1.__len__()
2.__str__() 美化实例调用
>>> class Student(object): ... def __init__(self, name): ... self.name = name ... >>> print(Student('Michael')) <__main__.Student object at 0x109afb190> --------------------------------------- >>> class Student(object): ... def __init__(self, name): ... self.name = name ... def __str__(self): ... return 'Student object (name: %s)' % self.name ... >>> print(Student('Michael')) Student object (name: Michael)
3.__repr__() 美化直接打印出的实例变量
>>> s = Student('Michael') >>> s <__main__.Student object at 0x109afb310> --------------------------------------------- class Student(object): def __init__(self, name): self.name = name def __str__(self): return 'Student object (name=%s)' % self.name __repr__ = __str__
4.__iter__()+__next__() 迭代器协议将类变为可迭代对象(用于for-in)
class Fib(object): def __init__(self): self.a, self.b = 0, 1 # 初始化两个计数器a,b def __iter__(self): return self # 实例本身就是迭代对象,故返回自己 def __next__(self): self.a, self.b = self.b, self.a + self.b # 计算下一个值 if self.a > 100000: # 退出循环的条件 raise StopIteration() return self.a # 返回下一个值 --------------------------------- >>> for n in Fib(): ... print(n) ... 1 1 2 3 5 ... 46368 75025
5.__getitem__() 使对象实现迭代功能
类实例按下标存取(像list)
class Fib(object): def __getitem__(self, n): a, b = 1, 1 for x in range(n): a, b = b, a + b return a #现在,就可以按下标访问数列的任意一项了: >>> f = Fib() >>> f[0] 1 >>> f[1] 1 >>> f[2] 2 >>> f[3] 3 >>> f[10] 89 >>> f[100] 573147844013817084101
切片:__getitem__()
传入的参数可能是一个int,也可能是一个切片对象slice
,所以要做判断
class Fib(object): def __getitem__(self, n): if isinstance(n, int): # n是索引 a, b = 1, 1 for x in range(n): a, b = b, a + b return a if isinstance(n, slice): # n是切片 start = n.start stop = n.stop if start is None: start = 0 a, b = 1, 1 L = [] for x in range(stop): if x >= start: L.append(a) a, b = b, a + b return L #现在试试Fib的切片: >>> f = Fib() >>> f[0:5] [1, 1, 2, 3, 5] >>> f[:10] [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
与之对应的是__setitem__()
方法,把对象视作list或dict来对集合赋值。最后,还有一个__delitem__()
方法,用于删除某个元素。
总之,自定义类和Python自带的list、tuple、dict没什么区别,这完全归功于动态语言的“鸭子类型”,不需要强制继承某个接口。
6.__getattr__ 动态返回属性
类中找属性--有,返回
没有,到__getattr__找--有,返回
没有,报错处理AttributeError
class Student(object): def __init__(self): self.name = 'Michael' def __getattr__(self, attr): if attr=='score': return 99 ------------------------------- >>> s = Student() >>> s.name 'Michael' >>> s.score 99
#返回函数也是完全可以的: class Student(object): def __getattr__(self, attr): if attr=='age': return lambda: 25 #只是调用方式要变为: >>> s.age() 25
#属性限制 class Student(object): def __getattr__(self, attr): if attr=='age': return lambda: 25 raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
链式调用实例:
class Chain(object): def __init__(self, path=''): self._path = path def __getattr__(self, path): return Chain('%s/%s' % (self._path, path)) def __str__(self): return self._path __repr__ = __str__ ------------------------------- >>> Chain().status.user.timeline.list '/status/user/timeline/list'
7.__call__ 直接对实例调用
class Student(object): def __init__(self, name): self.name = name def __call__(self): print('My name is %s.' % self.name) ------------------------ >>> s = Student('Michael') >>> s() # self参数不要传入 My name is Michael.
__call__还可定义参数(将对象看成函数)
判断对象是否可调用callable()
>>> callable(Student()) True >>> callable(max) True >>> callable([1, 2, 3]) False >>> callable(None) False >>> callable('str') False
Python的class允许定义许多定制方法,可以让我们非常方便地生成特定的类。
本节介绍的是最常用的几个定制方法,还有很多可定制的方法,请参考Python的官方文档。