国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

在Python中使用靜態,類或抽象方法的權威指南

cheukyin / 2838人閱讀

摘要:在中,可以將和裝飾器放在上面和的接口相反,你可以在抽象方法中實現代碼并通過調用它在上面的例子中,繼承來創建的每個都必須重寫方法,但是可以使用來獲取出處

Python中方法的工作方式

方法是存儲在類屬性中的函數,你可以用下面這種方式聲明和訪問一個函數

</>復制代碼

  1. >>> class Pizza(object):
  2. ... def __init__(self, size):
  3. ... self.size = size
  4. ... def get_size(self):
  5. ... return self.size
  6. ...
  7. >>> Pizza.get_size

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

</>復制代碼

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

我們無法調用它(get_size),因為它沒有綁定到Pizza的任何實例上,而且一個方法需要一個實例作為它的第一個參數(Python2中必須是類的實例,Python3沒有這個強制要求),讓我們試一下:

</>復制代碼

  1. >>> Pizza.get_size(Pizza(42))
  2. 42

我們使用一個實例作為這個方法的第一個參數來調用它,沒有出現任何問題。但是如果我說這不是一個方便的調用方法的方式,你將會同意我的觀點。我們每次調用方法都要涉及(這里我理解是引用)類

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

</>復制代碼

  1. >>> Pizza(42).get_size
  2. >
  3. >>> Pizza(42).get_size()
  4. 42

意料之中,我們不需要為get_size傳任何參數,自從被綁定后,它的self參數會自動設置為Pizza實例,下面是一個更明顯的例子:

</>復制代碼

  1. >>> m = Pizza(42).get_size
  2. >>> m()
  3. 42

事實上是,你甚至不需要對Pizza引用,因為這個方法已經綁定到了這個對象

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

</>復制代碼

  1. >>> m = Pizza(42).get_size
  2. >>> m.__self__
  3. <__main__.Pizza object at 0x7f3138827910>
  4. >>> # You could guess, look at this:
  5. ...
  6. >>> m == m.__self__.get_size
  7. True

明顯可以看出,我們仍然保持對我們對象的引用,而且如果需要我們可以找到它

在Python3中,類中的函數不再被認為是未綁定的方法(應該是作為函數存在),如果需要,會作為一個函數綁定到對象上,所以原理是一樣的(和Python2),只是模型被簡化了

</>復制代碼

  1. >>> class Pizza(object):
  2. ... def __init__(self, size):
  3. ... self.size = size
  4. ... def get_size(self):
  5. ... return self.size
  6. ...
  7. >>> Pizza.get_size
靜態方法

靜態方法一種特殊方法,有時你想把代碼歸屬到一個類中,但又不想和這個對象發生任何交互:

</>復制代碼

  1. class Pizza(object):
  2. @staticmethod
  3. def mix_ingredients(x, y):
  4. return x + y
  5. def cook(self):
  6. return self.mix_ingredients(self.cheese, self.vegetables)

上面這個例子,mix_ingredients完全可以寫成一個非靜態方法,但是這樣會將self作為第一個參數傳入。在這個例子里,裝飾器@staticmethod 會實現幾個功能:

Python不會為Pizza的實例對象實例化一個綁定方法,綁定方法也是對象,會產生開銷,靜態方法可以避免這類情況

</>復制代碼

  1. >>> Pizza().cook is Pizza().cook
  2. False
  3. >>> Pizza().mix_ingredients is Pizza.mix_ingredients
  4. True
  5. >>> Pizza().mix_ingredients is Pizza().mix_ingredients
  6. True

簡化了代碼的可讀性,看到@staticmethod我們就會知道這個方法不會依賴這個對象的狀態(一國兩制,高度自治)
允許在子類中重寫mix_ingredients方法。如果我們在頂級模型中定義了mix_ingredients函數,繼承自Pizza的類除了重寫,否則無法改變mix_ingredients的功能

類方法

什么是類方法,類方法是方法不會被綁定到一個對象,而是被綁定到一個類中

</>復制代碼

  1. >>> class Pizza(object):
  2. ... radius = 42
  3. ... @classmethod
  4. ... def get_radius(cls):
  5. ... return cls.radius
  6. ...
  7. >>>
  8. >>> Pizza.get_radius
  9. >
  10. >>> Pizza().get_radius
  11. >
  12. >>> Pizza.get_radius == Pizza().get_radius
  13. True
  14. >>> Pizza.get_radius()
  15. 42

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

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

</>復制代碼

  1. class Pizza(object):
  2. def __init__(self, ingredients):
  3. self.ingredients = ingredients
  4. @classmethod
  5. def from_fridge(cls, fridge):
  6. return cls(fridge.get_cheese() + fridge.get_vegetables())

2、使用靜態方法調用靜態方法,如果你需要將一個靜態方法拆分為多個,可以使用類方法來避免硬編碼類名。使用這種方法來聲明我們的方法Pizza的名字永遠不會被直接引用,而且繼承和重寫方法都很方便

</>復制代碼

  1. class Pizza(object):
  2. def __init__(self, radius, height):
  3. self.radius = radius
  4. self.height = height
  5. @staticmethod
  6. def compute_area(radius):
  7. return math.pi * (radius ** 2)
  8. @classmethod
  9. def compute_volume(cls, height, radius):
  10. return height * cls.compute_area(radius)
  11. def get_volume(self):
  12. return self.compute_volume(self.height, self.radius)
抽象方法

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

</>復制代碼

  1. class Pizza(object):
  2. def get_radius(self):
  3. raise NotImplementedError

