Python學習筆記——特殊方法
特殊方法
特點:
特殊方法定義在class內
不需要直接呼叫
Python的某些函式或操作附會呼叫對應的特殊方法
__str__和 __repr__
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)
__cmp__
對 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)
__len__
如果一個類表現得像一個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
用裝飾器(@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
__slots__
由於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__也能節省記憶體。
__call__
在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)