亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

在Python中使用靜態(tài),類或抽象方法的權(quán)威指南

cheukyin / 2889人閱讀

摘要:在中,可以將和裝飾器放在上面和的接口相反,你可以在抽象方法中實(shí)現(xiàn)代碼并通過調(diào)用它在上面的例子中,繼承來(lái)創(chuàng)建的每個(gè)都必須重寫方法,但是可以使用來(lái)獲取出處

Python中方法的工作方式

方法是存儲(chǔ)在類屬性中的函數(shù),你可以用下面這種方式聲明和訪問一個(gè)函數(shù)

>>> class Pizza(object):
    ...     def __init__(self, size):
    ...         self.size = size
    ...     def get_size(self):
    ...         return self.size
    ...
    >>> Pizza.get_size
    

Python在這里說(shuō)明了什么?Pizza類的屬性get_size是unbound(未綁定的),這代表什么含義?我們調(diào)用一下就明白了:

 >>> Pizza.get_size()
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: unbound method get_size() must be called with Pizza instance as first argument (got nothing instead)

我們無(wú)法調(diào)用它(get_size),因?yàn)樗鼪]有綁定到Pizza的任何實(shí)例上,而且一個(gè)方法需要一個(gè)實(shí)例作為它的第一個(gè)參數(shù)(Python2中必須是類的實(shí)例,Python3沒有這個(gè)強(qiáng)制要求),讓我們?cè)囈幌?

 >>> Pizza.get_size(Pizza(42))
    42

我們使用一個(gè)實(shí)例作為這個(gè)方法的第一個(gè)參數(shù)來(lái)調(diào)用它,沒有出現(xiàn)任何問題。但是如果我說(shuō)這不是一個(gè)方便的調(diào)用方法的方式,你將會(huì)同意我的觀點(diǎn)。我們每次調(diào)用方法都要涉及(這里我理解是引用)類

來(lái)看Python打算為我們做些什么,就是它從Pizza類中綁定所有的方法到這個(gè)類的任何實(shí)例上。意思就是Pizza實(shí)例化后get_size這個(gè)屬性是一個(gè)綁定方法,方法的第一個(gè)參數(shù)會(huì)是實(shí)例對(duì)象自己

>>> Pizza(42).get_size
    >
    >>> Pizza(42).get_size()
    42

意料之中,我們不需要為get_size傳任何參數(shù),自從被綁定后,它的self參數(shù)會(huì)自動(dòng)設(shè)置為Pizza實(shí)例,下面是一個(gè)更明顯的例子:

>>> m = Pizza(42).get_size
    >>> m()
    42

事實(shí)上是,你甚至不需要對(duì)Pizza引用,因?yàn)檫@個(gè)方法已經(jīng)綁定到了這個(gè)對(duì)象

如果你想知道這個(gè)綁定方法綁定到了哪一個(gè)對(duì)象,這里有個(gè)快捷的方法:

 >>> m = Pizza(42).get_size
    >>> m.__self__
    <__main__.Pizza object at 0x7f3138827910>
    >>> # You could guess, look at this:
    ...
    >>> m == m.__self__.get_size
    True

明顯可以看出,我們?nèi)匀槐3謱?duì)我們對(duì)象的引用,而且如果需要我們可以找到它

在Python3中,類中的函數(shù)不再被認(rèn)為是未綁定的方法(應(yīng)該是作為函數(shù)存在),如果需要,會(huì)作為一個(gè)函數(shù)綁定到對(duì)象上,所以原理是一樣的(和Python2),只是模型被簡(jiǎn)化了

 >>> class Pizza(object):
    ...     def __init__(self, size):
    ...         self.size = size
    ...     def get_size(self):
    ...         return self.size
    ...
    >>> Pizza.get_size
    
靜態(tài)方法

靜態(tài)方法一種特殊方法,有時(shí)你想把代碼歸屬到一個(gè)類中,但又不想和這個(gè)對(duì)象發(fā)生任何交互:

class Pizza(object):
        @staticmethod
        def mix_ingredients(x, y):
            return x + y

        def cook(self):
            return self.mix_ingredients(self.cheese, self.vegetables)

