特点:
特殊方法定义在class内
不需要直接调用
Python的某些函数或操作附会调用对应的特殊方法
print
python把任意变量变成str,因为任意数据类型的实例都有一个特殊方法 __str__()
__str__()用于显示给用户,而__repr__()用于显示给开发人员。
__repr__的目标是准确性,%r打印时能够重现它所代表的对象
__str__的目标是可读性,%s
import datetime
d = datetime.date.today()
print "%s" % d
print "%r" % d
2015-12-23
datetime.date(2015, 12, 23)
对 int、str 等内置数据类型排序时,Python的 sorted() 按照默认的比较函数 cmp 排序,但是,如果对一组类的实例排序时,就必须提供我们自己的特殊方法 __cmp__()
sorted默认由小到大,cmp()
sorted(iterable, cmp=None, key=None, reverse=False)
类实现了__cmp__()方法,__cmp__用实例自身self和传入的实例 s 进行比较,如果 self 应该排在前面,就返回 -1,如果 s 应该排在前面,就返回1,如果两者相当,返回 0
修改 Student 的 __cmp__ 方法,让它按照分数从高到底排序,分数相同的按名字排序
class Student(object):
def __init__(self,name,score):
self.name = name
self.score = score
def __str__(self):
return '(%s:%s)' % (self.name,self.score)
def __cmp__(self,s):
if self.score == s.score:
return cmp(self.name,s.name)
return -cmp(self.score,s.score)
L = [Student('Tim',79),Student('Bob',82),Student('Tom',99)]
print sorted(L)
如果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。类必须提供一个特殊方法__len__(),它返回元素的个数。
打印斐波那契数列,并返回数列和个数
class Fib(object):
def __init__(self,num):
a,b,L = 0,1,[]
for i in range(10):
L.append(a)
a,b = b,a+b
self.num = L
def __str__(self):
return str(self.num)
__repr__ = __str__
def __len__(self):
return len(self.num)
f = Fib(10)
print f
print len(f)
用于有理数的运算
def gcd(a,b):
if b == 0:
return a
return gcd(b,a%b)
class Rational(object):
def __init__(self,p,q):
self.p = p
self.q = q
#'+'
def __add__(self,r):
return Rational(self.p*r.q+self.q*r.p,self.q*r.q)
#'-'
def __sub__(self,r):
return Rational(self.p*r.q-self.q*r.p,self.q*r.q)
#'*'
def __mul__(self,r):
return Rational(self.p*r.p,self.q*r.q)
#'/'
def __div__(self,r):
return Rational(self.p*r.q,self.q*r.p)
def __str__(self):
g = gcd(self.p,self.q)
return '%s/%s' % (self.p/g,self.q/g)
__repr__ = __str__
r1 = Rational(1,2)
r2 = Rational(1,4)
print r1 + r2
print r1 - r2
print r1 * r2
print r1 / r2
用装饰器(@property)函数把 get/set 方法“装饰”成属性调用
@property—这是关键字,固定格式,能让方法当“属性”用。
@score.setter—前面的”score”是@property紧跟的下面定义的那个方法的名字,”setter”是关键字,这种“@+方法名字+点+setter”是个固定格式与@property搭配使用。
class Student(object):
def __init__(self,name,score):
self.name = name
self.__score = score
@property
def score(self):
return self.__score
@score.setter
def score(self,score):
if score < 0 or score > 100:
raise ValueError('invalid score')
self.__score = score
@property
def grade(self):
if self.__score < 60:
return 'C'
if self.__score < 80:
return 'B'
return 'A'
s = Student('Tom',80)
print s.grade
s.score = 62
print s.grade
s.score = 98
print s.grade
由于Python是动态语言,任何实例在运行期都可以动态地添加属性。
如果要限制添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的__slots__来实现。
顾名思义,__slots__是指一个类允许的属性列表
class Student(object):
__slots__=('name','gender','score')
def __init__(self,name,gender,score):
self.name = name
self.score = score
self.gender = gender
__slots__的目的是限制当前类所能拥有的属性,如果不需要添加任意动态的属性,使用__slots__也能节省内存。
在Python中,函数其实是一个对象.所有的函数都是可调用对象。一个类实例也可以变成一个可调用对象,只需要实现一个特殊方法__call__()。
class Fib(object):
def __call__(self,num):
a,b,L = 0,1,[]
for n in range(num):
L.append(a)
a,b = b,a+b
return L
f = Fib()
print f(10)