中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

@classmethod與@staticmethod的區(qū)別是什么

@classmethod與@staticmethod的區(qū)別是什么,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

為莫力達(dá)等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計制作服務(wù),及莫力達(dá)網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都做網(wǎng)站、網(wǎng)站制作、莫力達(dá)網(wǎng)站設(shè)計,以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!

Python面向?qū)ο缶幊讨?,類中定義的方法可以是 @classmethod 裝飾的類方法,也可以是 @staticmethod 裝飾的靜態(tài)方法,用的最多的還是不帶裝飾器的實例方法,如果把這幾個方法放一塊,對初學(xué)者來說無疑是一頭霧水,那我們該如何正確地使用它們呢?

先來看一個簡單示例:

class A(object):
   def m1(self, n):
       print("self:", self)

   @classmethod
   def m2(cls, n):
       print("cls:", cls)

   @staticmethod
   def m3(n):
       pass

a = A()
a.m1(1) # self: <__main__.A object at 0x000001E596E41A90>
A.m2(1) # cls: <class '__main__.A'>
A.m3(1)

我在類中一共定義了3個方法,m1 是實例方法,第一個參數(shù)必須是 self(約定俗成的)。m2 是類方法,第一個參數(shù)必須是cls(同樣是約定俗成),m3 是靜態(tài)方法,參數(shù)根據(jù)業(yè)務(wù)需求定,可有可無。當(dāng)程序運行時,大概發(fā)生了這么幾件事(結(jié)合下面的圖來看)。

  • 第一步:代碼從第一行開始執(zhí)行 class 命令,此時會創(chuàng)建一個類 A 對象(沒錯,類也是對象,一切皆對象嘛)同時初始化類里面的屬性和方法,記住,此刻實例對象還沒創(chuàng)建出來。

  • 第二、三步:接著執(zhí)行 a=A(),系統(tǒng)自動調(diào)用類的構(gòu)造器,構(gòu)造出實例對象 a

  • 第四步:接著調(diào)用 a.m1(1) ,m1 是實例方法,內(nèi)部會自動把實例對象傳遞給 self 參數(shù)進行綁定,也就是說, self 和 a 指向的都是同一個實例對象。

  • 第五步:調(diào)用A.m2(1)時,python內(nèi)部隱式地把類對象傳遞給 cls 參數(shù),cls 和 A 都指向類對象。

@classmethod與@staticmethod的區(qū)別是什么

嚴(yán)格意義上來說,左邊的都是變量名,是對象的引用,右邊才是真正的對像,為了描述方便,我直接把 a 稱為對象,你應(yīng)該明白我說對象其實是它所引用右邊的那個真正的對象。

再來看看每個方法各有什么特性

實例方法

print(A.m1)
# A.m1在py2中顯示為<unbound method A.m1>
<function A.m1 at 0x000002BF7FF9A488>

print(a.m1)
<bound method A.m1 of <__main__.A object at 0x000002BF7FFA2BE0>>

A.m1是一個還沒有綁定實例對象的方法,對于未綁定方法,調(diào)用 A.m1 時必須顯示地傳入一個實例對象進去,而 a.m1是已經(jīng)綁定了實例的方法,python隱式地把對象傳遞給了self參數(shù),所以不再手動傳遞參數(shù),這是調(diào)用實例方法的過程。

A.m1(a, 1)
# 等價  
a.m1(1)

如果未綁定的方法 A.m1 不傳實例對象給 self 時,就會報參數(shù)缺失錯誤,在 py3 與 py2 中,兩者報的錯誤不一致,python2 要求第一個參數(shù)self是實例對象,而python3中可以是任意對象。

A.m1(1)
TypeError: m1() missing 1 required positional argument: 'n'

類方法

print(A.m2)
<bound method A.m2 of <class '__main__.A'>>

print(a.m2)
<bound method A.m2 of <class '__main__.A'>>

m2是類方法,不管是 A.m2 還是 a.m2,都是已經(jīng)自動綁定了類對象A的方法,對于后者,因為python可以通過實例對象a找到它所屬的類是A,找到A之后自動綁定到 cls。

 A.m2(1)
# 等價
a.m2(1)

