这一章是相当复杂的一章。
第9章 魔法方法、特性和迭代器
1. 如果使用的不是python3
使用py -3 无需显式继承object
2. 构造函数(constructor)
创建构造函数:将方法名称改成__init__
对象创建时自动调用。
1.重写普通方法,子类将覆盖父类(或称超类)方法
重写构造函数时,要调用父类的构造函数来帮助初始化对象。
2.调用未关联的父类构造函数#如果使用的新类,可跳过这里,看3.使用函数super
通过类调用方法,没有实例与其关联。
举例:已有Bird类。
SongBird继承Bird
class SongBird(Bird):
def __init__(self):
Bird.__init__(self)
self.sound = 'Squawk!'
#...
Bird.__init__(self) 是通过类Bird调用方法
而没有和实例相关联。
3.使用函数super
只适用于新式类。
将当前类和当前实例作为参数,对其返回的对象调用方法时,调用的将是父类的方法。
举例:
上面的SongBird 的构造函数可以写出
super(SongBird, self).__init__()
py -3中可以不提供参数。于是可写成:
super().__init__()
#使用函数super比 未关联构造函数更好
3. 元素访问
1.基本的序列和映射协议
序列和映射 是元素(item)的集合.实现它们的基本行为,不可变对象要2个方法,可变对象要4个。
__len__(self):返回项数
__getitem__(self,key): 返回和键相关联的值
__setitem__(self,key,value):设置值,只有可变对象需要
__delitem__(self, key):删除,在对象的组成部分使用__del__时调用,只有可变对象需要
2.从list、dict和str派生
4.其他魔法方法
5.特性(property)
通过存取方法定义的属性通常称为特性。
举例: 有1个Recttangle类
class Rectangle:
def __init__(self):
self.width = 0
self.height = 0
def set_size(self, size):
self.width, self.height = size
def get_size(self):
return self.width, self.height
它有属性宽(width)和高(height)
而 set_size 和get_size 是假想属性 size 的存取方法,size属性是有width和 height 组成的元组.
python可隐藏存取方法,让这个属性看起来是常规的属性。
通过存取方法定义的属性叫特性(property)
1.函数property
例:在上面Rectangle类下面加上一行:
size = property(get_size,set_size)
这样就能像对待width、height一样对size了。
r = Rectangle()
r.size
property参数
fget,fset,fdel,doc
2.静态方法和类方法(很少用到它们)
静态方法的定义没有参数self,可以通过类调用
类方法的定义中包含类似self的参数,通常是cls,类方法可以通过对象调用,但参数cls将关联到类
class MyClass:
def smeth():
print("This is a static method")
smeth = staticmethod(smeth)
def cmeth(cls):
print("This is a class method of", cls)
cmeth = classmethod(cmeth)
装饰器:用于包装方法、对象
class MyClass:
@staticmethod
def smeth():
print("This is a static method")
@classmethod
def cmeth(cls):
print("This is a class method of", cls)
3.__getattr__、__setattr__等方法
拦截对 对象属性的访问。
用途之一是实现特性。
__getattribute__(self, name):在属性被访问时自动调用
__getattr__(self, name):访问对象没有的属性时调用
__setattr__(self, name, value):给属性赋值时调用
__delattr__(self, name): 删除属性
例子:
class Rectangle:
def __init__(self):
self.width = 0
self.height = 0
def __setattr__(self,name,value):
if name == 'size':
self.width, self.height = value
else:
self.__dict__[name] = value
def __getattr__(self,name):
if name == 'size':
return self.width,self.height
else:
raise AttributeError()
6.迭代器
1.迭代器协议
迭代(iterate)意味重复多次,就像循环。
对实现了方法__iter__的对象可以进行迭代。
__iter__ 返回一个迭代器,它是包含 __next__的对象。
调用__next__时,迭代器应返回下一个值,若没有可返回的值,将引发StopIteration异常
#可使用next(it)替换it.__next__()
例子:
class Fibs:
def __init__(self):
self.a = 0
self.b = 1
def __next__(self):
self.a, self.b = self.b, self.a + self.b
return self.a
def __iter__(self):
return self
2.从迭代器创建序列
class TestIterator:
value = 0
def __next__(self):
self.value += 1
if self.value > 10: reise StopIteration
return self.value
def __iter__(self):
return self
ti = TestIterator()
list(ti)
7.生成器
生成器很复杂。
而生成器并非是必需,可以不使用生成器。
1.创建生成器
包含yield语句的函数被称为 生成器。
生成器不是使用return返回一个值,而是可以生成多个值,每次一个。
每次使用yield生成一个值后,函数都将冻结,即在此停止执行,等待被重新唤醒。被重新唤醒后,函数将从停止的地方开始继续执行。
例子:
def flatten(nested):
for sublist in nested:
for element in sublist:
yield element
2.递归式生成器
def flatten(nested):
try:
for sublist in nested:
for element in flatten(sublist):
yield element
except TypeError:
yield nested
3.通用生成器
4.生成器的方法
外部可访问生成器的方法send。
生成器 yield返回一个值(通过send发送给外部)
5.模拟生成器