上面這個(gè)例子,mix_ingredients完全可以寫成一個(gè)非靜態(tài)方法,但是這樣會(huì)將self作為第一個(gè)參數(shù)傳入。在這個(gè)例子里,裝飾器@staticmethod 會(huì)實(shí)現(xiàn)幾個(gè)功能:

Python不會(huì)為Pizza的實(shí)例對(duì)象實(shí)例化一個(gè)綁定方法,綁定方法也是對(duì)象,會(huì)產(chǎn)生開銷,靜態(tài)方法可以避免這類情況

>>> Pizza().cook is Pizza().cook
        False
        >>> Pizza().mix_ingredients is Pizza.mix_ingredients
        True
        >>> Pizza().mix_ingredients is Pizza().mix_ingredients
        True

簡(jiǎn)化了代碼的可讀性,看到@staticmethod我們就會(huì)知道這個(gè)方法不會(huì)依賴這個(gè)對(duì)象的狀態(tài)(一國(guó)兩制,高度自治)
允許在子類中重寫mix_ingredients方法。如果我們?cè)陧敿?jí)模型中定義了mix_ingredients函數(shù),繼承自Pizza的類除了重寫,否則無(wú)法改變mix_ingredients的功能

類方法

什么是類方法,類方法是方法不會(huì)被綁定到一個(gè)對(duì)象,而是被綁定到一個(gè)類中

 >>> class Pizza(object):
    ...     radius = 42
    ...     @classmethod
    ...     def get_radius(cls):
    ...         return cls.radius
    ... 
    >>> 
    >>> Pizza.get_radius
    >
    >>> Pizza().get_radius
    >
    >>> Pizza.get_radius == Pizza().get_radius
    True
    >>> Pizza.get_radius()
    42

無(wú)論以何種方式訪問這個(gè)方法,它都會(huì)被綁定到類中,它的第一個(gè)參數(shù)必須是類本身(記住類也是對(duì)象)

什么時(shí)候使用類方法,類方法在以下兩種場(chǎng)合會(huì)有很好的效果:
1、工廠方法,為類創(chuàng)建實(shí)例,例如某種程度的預(yù)處理。如果我們使用@staticmethod代替,我們必須要在代碼中硬編碼Pizza(寫死Pizza),這樣從Pizza繼承的類就不能使用了

 class Pizza(object):
            def __init__(self, ingredients):
                self.ingredients = ingredients

            @classmethod
            def from_fridge(cls, fridge):
                return cls(fridge.get_cheese() + fridge.get_vegetables())

2、使用靜態(tài)方法調(diào)用靜態(tài)方法,如果你需要將一個(gè)靜態(tài)方法拆分為多個(gè),可以使用類方法來(lái)避免硬編碼類名。使用這種方法來(lái)聲明我們的方法Pizza的名字永遠(yuǎn)不會(huì)被直接引用,而且繼承和重寫方法都很方便

class Pizza(object):
            def __init__(self, radius, height):
                self.radius = radius
                self.height = height

            @staticmethod
            def compute_area(radius):
                 return math.pi * (radius ** 2)

            @classmethod
            def compute_volume(cls, height, radius):
                 return height * cls.compute_area(radius)

            def get_volume(self):
                return self.compute_volume(self.height, self.radius)
抽象方法

抽象方法是定義在基類中的,可以是不提供任何功能代碼的方法
在Python中簡(jiǎn)單的寫抽象方法的方式是:

 class Pizza(object):
        def get_radius(self):
            raise NotImplementedError

繼承自Pizza的類都必須要實(shí)現(xiàn)并重寫get_redius,否則就會(huì)報(bào)錯(cuò)

這種方式的抽象方法有一個(gè)問題,如果你忘記實(shí)現(xiàn)了get_radius,只有在你調(diào)用這個(gè)方法的時(shí)候才會(huì)報(bào)錯(cuò)

  >>> Pizza()
    <__main__.Pizza object at 0x7fb747353d90>
    >>> Pizza().get_radius()
    Traceback (most recent call last):
      File "", line 1, in 
      File "", line 3, in get_radius
    NotImplementedError

