1. 程式人生 > >Python學習筆記——特殊方法

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)