Python中的面向对象编程

Published: 29 Dec 2013 Category: 编程

Python的面向对象编程在本质上和其他的编程语言类似,也有继承、封装、初始化等概念。 主要介绍一些不同的地方和实现方式。

属性就是属于一个对象的数据或者函数元素,可以通过.来访问。

和类/实例相关的属性包括类属性、实例属性

类属性

类属性相当于静态数据和函数。类属性与其被定义的类绑定

类的数据属性:静态变量。直接在类中定义。

方法:成员函数。虽然成员函数只能通过实例对象进行调用,但是方法属于类的固有属性。

特殊的类属性: - __name__:名字(字符串) - __doc__:文档字符串 - _base__:父类元组 - __dict__:类所有的属性 - __module__:所在的模块 - __class__:实例所对应的类

实例

Python通过调用类来创建实力(就像调用函数一样)。

构造器方法:__init__()

当类被调用,第一步是创建实例对象。一旦对象成功创建,Python就回去检查是否实现了__init__()方法,如果定义了就会调用。

这个方法其实并没有构造一个实例对象,所以不能返回任何对象,只能返回None;

更底层的构造器方法:__new__()

Python可以对内建类型(如字符串、数字)进行派生,因此需要一个实例化不可变对象的方法。__new__()必须返回一个合法的实例,然后调用__init__()就可以将这个实例传给它。

析构器方法:__del__() Python具有垃圾回收机制,这个函数知道所有的实例对象引用都被清除才执行。很少使用,因为实例很少被显示释放。

实例属性

实例仅拥有数据属性。按照上文所说,虽然方法只能通过实例调用,但是它属于类。

Python中的特点:允许在运行时对实例的属性进行动态创建。当然,这个特点要谨慎使用。

一般来说,在构造器__init__()中对实例属性进行设置是最好的实践方法。同时,也可以在构造器中使用缺省参数。

类属性 vs 实例属性

类和实例都是名字空间。类是类属性的名字空间,实例是实例属性的名字空间。

方法

  • 方法是类内部定义的函数。
  • 方法只有在其所属的类拥有实例时,才能被调用。
  • 任何一个方法定义中的第一个参数都是变量self。相当于this指针,代表着调用此方法的实例对象。

调用绑定方法:使用实例化对象。实例化对象作为self参数默认传递进去,不需要明确传入。

调用非绑定方法:当没有实例化对象的时候,比如子类调用父类的函数,那么就要明确的将self参数传入禁区。

静态方法和类方法

通常的方法需要一个实例(self)作为一个参数,而对于类方法,需要类而不是实例作为第一个参数,并且由解释器传递给方法。类不需要特别的命名,一般使用cls作为传递进去的类的变量名字。

一般使用@saticmethod函数修饰符来完成静态方法的声明,也可以使用内建函数,不过不优雅不推荐。

继承和派生

Python中的继承通过在在类定义类名后使用()定义父类。

__bases__类属性:包含父类集合的元组。

继承覆盖方法

class P(object):
    def foo(self):
        print 'Hi, I am P-foo()
class C(P):
    def foo(self):
        print 'Hi, I am C-foo()'
>>>c=C()
>>>c.foo()
Hi, I am C-foo()

C的对象如何使用被覆盖的基类方法?可以调用未绑定的基类方法,明确给出子类的实例。

>>>P.foo(c)
Hi , I am P-foo()

未绑定的方法调用常常用于子类方法调用基类方法,如:

class C(P):
    def foo(self):
        P.foo(self)
        print 'Hi, I am C-foo'
##或者使用super()内建方法,这是一个更好的办法
class C(P):
    def foo(self):
        super(C,self).foo()
        print 'Hi, I am C-foo'

使用super的好处是不需要明确给出父类的名字,进行了解耦。

重写init就不会自动调用基类的__init__()

如果派生类不重写__init__(),那么它会被继承并自动调用。如果重写了该函数,那么基类的__init__()不会被自动调用,要通过非绑定方法调用手动调用。

多继承问题 多继承会导致很多问题,尽量不用使用。

先记住:多继承的话,如class C(P1,P2):,前面的P1和P2如果有相同名称的函数,那么P1的方法会覆盖P2的方法。

super()及其他内建函数

super():用于找出相应的父类。一般情况,在子类想要调用父类的方法时只能通过非绑定的方法,而super()就是用来查找父类的属性。 issubclass():判断一个类是否是另一个类的子类或者子孙类。 isinstance():判断一个对象是否是一个类的实例。 hasattr(),getattr(),setattr(),delattr():操作对象的属性。这些函数不限于类和实例,可以在各种对象下工作。