1.1 定制类
1.1.1 __str__
>>> class Student(object):
... def __init__(self, name):
... self.name = name
...
>>> s = Student(‘daidai‘)
>>> s.name
‘daidai‘
>>> Student(‘daidai‘).name
‘daidai‘
>>> print(Student(‘daidai‘)) --发现这样打印并不好看
<__main__.Student object at0x2ac5ebc99128>
>>> class Student(object):
... def __init__(self, name):
... self.name = name
... def __str__(self):
... return ‘Student object (name: %s)‘ %self.name
...
>>> print(Student(‘daidai‘))
Student object (name: daidai)
>>> s = Student(‘daidai‘)
>>> s --指向变量后,仍然不好看
<__main__.Student object at0x2ac5ebc99160>
>>> s.name
‘daidai‘
将__str__同时指向__repr__
>>> class Student(object):
... def __init__(self, name):
... self.name = name
... def __str__(self):
... return ‘Student object (name: %s)‘ % self.name
... __repr__ = __str__
...
>>> print(Student(‘daidai‘))
Student object (name: daidai)
>>> s = Student(‘daidai‘)
>>> s.name
‘daidai‘
>>> s
Student object (name: daidai)
1.1.2 __iter__
如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的__next__()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。
以斐波那契数列为例。
>>> 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 > 10000: #退出循环条件
... raiseStopIteration();
... return self.a #返回下一个值
...
>>> for n in Fib():
... print(n)
...
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
1.1.3 __getitem__
上述Fib实例感觉和list类似,但是并不能通过下标来取元素。
通过__getitem__方法就可以。
>>> 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[4]
5
>>> f[88]
1779979416004714189
1.1.4 __getattr__
正常情况下,当我们调用类的方法或属性时,如果不存在,就会报错。
>>> class Student(object):
... def __init__(self):
... self.name = ‘daidai‘
...
>>> s = Student()
>>> print(s.name)
daidai
>>> print(s.score)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: ‘Student‘ object has noattribute ‘score‘
加上__getattr__动态返回属性值
>>> class Student(object):
... def __init__(self):
... self.name = ‘daidai‘
... def __getattr__(self, attr): --当输入score不存在时,python动态调用这个方法
... if attr == ‘score‘:
... return 98
...
>>> s = Student()
>>> s.name
‘daidai‘
>>> s.score
98
__getattr__返回函数也是可行的
>>> class Student(object):
... def __getattr__(self, attr):
... if attr == ‘age‘:
... return lambda : 24
...
>>> s = Student()
>>> s.age
<functionStudent.__getattr__.<locals>.<lambda> at 0x2ac5ebc8e730>
>>> s.age()
24
只有在没有找到属性的情况下,才调用__getattr__,已有的属性,比如name,不会在__getattr__中查找。
>>> class Student(object):
... def __getattr__(self, attr):
... if attr == ‘age‘:
... return lambda : 24
... raise AttributeError(‘\‘Student\‘ object has no attribute \‘%s\‘‘ %attr)
...
>>>
>>> s = Student()
>>> s.name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __getattr__
AttributeError: ‘Student‘ object has noattribute ‘name‘
>>> s.age
<functionStudent.__getattr__.<locals>.<lambda> at 0x2ac5ebc8e488>
>>> s.age()
24
1.1.5 __call__
__call__方法能实现直接在实例本身上调用。
>>> class Student(object):
... def __init__(self, name):
... self.name = name
... def __call__(self):
... print(‘My name is %s.‘ % self.name)
...
>>> s = Student(‘daidai‘)
>>> s
<__main__.Student object at0x2ac5ebc99748>
>>> s() --直接实例对象调用
My name is daidai.
可通过callable判断对象是否可调用
>>>callable(Student(‘daidai‘))
True
>>> callable(max)
True
>>> callable((1, 2, 3))
False
>>> callable(‘str‘)
False
__call__也可传入参数
>>> class Student(object):
... def __init__(self, name):
... self.name = name
... def __call__(self, others):
... print(‘My name is %s, %s‘ %(self.name, others))
...
>>>
>>> s = Student(‘daidai‘)
>>> s(‘so handsome.‘)
My name is daidai, so handsome.