Python的class容許定義許多特殊方法,可讓咱們很是方便地生成特定的類。在類中應用或者重寫python的特殊方法,獲得的類,就是定製類。python
你們都知道print的用法。見下面例子shell
>>> lst = [2,3,4] >>> print lst [2, 3, 4] >>> class Animal(object): pass >>> a = Animal() >>> print a <__main__.Animal object at 0x01E6E990>
爲何print都能識別出lst和p的數據類型呢?app
當咱們執行以下代碼的時候,就知道爲何了?函數
>>> print lst.__str__ <method-wrapper '__str__' of list object at 0x01E641E8> >>> print a.__str__ <method-wrapper '__str__' of Animal object at 0x01E6E990>
__str__特殊方法,能識別出每個數據類型。若是但願類的實例print a 打印出 ‘object of Animal class’.怎麼辦?從新定義__str__方法。spa
>>> class Animal(object): def __str__(self): return 'object of Animal class' >>> a = Animal() >>> print a object of Animal class
可是有時候發現直接敲code
>>> a <__main__.Animal object at 0x01E6E990>
__str__不會被調用。由於當直接敲a這行代碼的時候,直接調用的並非__str__.而是__repr__.對象
>>> class Animal(object): def __str__(self): return 'object of Animal class' __repr__ = __str__ //偷懶一下 >>> a = Animal() >>> a object of Animal class
python的特殊方法不少,這裏就不作一一介紹。下面主要介紹 __slots__,__call__,@property用法。blog
python是一個動態語言,任何實例能夠再運行期間都能動態添加實例的屬性。可是有時候,想限制實例的添加屬性,就使用__slot__方法。見下面例子:繼承
>>> class Person(object): __slots__ = ('name','age')//限制只有name和age的屬性 def __init__(self,name,age): self.name = name self.age = age >>> p = Person('zhangsan',25) >>> p.age 25 >>> p.name 'zhangsan' >>> p.gender ='man'//直接動態賦屬性gender,會出現錯誤 Traceback (most recent call last): File "<pyshell#42>", line 1, in <module> p.gender ='man' AttributeError: 'Person' object has no attribute 'gender'
__slot__目的是限制當前類所能擁有的屬性。因此在繼承的環境下,子類不受影響。get
>>> class Student(Person): pass >>> s = Student('zhangsan',26) >>> s.age 26 >>> s.name 'zhangsan' >>> s.gender = 'man'//能夠動態添加屬性 >>> s.gender 'man'
因此子類Student若是想本身限制添加屬性的話,也要經過__slots__來控制。
一個類的實例能夠變成一個可調用的對象,只須要實現一個特殊的方法__call__就能夠了。
接下來咱們把Student類變成一個可調用的對象:
>>> class Student(Person): def __init__(self,name,score): self.name = name self.score = score >>> class Student(Person): def __init__(self,name,score): self.name = name self.score = score def __call__(self,age): print 'my name is %s'% self.name print 'my age is %d'% age >>> s = Student('lixi',89) >>> s(25) my name is lixi my age is 25
有時候你會發現s(25)乍一眼感受不出來是一個函數仍是對象的實例。python語言函數和對象的實例不是區分的很明顯。
上述的class Student中,當修改s實例的score值時,
>>> s.score = 89 >>> s.score = 9999
可是這樣沒法檢查s實例的分數有效性。目前只能這樣作:
>>> class Student(object): def __init__(self,name,score): self.name = name self.__score = score def set_score(self,score): if score <0 or score >100: raise ValueError('invalid score') self.__score = score def get_score(self): return self.__score >>> s = Student('wangwu',89) >>> s.set_score(89) >>> s.set_score(9999) //非法值,ValueError Traceback (most recent call last): File "<pyshell#75>", line 1, in <module> s.set_score(9999) File "<pyshell#71>", line 7, in set_score raise ValueError('invalid score') ValueError: invalid score
有時候以爲寫s.set_score和s.get_score沒有直接寫s.score那麼直接。有沒有其餘辦法?既能直接的s.score又能檢查score的有效性?python提供@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 >>> s = Student('liunx',98) >>> s.score = 89 >>> s.score = 9999 Traceback (most recent call last): File "<pyshell#82>", line 1, in <module> s.score = 9999 File "<pyshell#79>", line 12, in score raise ValueError('invalid score') ValueError: invalid score
小結:
特殊方法:
1.任何數據實例都有特殊方法
2.特殊方法定義在class中
3.不須要直接調用
4.python的某些方法或者函數會直接調用數據實例的特殊方法
實現特殊方法:
1.從新編寫用到的特殊方法
2.若是從新一些特殊方法,有些關聯的特殊方法也要一併實現。例如:__setattr__,__getattr__,__delattr__