快速瞭解Python的定製類

來源:互聯網
上載者:User

標籤:http   title   作用   方法   利用   處理   res   __init__   快速   

多重繼承

class Student(man,oldman):

  pass

可以繼承多個父類,擁有他們的方法,如果有父類有相同的方法,哪個在前用哪個

定製類

看到類似__slots__這種形如 __xxx__的變數或函數名就要注意,這些在python中是有特殊用途的

我們已經知道了__slots__的用法,用__len__()方法我們也知道是為了能讓class作用於len()函數

__str__

我們先定義一個Student類,列印一個執行個體

class Studentc():    def __init__(self,name):        self.__name = nameprint(Studentc(‘cc‘))
--> <__main__.Studentc object at 0x0000000000B48B00>

列印出來一坨不好看,我們定義一下__str__()方法,返回一個好看的字串

class Studentc():    def __init__(self,name):        self.__name = name    def __str__(self):        return ‘Studentc object (name : %s)‘% self.__nameprint(Studentc(‘cc‘)) #  Studentc object (name : cc)

這裡return 不用敲print

但是直接敲變數在shell下運行,列印出來的還是不好看

123 >>> s = Student(‘Michael‘)>>> s<__main__.Student object at 0x109afb310>

這是因為直接顯示變數調用的不是__str__(),而是__repr__(),兩者的區別就是__str__()返回使用者看到的字串,而__repr__返回程式開發人員看到的字串,也就是說__repr__()是為調試服務的

解決辦法是再定義一個__repr__()。但是通常兩個代碼是一樣的,可以偷懶

class Studentc():    def __init__(self,name):        self.__name = name    def __str__(self):        return ‘Studentc object (name : %s)‘% self.__name    __repr__ = __str__

__iter__

如果一個類想要被用於for in 迴圈,必須實現一個__iter__()方法,改方法返回一個迭代對象,然後就會不斷調用該迭代對象的__next__()方法拿到迴圈的下一個值,直到遇到StopIteration錯誤時退出迴圈

class Fib():    def __init__(self):        self.__a,self.__b = 0,1    def __iter__(self):        return self    def __next__(self):        self.__a,self.__b = self.__b,self.__a + self.__b        if self.__a >1000:            raise StopIteration        else:            return self.__afor x in Fib():    print(x)

__getitem__

Fib執行個體雖然能作用於for迴圈,看起來和list有點像,但是,把它當成list使用還是不行比如取第五個元素

class Suv():    def __getitem__(self,n):        a,b = 0,1        for x in range(n):            a,b = b,a+b        return aprint(Fib()[3])

list還有切片功能,這裡不能用,因為我們不知道傳進來的是什麼需要做一個判斷

isinstance(n,slice) slice是切片的類型。還有負數等沒有處理真想完全實現的話需要添加很多

__getattr__

正常情況下,當我們調用類的方法或屬性時,如果不存在,就會報錯

避免這種情況,除了可以加上一個score屬性外,python還有另一個機智,那就是寫一個__getattr__()方法,動態返回一個屬性

class Su():    def __init__(self):        self.name = ‘cc‘    def __getattr__(self, item):        if item == ‘score‘:            return ‘99‘print(Su().score)

當調用的屬性不存在時,比如score,python會試圖調用__getattr__(self,‘score‘)來嘗試獲得屬性,這樣我們就有機會返回score的值

返回函數也是可以的

class Student():    def __init__(self):        self.name = ‘cc‘    def __getattr__(self, item):        if item == ‘age‘:            return lambda :25print(Student().age())

返回一個函數,調用的時候修改成Student().age()

注意,只有在沒有找到屬性的情況下,才調用__getattr__,已有的屬性,比如name,不會在__getattr__中尋找

此外,如果沒對未知的屬性做處理,if判斷輸出的話。會返回None,要讓class只響應特定的幾個屬性,我們就按照約定拋出AttributeError的錯誤

class Student():    def __init__(self):        self.name = ‘cc‘    def __getattr__(self, item):        if item == ‘age‘:            return lambda :25        raise AttributeError(‘no have %s‘%item)print(Student().ac())

這實際上可以吧一個類的所有屬性和方法調用全部動態化處理了,不需要任何特殊手段

這種完全動態調用的特性與什麼實際作用呢?作用就是可以針對完全動態情況作調用

舉個例子

現在很多網站都搞rest api,比如新浪微博,豆瓣 調用api的url類似 

http://api.server/user/friends

如果要寫sdk,給誒給url對應的api寫一個方法,那得累死,而且一旦api改動,sdk也要改

利用完全動態__getaattr__我們可以寫一個鏈式調用

class Chain():    def __init__(self,ab=""):        self._path =ab    def __getattr__(self, path):        print(‘self._path = %s ,path = %s‘%(self._path,path))        return Chain(‘%s/%s‘ % (self._path,path))    def __str__(self):        return self._path    __reper__ = __str__c = Chain().status.user.time.listprint(c)
12345 self._path =  ,path = statusself._path = /status ,path = userself._path = /status/user ,path = timeself._path = /status/user/time ,path = list/status/user/time/list

屬性都不存在,每一次都調用__getattr__方法,返回當前self._path + 屬性名稱,並被_path獲得,不斷累加直到沒有屬性

列印返回self._path 的值

__call__

一個對象執行個體可以與自己的屬性和方法,當我們調用執行個體方法時,我們會用instance.methond()來調用。能不能直接在執行個體本身上調用呢,在python答案是肯定的

任何類,只需要定義一個__call__()方法,就可以直接對執行個體進行調用

class Students():    def __init__(self,name):        self.name = name    def __call__(self):        print(‘myname is %s‘% self.name)s1 = Students(‘s1‘)s1()

__call__()還可以定義參數。對執行個體進行直接調用就好比對一個函數調用一樣,所以你完全可以把對象看出函數,把函數看成對象,因為兩者之間本來就沒有什麼根本的區別

如果你把對象看成函數,那麼函數本身其實也可以在運行期間動態建立出來的,這麼一來,我們就模糊了對象和函數的界限。

那麼如何判斷一個變數是對象還是函數呢?其實我們只需要判斷一個對象是否能被調用,能被調用的對象就是一個Callable對象,比如函數和我們上面定義的__call__()的類執行個體

print(callable(Student))print(callable([1,2,34]))print(callable(None))print(callable(‘str‘))

快速瞭解Python的定製類

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.