本章将首先熟悉pyhton中类的定义、创建并操作类实例对象的机制和写法。理解_init_,_new_,_del_的用法和在类生命周期中的调用时机。理解类和类实例对象之间的关系,熟悉类方法和静态方法的机制和写法,熟悉继承和派生的机制和写法。
面向对象中的基本概念无论在什么编程语言中都是相同的,如果没有接触过建议详细看13.1、13.2节、
在python中类的声明与函数声明很相似:
class ClassName(obj):
'class document'
class suite
类和函数都允许在他们的声明中创建函数、闭包或者内部函数。
最大的不同在于运行函数,而类会创建一个对象。类就像一个python容器类型。当你创建一个类,你就实际创建了一个你自己的数据类型。所以这个类的实例都是相似的,但类之间彼此是有区别的。
声明与定义类是同时进行的,python中并不支持C++中的纯虚函数(只定义不实现)。
属性就是属于另一对象的数据或函数元素,可以通过句点来访问。访问属性时,它同时也是对象,可以拥有自己的属性。
类的数据属性:类的变量,在类被创建后使用,类似于C++中的静态变量,它不依赖于任何实例,是与类对象绑定的。
方法:类中的方法,作为类定义的一部分定义函数。与C++不同的是,python中没有实例,方法是不能被调用的,方法必须绑定到一个实例中才能被使用。
要查看一个类拥有哪些属性,需要通过内建函数dir(MyClass)或查看_dict_属性。
在python中,对于任何类,都有以下特殊属性:
初始化类:与其他语言使用new关键字不同,python的方式更简单。
c1=c()
_init_():当类被调用,实例化的第一步就是创建实例对象,一旦对象创建了,python检查是否实现了_init_()方法。默认情况下,如果没有定义或覆盖init,则不会进行任何特别的操作。
_new_():与init相比,new方法更像是一个真正的构造器。new的调用会在init之前进行,主要是用来实例化不可变对象,例如派生字符串、数字等等。
_del_():解构器方法,由于python具有垃圾回收机制(引用计数),这个函数要直到该实例对象所有的引用都被清除掉后才执行。当_del_没有在预期的时候被调用,则说明实例对象由于某些原因,其引用计数不为0,有可能还有对其的引用活着。
同样dir()也可以用于查看实例的属性。
类属性仅是与类相关的数据值,和实例属性不同,类属性和实例无关。类和实例都是名字空间。
简单来说类的属性改变,如果实例没有显式改变属性,则实例属性也改变。实例属性改变,但类的属性不发生改变。
class c:
foo=100
if __name__ == '__main__':
c1=c()
c2=c()
c.foo=200
print c1.foo #200
c1.foo=400
print c.foo #200
print c1.foo #400
类的绑定与方法的调用相关联。方法只有在有所属的类时,才能被调用,被认为是已经绑定到实例。而没有实例的方法就是未绑定的。
self参数:相当于C++this指针。用于在类实例方法中引用方法所绑定的实例。self在每一个方法声明中都是作为第一个参数出现的。
与C++中的静态方法一样,它们仅是类中的函数,不需要通过实例也可以直接调用。
使用函数修饰符@加上staticmethod或classmethod就可以指定方法为静态或类方法。
class c:
foo=100
@staticmethod
def func():
print 'static func'
一个类被定义之后,目标就是把它当做一个模块来使用,并把这些对象嵌入到代码中,同其他数据类型一起使用。有两种方法可以在代码中利用类:组合和派生。
组合:例如对于地址簿类中有name、address、phone等不同的类,在将这些类的实例都放在地址簿类中时,就产生了一种has-a的关系,即为地址簿中有name、address等实例。
派生:当设计一个相同的类但有一些不同的功能时,派生就是更加好的选择。面向对象编程允许子类继承自父类,甚至多代之间继承。例如在我们需要同时创建客户地址簿和员工地址簿,它们之间会有大量重复的功能,所以可以是它们同时继承自地址簿类。
class parent()::
'parent class'
class child(parent):
'child is inherit from parent'
类继承就是描述基类的属性如何‘遗传’给派生类。一个子类可以继承它的基类的任何属性,不管是属性还是方法(_doc_文档字符串并不继承)。
如果父类没有属性,那么继承于父类的子类也没有属性。
如果子类重写了父类中的方法,那么子类将会重写这个方法。
如果想要继续调用父类的方法,则需要在子类重写的方法里显式的调用基类的方法,或者通过super()函数。
_init_方法被重写之后,子类只会调用子类的init函数。
默认情况下,属性在python中都是public的,类所在模块和导入了类所在模块的其他模块的代码都可以访问到。这部分会在下一章进行讨论。
在使用子类的时候,通常需要重写构造函数(有时候也需要保留父类的构造函数),在需要先使用父类构造函数的情况下,一般有两种解决方法:
# 1 直接调用父类的构造函数
class child:
def _init_(self):
parent._init_(self)
print 'child's init'
# 2 使用super
class child:
def _init_(self):
super(child,self)._init_()
print 'child's init'
下一章将是python基础学习的最后一章,模块的相关学习。