特殊方法简介
Python之所以能把把任意变量变成str输出,因为任何数据类型的实例都有一个特殊方法str()。
常用特殊方法举例
__str()__
如果要把一个类的实例变成str,需要实现特殊方法__str__(),
1 2 3 4 5 6 7 8 9
| class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender def __str__(self): return '(Person: %s, %s)' % (self.name, self.gender)
p = Person('Bob', 'male') print(p)
|
__cmp()__
对int、str等内置数据类型排序时,Python的sorted()函数按照默认的比较函数cmp排序,但是,如果对一组Student类的实例排序时,就必须实现特殊方法__cmp__(),
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Student(object): def __init__(self, name, score): self.name = name self.score = score def __str__(self): return '(%s: %s)' % (self.name, self.score) __repr__ = __str__
def __cmp__(self, s): if self.name < s.name: return -1 elif self.name > s.name: return 1 else: return 0
L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 77)] print sorted(L)
|
上述Student类实现了__cmp__()方法,__cmp__用实例自身self和传入的实例s进行比较,如果self应该排在前面,就返回-1,如果s应该排在前面,就返回1,如果两者相当,返回0。
注意: 如果list不仅仅包含Student类,则__cmp__可能会报错。Python3已经取消该函数。
__len()__
如果一个类表现得像一个list,要获取有多少个元素,就得用len()函数。要让len()函数工作正常,类必须提供一个特殊方法__len__(),它返回元素的个数。
例如,写一个Students类,把名字传进去,只要正确实现了__len__()方法,就可以用len()函数返回Students实例的“长度”,
1 2 3 4 5 6 7 8
| class Students(object): def __init__(self, *args): self.names = args def __len__(self): return len(self.names)
ss = Students('Bob', 'Alice', 'Tim') print len(ss)
|
__slots__
由于Python是动态语言,任何实例在运行期都可以动态地添加属性。
如果要限制添加的属性,例如,Student类只允许添加name、gender和score这3个属性,可以利用Python的__slots__来实现。__slots__是指一个类允许的属性列表,
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Student(object): __slots__ = ('name', 'gender', 'score') def __init__(self, name, gender, score): self.name = name self.gender = gender self.score = score
s = Student('Bob', 'male', 59) s.name = 'Tim' s.score = 99 .grade = 'A' Traceback (most recent call last): ... AttributeError: 'Student' object has no attribute 'grade'
|
__slots__的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用__slots__也能节省内存。slots定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。
__call()__
在Python中,函数其实是一个对象。如下,由于f可以被调用,所以,f被称为可调用对象。所有的函数都是可调用对象。
1 2 3
| f = abs print(f.__name__) print(f(-123))
|
一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()。该函数在调用类的实例时自动调用。把Person类变成一个可调用对象如下,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender
def __call__(self, friend): print('My name is %s...' % self.name) print('My friend is %s...' % friend)
p = Person('Bob', 'male') p('Tim')
|
单看p('Tim')无法确定p是一个函数还是一个类实例,所以,在Python中,函数也是对象,对象和函数的区别并不显著。