這使得我們可以在實例方法中通過使用 self.m2()這種方式來調(diào)用類方法和靜態(tài)方法。

def m1(self, n):
   print("self:", self)
   self.m2(n)

靜態(tài)方法

print(A.m3)
<function A.m3 at 0x000002BF7FF9A840>

print(a.m3)
<function A.m3 at 0x000002BF7FF9A840>

m3是類里面的一個靜態(tài)方法,跟普通函數(shù)沒什么區(qū)別,與類和實例都沒有所謂的綁定關(guān)系,它只不過是碰巧存在類中的一個函數(shù)而已。不論是通過類還是實例都可以引用該方法。

 A.m3(1)
# 等價
a.m3(1)

以上就是幾個方法的基本介紹。現(xiàn)在把幾個基本的概念理清楚了,那么現(xiàn)在來說說幾個方法之間的使用場景以及他們之間的優(yōu)缺點。

應(yīng)用場景

靜態(tài)方法的使用場景:

如果在方法中不需要訪問任何實例方法和屬性,純粹地通過傳入?yún)?shù)并返回數(shù)據(jù)的功能性方法,那么它就適合用靜態(tài)方法來定義,它節(jié)省了實例化對象的開銷成本,往往這種方法放在類外面的模塊層作為一個函數(shù)存在也是沒問題的,而放在類中,僅為這個類服務(wù)。

例如下面是微信公眾號開發(fā)中驗證微信簽名的一個例子,它沒有引用任何類或者實例相關(guān)的屬性和方法。

from hashlib import sha1
import tornado.web

class SignatureHandler(tornado.web.RequestHandler):
   def get(self):
       """
        根據(jù)簽名判斷請求是否來自微信
       """
       if self._check_sign(TOKEN, timestamp, nonce, signature):
           self.write(echostr)
       else:
           self.write("你不是微信發(fā)過來的請求")

   @staticmethod
   def _check_sign(token, timestamp, nonce, signature):
       sign = [token, timestamp, nonce]
       sign.sort()
       sign = "".join(sign)
       sign = sha1(sign).hexdigest()
       return sign == signature

類方法的使用場景有:

作為工廠方法創(chuàng)建實例對象,例如內(nèi)置模塊 datetime.date 類中就有大量使用類方法作為工廠方法,以此來創(chuàng)建date對象。

class date:

   def __new__(cls, year, month=None, day=None):
       self = object.__new__(cls)
       self._year = year
       self._month = month
       self._day = day
       return self

   @classmethod
   def fromtimestamp(cls, t):
       y, m, d, * = _time.localtime(t)
       return cls(y, m, d)

   @classmethod
   def today(cls):
       t = _time.time()
       return cls.fromtimestamp(t)

如果希望在方法裡面調(diào)用靜態(tài)類,那么把方法定義成類方法是合適的,因為要是定義成靜態(tài)方法,那么你就要顯示地引用類A,這對繼承來說可不是一件好事情。

class A:

    @staticmethod
    def m1()
        pass

    @staticmethod
    def m2():
        A.m1() # bad

    @classmethod
    def m3(cls):
        cls.m1() # good

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。

新聞名稱:@classmethod與@staticmethod的區(qū)別是什么
文章轉(zhuǎn)載:http://www.rwnh.cn/article0/psjcio.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應(yīng)網(wǎng)站、品牌網(wǎng)站建設(shè)、移動網(wǎng)站建設(shè)、網(wǎng)站策劃、外貿(mào)網(wǎng)站建設(shè)網(wǎng)站營銷

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計公司
揭西县| 友谊县| 崇仁县| 绍兴市| 庐江县| 双鸭山市| 兴业县| 澄江县| 四川省| 环江| 定兴县| 囊谦县| 山阳县| 武城县| 清苑县| 萨嘎县| 阜康市| 卓尼县| 和田市| 靖宇县| 西乌珠穆沁旗| 阜城县| 呼图壁县| 荥经县| 白银市| 涟源市| 广元市| 岳阳市| 定日县| 甘洛县| 岱山县| 曲阳县| 沧州市| 宁乡县| 金堂县| 长春市| 莱阳市| 卓资县| 桃园市| 南木林县| 屯门区|