class语句
Class语句表面上看起来和其它OOP语言的工具类似。像def语句一样,class语句也是创建了一个类对象,并把该对象赋值给类名。在没有执行class语句之前,你的类都是不存在的。
class语句的一般形式:
class语句是复合语句,其缩进语句的主体一般都是出现在头一行下边。
class <name>(superclass,...):
data = value #类变量,被所有实例共享
def method(self,...):
self.member = value
在class顶层内赋值的变量名都成为类的变量,这个变量被所以该类的实例所共享(共享相同的一个内存)。
- 就像函数一样,class语句是本地作用域,由内嵌的赋值语句建立的变量名,就存在于这个本地作用域内。
- 就像模块内的变量名,在class语句内赋值的变量名会变成类对象中的属性。如果在类的实例中进行属性赋值,就会在实例中创建一个变量,这个变量就由实例所特有。
>>> class testdata:
... test=222
...
>>> a=testdata()
>>> b=testdata()
>>> c=testdata()
>>> a.test,b.test,c.test,testdata.test #都是使用的类变量
(222, 222, 222, 222)
>>> a.test=333 #实例中变量赋值
>>> a.test,b.test,c.test,testdata.test #改变的实例对象中的变量,类变量没有改变
(333, 222, 222, 222)
>>> testdata.test=444 #修改类变量
>>> a.test,b.test,c.test,testdata.test
(333, 444, 444, 444) #共享类变量的实例中,变量都发生了改变
>>>
方法
类中的定义的函数就称为方法,语法与函数很类似,唯一不同的就是方法的第一个参数总是会接受方法的调用对应的类的实例对象,按照惯例,第一个参数通常称为self(其实名字不重要,重要的是位置。)这个参数实现了一个钩子,从而返回调用类方法的实例对象。在子类中,也可以调用父类中的方法。
继承
之前讲过,在使用点运算时(object.attribute)Python内部实际上是去按照一定的规则去查找属性树,以取出对应的值。那么通常来说,各个命名空间的属性有如下规则:
- 实例的属性一般是又对类内的self属性(类创建的实例对象)进行运算而产生的
- 类属性是在定义类时,直接在类内通过赋值运算产生的。
- 超类的链接是在类的定义时,在首行内的括号中给出。
抽象类
与其他OOP编程一样,也可以在Python中实现抽象类,抽象类是会调用方法的类,但没有继承或定义该方法,而是期待该方法由子类填补。即**类的实现又子类来定义,而不是在超类中定义。**Python实现这种效果的方式很简单:
>>> class superclass:
... def test(self):
... assert False,'action must be defined' #或者定义为raise NotImplementedError('action must be defined')
...
>>> x=superclass()
>>> x.test() #不能由父类直接调用,而是由子类继承定义后调用。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in test
AssertionError: action must be defined
>>>
在Python3.0中,抽象类还可以使用关键字参数和特殊的语法装饰器来定义一个抽象类:
>>> from abc import ABCMeta,abstractmethod
>>> class Super(metaclass=ABCMeta): #关键字参数来声明这个是抽象类
... def delegate(self):
... self.action()
... @abstractmethod #声明是抽象方法
... def action(self):
... pass
...
>>> x=Super()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class Super with abstract methods action
>>> class sub(Super):
... pass
...
>>> x=sub()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class sub with abstract methods action
>>> class Sub(Super): #必须在子类中实现抽象方法后才能正常调用。
... def action(self):
... print('OK')
...
>>> x=Sub()
>>> x.delegate()
OK
>>> x.action()
OK
>>>