定制类
.
-描述
看到形如__xxx__的变量或者函数名需要注意,这些在Python中是由特殊用途的
- __str __
例
class Student(object):
def __init__(self, name):
self.name = name
print(Stduent('Maybe')
输出
<__main__.Student object at 0x00000201FC958E48>
可以通过定义__str__()
方法,返回指定的字符串
class Student(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Student object (name:{})'.format(self.name)
print(Student('Maybe'))
输出
Student object (name:Maybe)
不过不适用print()函数,输出的实例还是没有改变
例
# Python交互环境
>>> class Student(object):
... def __init__(self, name):
... self.name = name
... def __str__(self):
... return 'Student object (name: %s)' % self.name
>>> s = Student('Michael')
>>> s
输出
<__main__.Student object at 0x00000201FC958E48>
因为直接显示变量调用的不是__str__()
,而是__repr__()
,两者的区别是__str__()
返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串
偷懒写法
class Student(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Student object (name={}').format.name
__repr__ = __str__
.
- __iter __
如果一个类想被用于for…in循环,类似list或tuple,就必须实现一个__iter__()
方法,该方法返回一个迭代对象
例
# 斐波那契数列
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 > 100:
raise StopIteration()
return self.a # 返回下一个值
for i in Fib():
print(i)
输出
1
1
2
3
5
8
13
21
34
55
89
.
- __getitem __
要实现像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()
print(f[3])
输出
3
.
- __getattr __
正常情况下,调用类的方法或属性时,如果不存在,就会报错。可以通过写一个__getattr__()
方法,动态返回一个属性
例
class Student(object):
def __init__(self):
self.name = 'Maybe'
def __getattr__(self, attr):
if sttr == 'score':
return 100
s = Student()
print(s.name)
print(s.score)
输出
Maybe
100
也可以返回函数
class Student(object):
def __getattr__(self, attr):
if attr == 'age':
return lambda:25
s = Student()
print(s.age()) # 调用方式改为调用函数
输出
25
注意:只有没有找到属性的情况下,才调用__getattr__
,已有的属性,不会在__getattr__
中查找
定义的__getattr__默认返回值时None
例
class Student(object):
def __getattr__(self, attr):
if attr == 'age':
return lambda:25
s = Student()
print(s.abc) # abc属性不存在,返回None
输出
None
要让class只相应特定的几个属性,就按照约定,抛出AttributeError
的错误
class Student(object):
def __getattr__(self, attr):
if attr == 'age':
return lambda: 25
raise AttributeError('\'Student\' object has no attribute \'{}\''.format(attr))
s = Student()
print(s.abc)
输出
AttributeError: 'Student' object has no attribute 'abc'
应用场景
# 链式调用
class Chain(objcet):
def __init__(self, path=''):
self._path = path
def __getattr__(self, path):
return Chain('{}/{}'.format(self._path, path))
def __str__(self):
return self._path
__repr__ = __str__
print(Chain().status.user.timeline.list)
输出
/status/user/timeline/list
.
- __call __
任何类,只需要定义一个__call__()
方法,就可以直接对实例进行调用
class Student(object):
def __init__(self, name):
self.name = name
def __call__(self):
print('My name is {}.'.format(self.name))
s = Stduent('Maybe')
s()
输出
My name is Maybe.
判断一个对象是否能被调用使用Callable
class Student(object):
def __init__(self, name):
self.name = name
def __call__(self):
print('My name is %s.' % self.name)
print(callable(Student('Maybe')))
print(callable(max))
print(callable(list))
print(callable([1,2,3]))
输出
True
True
True
False