繼承自Pizza的類都必須要實現并重寫get_redius,否則就會報錯

這種方式的抽象方法有一個問題,如果你忘記實現了get_radius,只有在你調用這個方法的時候才會報錯

</>復制代碼

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

使用python的abc模塊可以是這個異常被更早的觸發

</>復制代碼

  1. import abc
  2. class BasePizza(object):
  3. __metaclass__ = abc.ABCMeta
  4. @abc.abstractmethod
  5. def get_radius(self):
  6. """Method that should do something."""

使用abc和它的特殊類,如果你嘗試實例化BasePizza或者繼承它,都會得到TypeError錯誤

</>復制代碼

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

備注:我使用Python3.6實現的代碼

</>復制代碼

  1. In [8]: import abc
  2. ...:
  3. ...: class BasePizza(abc.ABC):
  4. ...:
  5. ...: @abc.abstractmethod
  6. ...: def get_radius(self):
  7. ...: """:return"""
  8. ...:
  9. In [9]: BasePizza()
  10. ---------------------------------------------------------------------------
  11. TypeError Traceback (most recent call last)
  12. in ()
  13. ----> 1 BasePizza()
  14. TypeError: Can"t instantiate abstract class BasePizza with abstract methods get_radius
混合靜態,類和抽象方法

如果對Python編程、網絡爬蟲、機器學習、數據挖掘、web開發、人工智能、面試經驗交流。感興趣可以519970686,群內會有不定期的發放免費的資料鏈接,這些資料都是從各個技術網站搜集、整理出來的,如果你有好的學習資料可以私聊發我,我會注明出處之后分享給大家。

當需要創建類和繼承時,如果你需要混合這些方法裝飾器,這里有一些小竅門建議給你
記住要將方法聲明為抽象,不要凍結這個方法的原型。意思是它(聲明的方法)必須要執行,但是它在執行的時候,參數不會有任何限制

</>復制代碼

  1. import abc
  2. class BasePizza(object):
  3. __metaclass__ = abc.ABCMeta
  4. @abc.abstractmethod
  5. def get_ingredients(self):
  6. """Returns the ingredient list."""
  7. class Calzone(BasePizza):
  8. def get_ingredients(self, with_egg=False):
  9. egg = Egg() if with_egg else None
  10. return self.ingredients + egg

這樣是有效的,因為Calzone實現了我們為BasePizza定義的接口要求,這意味著我們也可以將它實現為一個類或者靜態方法,例如:

</>復制代碼

  1. import abc
  2. class BasePizza(object):
  3. __metaclass__ = abc.ABCMeta
  4. @abc.abstractmethod
  5. def get_ingredients(self):
  6. """Returns the ingredient list."""
  7. class DietPizza(BasePizza):
  8. @staticmethod
  9. def get_ingredients():
  10. return None

這也是正確的,它實現了抽要BasePizza的要求,事實上是get_ingredioents方法不需要知道對象返回的結果,
因此,你不需要強制抽象方法實現成為常規方法、類或者靜態方法。在python3中,可以將@staticmethod和@classmethod裝飾器放在@abstractmethod上面

</>復制代碼

  1. import abc
  2. class BasePizza(object):
  3. __metaclass__ = abc.ABCMeta
  4. ingredient = ["cheese"]
  5. @classmethod
  6. @abc.abstractmethod
  7. def get_ingredients(cls):
  8. """Returns the ingredient list."""
  9. return cls.ingredients

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

</>復制代碼

  1. import abc
  2. class BasePizza(object):
  3. __metaclass__ = abc.ABCMeta
  4. default_ingredients = ["cheese"]
  5. @classmethod
  6. @abc.abstractmethod
  7. def get_ingredients(cls):
  8. """Returns the ingredient list."""
  9. return cls.default_ingredients
  10. class DietPizza(BasePizza):
  11. def get_ingredients(self):
  12. return ["egg"] + super(DietPizza, self).get_ingredients()

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

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

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/44895.html

相關文章

  • Python標準庫---6、內置函數(P-K-R-S-T-U)

    摘要:上一篇文章標準庫內置函數下一篇文章標準庫內置函數內置函數返回一個新的對象,可以選擇帶有從獲取的元素。推薦使用內置函數來檢測對象的類型,因為它會考慮子類的情況。上一篇文章標準庫內置函數下一篇文章標準庫內置函數 上一篇文章:Python標準庫---5、內置函數(P-K-R)下一篇文章:Python標準庫---7、內置函數(V-W-X-Y-Z) 內置函數: showImg(https://...

    lastSeries 評論0 收藏0
  • 資源大放送

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

    lidashuang 評論0 收藏0
  • 第3章:抽象數據類型(ADT)和面向對象編程(OOP) 3.4面向對象編程(OOP)

    摘要:抽象數據類型的多個不同表示可以共存于同一個程序中,作為實現接口的不同類。封裝和信息隱藏信息隱藏將精心設計的模塊與不好的模塊區分開來的唯一最重要的因素是其隱藏內部數據和其他模塊的其他實施細節的程度。 大綱 面向對象的標準基本概念:對象,類,屬性,方法和接口OOP的獨特功能 封裝和信息隱藏 繼承和重寫 多態性,子類型和重載 靜態與動態分派 Java中一些重要的Object方法設計好的類面向...

    Heier 評論0 收藏0
  • JSbind方法與函數柯里化

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

    wua_wua2012 評論0 收藏0

發表評論

0條評論

cheukyin

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<