1
__str__() 和 __repr__()
修改打印一个实例时的默认值。
修改前:
>>> class Student(object):
... def __init__(self,name):
... self.name = name
...
>>> s=Student('syztoo')
>>> print(s)
<__main__.Student object at 0x7fde19208128>
>>> s
<__main__.Student object at 0x7fde192082b0>
定制 __str__() 方法:
>>> class Student(object):
... def __init__(self,name):
... self.name = name
... def __str__(self):
... return 'Student object (name: %s)' % self.name
...
>>> s=Student('syztoo')
>>> print(s)
Student object (name: syztoo)
>>> s
<__main__.Student object at 0x7fde192082b0>
定制 __repr__() 方法:
>>> class Student(object):
... def __init__(self,name):
... self.name = name
... def __str__(self):
... return 'Student object (name: %s)' % self.name
... __repr__ = __str__
...
>>> s=Student('syztoo')
>>> print(s)
Student object (name: syztoo)
>>> s
Student object (name: syztoo)
2
__iter__()
如果一个类想被用于 for ... in
循环,类似 list 或 tuple 那样,就必须实现一个 __iter__()
方法,该方法返回一个迭代对象,然后,Python 的 for 循环就会不断调用该迭代对象的 __next__()
方法拿到循环的下一个值,直到遇到 StopIteration
错误时退出循环。
>>> class Fib():
... def __init__(self):
... self.a,self.b = 0,1
... def __iter__(self):
... return self
... def __next__(self):
... self.a,self.b = self.b,self.a+self.b
... if self.a > 1000:
... raise StopIteration()
... 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
3
__getitem__(self,key)
使用 __iter__() 方法定制类后,虽然类可以作用于 for 循环,但并不能像列表那样通过索引取出元素,比如:
>>> Fib()[2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'Fib' object does not support indexing
提示类对象不支持索引。
可以使用 __getitem__(self,key)
方法为类定制索引,该方法需要一个固定参数key(及索引,从0开始),该方法返回key对应的值。
>>> class Fib(object):
... def __getitem__(self,key):
... a,b = 1,1
... for i in range(key):
... a,b = b,a+b
... return a
...
>>> f = Fib()
>>> f[0]
1
>>> f[100]
573147844013817084101
定制切片和步长功能:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
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
step = n.step
if start is None:
start = 0
a, b = 1, 1
L = []
for x in range(stop):
if step:
if x >= start and (x - start) % step == 0:
L.append(a)
else:
if x >= start:
L.append(a)
a, b = b, a + b
return L
f = Fib()
print(f[100])
print(f[10:20])
print(f[:10])
print(f[10:20:2])
4
__getattr__()
class Student(object):
def __init__(self):
self.name = 'Michael'
def __getattr__(self, attr):
if attr=='score':
return 99
当我们调用类不存在的属性时,Python解释器会尝试从 __getattr__() 方法中获取该属性,如果 __getattr__() 方法中,有定义该属性,那么我们有机会返回该属性的值:
>>> s = Student()
>>> s.name
'Michael'
>>> s.score
99
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'
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('Michael')
>>> s() # self参数不要传入
My name is Michael.
__call__()
还可以定义参数:
class Chain(object):
def __init__(self, path=''):
self.__path = path
def __getattr__(self, path):
return Chain('%s/%s' % (self.__path, path))
def __call__(self, path):
return Chain('%s/%s' % (self.__path, path))
def __str__(self):
return self.__path
__repr__ = __str__
>>> print(Chain().users('michael').repos)
/users/michael/repos