Python 定制类 特殊方法
1、特殊方法
定义在class中
不需要直接调用,python的某些函数或操作符会自动的调用对应的特殊方法。
如定义了person类,使用print p 语句打印person类的实例时,就调用了特殊方法__str__()
此时就需要在person类中实现这个方法。
使用特殊方法时注意:
只需要编写用到的特殊方法
有关联性的特殊方法都必须实现(如__getattr__,__setattr__,delattr__)
2、python中 __str__和__repr__
__str__()用于显示给用户,而__repr__()用于显示给开发人员。
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) __repr__ = __str__ #直接让repr和str相同
定义了repr函数后,在调试时直接向命令行输入p即可输出person的信息,否则会输出
<__main__.Person object at 0x0000000002E66C88>
__str__和__repr__函数会被子类继承。
3、python中 __cmp__
为了对对象进行排序,可以使用函数sorted函数,前提是设置了类的__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) __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) [(Alice: 77), (Bob: 88), (Tim: 99)]
4、python中 __len__
调用len()返回实例的长度.
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) 3
任务:
斐波那契数列是由 0, 1, 1, 2, 3, 5, 8...构成。
请编写一个Fib类,Fib(10)表示数列的前10个元素,print Fib(10) 可以打印出数列的前 10 个元素,len(Fib(10))可以正确返回数列的个数10。
代码1:(参考代码)
可以使用str()将整型列表转化为字符串。
class Fib(object):
def __init__(self, num):
a, b, L = 0, 1, []
for n in range(num):
L.append(a)
a, b = b, a + b
self.numbers = L
def __str__(self):
return str(self.numbers)
__repr__ = __str__
def __len__(self):
return len(self.numbers)
f = Fib(10)
print f
print len(f)
class Fib(object): def __init__(self, num): self.num = num def __str__(self): if(self.num==1): return "[0]" elif(self.num==2): return "[0,1]" else: fib_str = "[0," fib=[0,1] for k in range(2,self.num+1): fib_str = fib_str+ str(fib[k-1]) + "," fib.append(fib[k-1]+fib[k-2]) return fib_str[:-1]+']' def __len__(self): return self.num f = Fib(10) print f print len(f)
5、python中数学运算(运算符重载)
例:有理数可以用p/q表示,其中p和q都是整数。
调用求最大公约数的gcd函数(递归):
欧几里得定理:若a=b*r+q,则 GCD(a,b)=GCD(b,q)
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-r.p*self.q,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
6、python中类型转换
__int__ 和 __float__方法实现类型转换,
__str__ 方法也可以看做是一种类型转换。
class Rational(object): def __init__(self, p, q): self.p = p self.q = q def __int__(self): return self.p // self.q def __float__(self): return float(self.p)/float(self.q) print float(Rational(7, 2)) print float(Rational(1, 3))
7、python中 @property(装饰器函改写set和get方法)
@property 修饰方法后即是get方法。
“@+方法名字+点+setter”是个固定格式与@property搭配使用,set方法。
如果没有定义set方法,就不能对“属性”赋值,这时,就可以创建一个只读“属性”。
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
8、python中 __slots__ 属性限制
__slots__规定了一个类允许的属性列表。不允许添加列表外的属性。
class Student(object): __slots__ = ('name', 'gender', 'score') def __init__(self, name, gender, score): self.name = name self.gender = gender self.score = score
强行添加grade属性会报错。
>>> s = Student('Bob', 'male', 59) >>> s.name = 'Tim' # OK >>> s.score = 99 # OK >>> s.grade = 'A' Traceback (most recent call last): ... AttributeError: 'Student' object has no attribute 'grade'
9、python中__call__ 把类实例变成可调用对象
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') My name is Bob... My friend is Tim...
第四节的斐波那契数列问题,可以改用call实现。
class Fib(object): def __call__(self,num): a=0 b=1 L=[] for n in range(1,num+1): L.append(a) temp = b b = a + b a = temp return L f = Fib() print f(10)
参考代码:
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)
注意代码中 高亮语句,使用参考代码的写法,就省去了一个中间变量。