5 继承
继承语法
# 定义类
class C:
pass
# 继承类
class CC(C):
pass
# 继承模块类
class CCC(inheritance.MC):
pass
在解析属性引用时,如果请求属性没有在类中被找到,将会在基类中继续搜索。如果基类从其它类中派生而来,此过程会被递归应用。
派生类会重写基类方法。由于在调用相同对象中的其他方法时,方法没有特别的权限,所以一个基类的方法在调用定义在相同基类中的其他方法时,可能会调用到重写此方法的派生类中的方法。
派生类重写基类方法
# 定义基类
class MC:
def fff(self):
print "This is MC"
# 定义派生类(扩展基类方法)
class CC(MC):
def fff(self):
MC.fff(self)
print "This is Cc"
判断继承内置函数
# 判断实例是否由指定类派生而来
print isinstance(x, int)
# 判断类是否由指定类派生而来
print issubclass(CC, MC)
5.1 多重继承
Python支持有限形式的多重继承。
import base
class A:
def aa(self):
print "This is A"
class B:
def bb(self):
print "This is B"
class C(A, B, base.Base):
def cc(self):
print "This is C"
与只继承一个类相比,唯一的规则是深度优先,由左到右。
方法解析顺序可以动态改变以支持对super()的协同调用。
由于所有多重继承的情况都表现出菱形关系,所以动态顺序顺序必要的。(至少一个双亲类可以通过由底层类出发的多条路径访问。)
为了防止基类被访问超过一次,动态算法线性化搜索顺序,以一种保持每个类指定的从左到右顺序,只调用每个双亲一次,并且不变(即类可以在不影响其双亲优先度的情况下子类化)的方法达成。
6 私有变量与类局部引用
Python中不存在“私有”实例变量。
Python中有一个通用约定:以下划线为前缀的名称应该被看作是API的非公开部分。
由于存在类私有成员的有效用例(即避免名称与子类中定义的名称冲突),存在对命名修改机制的有限支持。
任何形式为__spam(开头至少两个下划线,结尾最多一个下划线)的标识符会被文本替换为_classname__spam,其中classname是当前类名。只要出现在类定义中,就可以在不考虑标识符句法位置的情况下,完成修改。
命名修改有助于子类重写方法时不会破坏内部类方法调用。
注意,传递给exec()、eval()或execfile()的代码不会将调用者的类视为当前类,这一点类似global语句的效果。
7 碎片补充
# 使用类绑定一组数据名称
class C:
pass:
c = C()
c.n = 'Jo'
c.j = 123
需要特殊抽象数据类型的一段Python代码可以被传入一个模仿数据类型方法的类。
实例方法对象也具有属性。
# 定义类
class CC:
def ff(self):
print "fff"
# 实例化
x = CC()
# 获取实例对象
x.ff.im_self
# 获取方法对应的函数对象
x.ff.im_func
8 异常也是类
用户定义的异常由类标识。使用此机制可以创建异常的扩展架构。
# raise语句
class B:
pass
class C(B):
pass
class D(C):
pass
for c in [B, C, D]:
try:
raise c()
except D:
print "D"
except C:
print "C"
except B:
print "B"
如果异常与except子句中的类相同或是它是异常的基类,异常与except子句中类兼容。
如果一个未处理异常的错误信息没有被打印,异常的类名将会被打印,然后是冒号与空格,最后是使用内置函数str()转化为字符串的实例。
9 迭代器
迭代过程中,for语句调用容器对象的iter()。此函数返回一个迭代器对象,此对象定义了一次访问容器中一个元素的方法next()。当没有元素时,next()提出了StopIteration异常,此异常告知for循环终止。
在类中添加迭代行为,需要定义__iter__()方法,返回一个具有next()方法的对象,也可以在类中同时定义next(),然后令__iter__()返回self。
class Reverse:
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def next(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
10 生成器
生成器是创建迭代器的简单有效的工具。它们想常规函数一样使用,但是使用yield语句返回数据。每次调用next(),生成器都会从中断处继续(它会记住所有的数据值与最后执行的语句)。
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
for char in reverse('sdgaf'):
print char
生成器会自动创建__iter__()与next()方法。
局部变量与执行状态会在调用之间自动保存。这就省略了self.index与self.data的使用,代码更整洁。
当生成器终止时,它会自动提出一个StopIteration。
11 生成器表达式
一些简单的生成器可以使用类似列表推导的语法编码为表达式,不过使用括号代替方括号。这些表达式被设计为用于生成器通过封闭函数立即使用的情况。生成器表达式比完整的生成器定义更紧凑但功能较少,与等价的列表推导式相比,更具内存友好性。
sum(i * i for i in range(10))