使用python的abc模塊可以是這個(gè)異常被更早的觸發(fā)

 import abc

    class BasePizza(object):
        __metaclass__  = abc.ABCMeta

        @abc.abstractmethod
        def get_radius(self):
             """Method that should do something."""

使用abc和它的特殊類,如果你嘗試實(shí)例化BasePizza或者繼承它,都會(huì)得到TypeError錯(cuò)誤

>>> BasePizza()
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: Can"t instantiate abstract class BasePizza with abstract methods get_radius

備注:我使用Python3.6實(shí)現(xiàn)的代碼

In [8]: import abc
       ...:
       ...: class BasePizza(abc.ABC):
       ...:
       ...:     @abc.abstractmethod
       ...:     def get_radius(self):
       ...:          """:return"""
       ...:

    In [9]: BasePizza()
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
     in ()
    ----> 1 BasePizza()

    TypeError: Can"t instantiate abstract class BasePizza with abstract methods get_radius
混合靜態(tài),類和抽象方法

如果對(duì)Python編程、網(wǎng)絡(luò)爬蟲、機(jī)器學(xué)習(xí)、數(shù)據(jù)挖掘、web開發(fā)、人工智能、面試經(jīng)驗(yàn)交流。感興趣可以519970686,群內(nèi)會(huì)有不定期的發(fā)放免費(fèi)的資料鏈接,這些資料都是從各個(gè)技術(shù)網(wǎng)站搜集、整理出來(lái)的,如果你有好的學(xué)習(xí)資料可以私聊發(fā)我,我會(huì)注明出處之后分享給大家。

當(dāng)需要?jiǎng)?chuàng)建類和繼承時(shí),如果你需要混合這些方法裝飾器,這里有一些小竅門建議給你
記住要將方法聲明為抽象,不要凍結(jié)這個(gè)方法的原型。意思是它(聲明的方法)必須要執(zhí)行,但是它在執(zhí)行的時(shí)候,參數(shù)不會(huì)有任何限制

 import abc

        class BasePizza(object):
            __metaclass__  = abc.ABCMeta

            @abc.abstractmethod
            def get_ingredients(self):
                 """Returns the ingredient list."""

        class Calzone(BasePizza):
            def get_ingredients(self, with_egg=False):
                egg = Egg() if with_egg else None
                return self.ingredients + egg

這樣是有效的,因?yàn)镃alzone實(shí)現(xiàn)了我們?yōu)锽asePizza定義的接口要求,這意味著我們也可以將它實(shí)現(xiàn)為一個(gè)類或者靜態(tài)方法,例如:

import abc

        class BasePizza(object):
            __metaclass__  = abc.ABCMeta

            @abc.abstractmethod
            def get_ingredients(self):
                 """Returns the ingredient list."""

        class DietPizza(BasePizza):
            @staticmethod
            def get_ingredients():
                return None

這也是正確的,它實(shí)現(xiàn)了抽要BasePizza的要求,事實(shí)上是get_ingredioents方法不需要知道對(duì)象返回的結(jié)果,
因此,你不需要強(qiáng)制抽象方法實(shí)現(xiàn)成為常規(guī)方法、類或者靜態(tài)方法。在python3中,可以將@staticmethod和@classmethod裝飾器放在@abstractmethod上面

 import abc

        class BasePizza(object):
            __metaclass__  = abc.ABCMeta

            ingredient = ["cheese"]

            @classmethod
            @abc.abstractmethod
            def get_ingredients(cls):
                 """Returns the ingredient list."""
                 return cls.ingredients

和Java的接口相反,你可以在抽象方法中實(shí)現(xiàn)代碼并通過super()調(diào)用它

  import abc

        class BasePizza(object):
            __metaclass__  = abc.ABCMeta

            default_ingredients = ["cheese"]

            @classmethod
            @abc.abstractmethod
            def get_ingredients(cls):
                 """Returns the ingredient list."""
                 return cls.default_ingredients

        class DietPizza(BasePizza):
            def get_ingredients(self):
                return ["egg"] + super(DietPizza, self).get_ingredients()

