如果一个类包含了__iter__方法,而且该方法返回了一个包含__next__方法的对象,即为迭代器
# 示例1,返回一个迭代对象 class A: def __iter__(self): return list('abcd').__iter__() # 示例2 自身可迭代 class A: def __iter__(self): self.data = list('abcd') return self def __next__(self): # 注意 try: return self.data.pop(0) except IndexError: raise StopIteration # 扩展,利用生成器快速实现元素迭代访问,缺点是调用需要A().travel() class A: def travel(self): for i in list('abcd'): yield i
通过实现运算符,可以实现开起来比较直观的程序
参见:https://docs.python.org/zh-cn/3/library/operator.html#module-operator
''' - __lt__() < - __le__() <= - __gt__() > - __ge__() >= - __eq__() = - ... '''
注意:实例查找通过命名空间链进行扫描,数据描述器的优先级最高,其次是实例变量、非数据描述器、类变量,最后是 getattr() (如果存在的话)。
区分 getattr、setattr 与 描述器
import os class DirectorySize: def __get__(self, obj, objtype=None): # 计算文件夹中文件的数量 return len(os.listdir(obj.dirname)) class Directory: size = DirectorySize() # 访问该属性,即可获得文件夹中文件的数量 def __init__(self, dirname): self.dirname = dirname # Regular instance attribute
通过属性托管,实现一些附加功能,比如属性访问日志或者属性校验等
class Number: def __set_name__(self, owner, name): # 在Person中定义属性时调用,定义了一个私有名字 self.private_name = '_' + name def __get__(self, obj, objtype=None): # 在Person对象调用age时调用 return getattr(obj, self.private_name) def __set__(self, obj, value): # 在Person对象为age赋值时调用,验证赋值属性 self.validate(value) setattr(obj, self.private_name, value) def validate(self, value): if not isinstance(value, (int, float)): raise TypeError(f'Expected {value!r} to be an int or float') class Person: age = Number() def __init__(self, age): self.age = age