在上面的例子中,繼承BasePizza來(lái)創(chuàng)建的每個(gè)Pizza都必須重寫get_ingredients 方法,但是可以使用super()來(lái)獲取default_ingredients

出處 https://blog.csdn.net/Stephen...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/44895.html

相關(guān)文章

  • Python標(biāo)準(zhǔn)庫(kù)---6、內(nèi)置函數(shù)(P-K-R-S-T-U)

    摘要:上一篇文章標(biāo)準(zhǔn)庫(kù)內(nèi)置函數(shù)下一篇文章標(biāo)準(zhǔn)庫(kù)內(nèi)置函數(shù)內(nèi)置函數(shù)返回一個(gè)新的對(duì)象,可以選擇帶有從獲取的元素。推薦使用內(nèi)置函數(shù)來(lái)檢測(cè)對(duì)象的類型,因?yàn)樗鼤?huì)考慮子類的情況。上一篇文章標(biāo)準(zhǔn)庫(kù)內(nèi)置函數(shù)下一篇文章標(biāo)準(zhǔn)庫(kù)內(nèi)置函數(shù) 上一篇文章:Python標(biāo)準(zhǔn)庫(kù)---5、內(nèi)置函數(shù)(P-K-R)下一篇文章:Python標(biāo)準(zhǔn)庫(kù)---7、內(nèi)置函數(shù)(V-W-X-Y-Z) 內(nèi)置函數(shù): showImg(https://...

    lastSeries 評(píng)論0 收藏0
  • 資源大放送

    摘要:這是我收集的一些資源,分享給大家,全部放在百度網(wǎng)盤,有需要的請(qǐng)轉(zhuǎn)存到自己的網(wǎng)盤或者下載,以免網(wǎng)盤鏈接失效,另外還有幾百的視頻文件存在網(wǎng)盤,需要的加全部分享在空間,自己可以去下載與權(quán)威指南配套源碼禪意花園高清源碼基礎(chǔ)教程權(quán)威指南參考手冊(cè)鋒利 這是我收集的一些資源,分享給大家,全部放在百度網(wǎng)盤,有需要的請(qǐng)轉(zhuǎn)存到自己的網(wǎng)盤或者下載,以免網(wǎng)盤鏈接失效,另外還有幾百G的視頻文件存在網(wǎng)盤,需要的加...

    lidashuang 評(píng)論0 收藏0
  • 第3章:抽象數(shù)據(jù)類型(ADT)和面向?qū)ο缶幊蹋∣OP) 3.4面向?qū)ο缶幊蹋∣OP)

    摘要:抽象數(shù)據(jù)類型的多個(gè)不同表示可以共存于同一個(gè)程序中,作為實(shí)現(xiàn)接口的不同類。封裝和信息隱藏信息隱藏將精心設(shè)計(jì)的模塊與不好的模塊區(qū)分開來(lái)的唯一最重要的因素是其隱藏內(nèi)部數(shù)據(jù)和其他模塊的其他實(shí)施細(xì)節(jié)的程度。 大綱 面向?qū)ο蟮臉?biāo)準(zhǔn)基本概念:對(duì)象,類,屬性,方法和接口OOP的獨(dú)特功能 封裝和信息隱藏 繼承和重寫 多態(tài)性,子類型和重載 靜態(tài)與動(dòng)態(tài)分派 Java中一些重要的Object方法設(shè)計(jì)好的類面向...

    Heier 評(píng)論0 收藏0
  • JSbind方法與函數(shù)柯里化

    摘要:手賤搜了下函數(shù)柯里化,結(jié)果搜出騰訊的一篇反柯里化的文章中有趣的反柯里化技術(shù),又犧牲不少腦細(xì)胞,趕緊吃飯,餓死了 原生bind方法 不同于jQuery中的bind方法只是簡(jiǎn)單的綁定事件函數(shù),原生js中bind()方法略復(fù)雜,該方法上在ES5中被引入,大概就是IE9+等現(xiàn)代瀏覽器都支持了(有關(guān)ES5各項(xiàng)特性的支持情況戳這里ECMAScript 5 compatibility table),...

    wua_wua2012 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<