關于如何在Python中使用靜態、類或抽象方法的權威指南

Python中方法的工作方式

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

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

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

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

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

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

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

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

    >>> Pizza(42).get_size<bound method Pizza.get_size of <__main__.Pizza object at 0x7f3138827910>>>>> Pizza(42).get_size()42

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

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

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

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

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

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

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

    >>> class Pizza(object):...     def __init__(self, size):...         self.size = size...     def get_size(self):...         return self.size...>>> Pizza.get_size<function Pizza.get_size at 0x7f307f984dd0>

靜態方法

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

    class Pizza(object):@staticmethoddef mix_ingredients(x, y):return x + ydef cook(self):return self.mix_ingredients(self.cheese, self.vegetables)

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

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

        >>> Pizza().cook is Pizza().cookFalse>>> Pizza().mix_ingredients is Pizza.mix_ingredientsTrue>>> Pizza().mix_ingredients is Pizza().mix_ingredientsTrue

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

類方法

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

     >>> class Pizza(object):...     radius = 42...     @classmethod...     def get_radius(cls):...         return cls.radius... >>> >>> Pizza.get_radius<bound method type.get_radius of <class '__main__.Pizza'>>>>> Pizza().get_radius<bound method type.get_radius of <class '__main__.Pizza'>>>>> Pizza.get_radius == Pizza().get_radiusTrue>>> Pizza.get_radius()42

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


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

        class Pizza(object):def __init__(self, ingredients):self.ingredients = ingredients@classmethoddef from_fridge(cls, fridge):return cls(fridge.get_cheese() + fridge.get_vegetables())

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

        class Pizza(object):def __init__(self, radius, height):self.radius = radiusself.height = height@staticmethoddef compute_area(radius):return math.pi * (radius ** 2)@classmethoddef compute_volume(cls, height, radius):return height * cls.compute_area(radius)def get_volume(self):return self.compute_volume(self.height, self.radius)

抽象方法

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

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

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

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

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

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

    import abcclass BasePizza(object):__metaclass__  = abc.ABCMeta@abc.abstractmethoddef get_radius(self):"""Method that should do something."""

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

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

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

    In [8]: import abc...:...: class BasePizza(abc.ABC):...:...:     @abc.abstractmethod...:     def get_radius(self):...:          """:return"""...:In [9]: BasePizza()---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)<ipython-input-9-70b53ea21e68> in <module>()----> 1 BasePizza()TypeError: Can't instantiate abstract class BasePizza with abstract methods get_radius

混合靜態,類和抽象方法

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

        import abcclass BasePizza(object):__metaclass__  = abc.ABCMeta@abc.abstractmethoddef get_ingredients(self):"""Returns the ingredient list."""class Calzone(BasePizza):def get_ingredients(self, with_egg=False):egg = Egg() if with_egg else Nonereturn self.ingredients + egg

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

        import abcclass BasePizza(object):__metaclass__  = abc.ABCMeta@abc.abstractmethoddef get_ingredients(self):"""Returns the ingredient list."""class DietPizza(BasePizza):@staticmethoddef get_ingredients():return None

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

        import abcclass BasePizza(object):__metaclass__  = abc.ABCMetaingredient = ['cheese']@classmethod@abc.abstractmethoddef get_ingredients(cls):"""Returns the ingredient list."""return cls.ingredients

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

        import abcclass BasePizza(object):__metaclass__  = abc.ABCMetadefault_ingredients = ['cheese']@classmethod@abc.abstractmethoddef get_ingredients(cls):"""Returns the ingredient list."""return cls.default_ingredientsclass DietPizza(BasePizza):def get_ingredients(self):return ['egg'] + super(DietPizza, self).get_ingredients()

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

?

本文翻譯自:https://julien.danjou.info/guide-python-static-class-abstract-methods/

轉載于:https://www.cnblogs.com/flashBoxer/p/9814012.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/388199.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/388199.shtml
英文地址,請注明出處:http://en.pswp.cn/news/388199.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

廣義估計方程估計方法_廣義估計方程簡介

廣義估計方程估計方法A key assumption underpinning generalized linear models (which linear regression is a type of) is the independence of observations. In longitudinal data this will simply not hold. Observations within an individual (between time points) …

css二

結構性偽類:nth-child(index)系列1.:first-child2.:last-child3.nth-last-child(index)4.only-child :nth-of-type(index)系列1.first-of-type2.last-of-type3.nth-last-type(index)4.only-of-type :not偽類處理導航欄最后一個豎劃線a:not(:last-of-type) :empty偽類 選中所有內…

Unity3d鼠標點擊屏幕來控制人物的走動

今天呢&#xff0c;我們來一起實現一個在RPG中游戲中十分常見的功能&#xff0c;通過鼠標點擊屏幕來控制人物的走動。首先來說一下原理&#xff0c;當我們點擊屏幕時&#xff0c;我們按照一定的方法&#xff0c;將屏幕上的二維坐標轉化為三維坐標&#xff0c;然后我們從攝像機位…

Java中的ReentrantLock和synchronized兩種鎖定機制的對比

2019獨角獸企業重金招聘Python工程師標準>>> 多線程和并發性并不是什么新內容&#xff0c;但是 Java 語言設計中的創新之一就是&#xff0c;它是第一個直接把跨平臺線程模型和正規的內存模型集成到語言中的主流語言。核心類庫包含一個 Thread 類&#xff0c;可以用它…

10.15 lzxkj

幾天前寫的&#xff0c;忘了放了&#xff0c;在此填坑 10月16的題我出的不寫題解了 lzxkj 題目背景 眾所不周知的是&#xff0c; 酒店之王 xkj 一個經常迷失自我的人 有一天&#xff0c; 當起床鈴再一次打響的時候&#xff0c; TA 用 O(1)的時間在 TA 那早就已經生銹的大腦中自…

大數定理 中心極限定理_中心極限定理:直觀的遍歷

大數定理 中心極限定理One of the most beautiful concepts in statistics and probability is Central Limit Theorem,people often face difficulties in getting a clear understanding of this and the related concepts, I myself struggled understanding this during my…

萬惡之源 - Python數據類型二

列表 列表的介紹 列表是python的基礎數據類型之一 ,其他編程語言也有類似的數據類型. 比如JS中的數 組, java中的數組等等. 它是以[ ]括起來, 每個元素用 , 隔開而且可以存放各種數據類型: lst [1,a,True,[2,3,4]]列表相比于字符串,不僅可以存放不同的數據類型.而且可…

230. Kth Smallest Element in a BST

Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.Note: You may assume k is always valid, 1 ≤ k ≤ BSTs total elements.Example 1: Input: root [3,1,4,null,2], k 13/ \1 4\2 Output: 1 Example 2: Input: root …

探索性數據分析(EDA)-不要問如何,不要問什么

數據科學 &#xff0c; 機器學習 (Data Science, Machine Learning) This is part 1 in a series of articles guiding the reader through an entire data science project.這是一系列文章的第1部分 &#xff0c;指導讀者完成整個數據科學項目。 I am a new writer on Medium…

unity3d 攝像機跟隨鼠標和鍵盤的控制

鼠標控制&#xff1a; using UnityEngine; using System.Collections; public class shubiao : MonoBehaviour { //public Transform firepos; public int Ball30; public int CurBall1; public Rigidbody projectile; public Vector3 point; public float time100f; public…

《必然》九、享受重混盛宴,是每個人的機會

今天說的是《必然》的第七個關鍵詞&#xff0c;過濾Filtering。1我們需要過濾如今有一個問題&#xff0c;彌漫在我們的生活當中&#xff0c;困擾著所有人。那就是“今天我要吃什么呢&#xff1f;”同樣的&#xff0c;書店里這么多的書&#xff0c;我要看哪一本呢&#xff1f;網…

IDEA 插件開發入門教程

2019獨角獸企業重金招聘Python工程師標準>>> IntelliJ IDEA 是目前最好用的 JAVA 開發 IDE&#xff0c;它本身的功能已經非常強大了&#xff0c;但是每個人的需求不一樣&#xff0c;有些需求 IDEA 本身無法滿足&#xff0c;于是我們就需要自己開發插件來解決。工欲善…

安卓代碼還是xml繪制頁面_我們應該繪制實際還是預測,預測還是實際還是無關緊要?

安卓代碼還是xml繪制頁面Plotting the actual and predicted data is frequently used for visualizing and analyzing how the actual data correlate with those predicted by the model. Ideally, this should correspond to a slope of 1 and an intercept of 0. However, …

Mecanim動畫系統

本期教程和大家分享Mecanim動畫系統的重定向特性&#xff0c;Mecanim動畫系統是Unity3D推出的全新的動畫系統&#xff0c;具有重定向、可融合等諸多新特性&#xff0c;通過和美工人員的緊密合作&#xff0c;可以幫助程序設計人員快速地設計出角色動畫。一起跟著人氣博主秦元培學…

【嵌入式硬件Esp32】Ubuntu 1804下ESP32交叉編譯環境搭建

一、ESP32概述EPS32是樂鑫最新推出的集成2.4GWi-Fi和藍牙雙模的單芯片方案&#xff0c;采用臺積電(TSMC)超低功耗的40nm工藝&#xff0c;擁有最佳的功耗性能、射頻性能、穩定性、通用性和可靠性&#xff0c;適用于多種應用和不同的功耗要求。 ESP32搭載低功耗的Xtensa LX6 32bi…

你認為已經過時的C語言,是如何影響500萬程序員的?...

看招聘職位要c語言的占比真不多了&#xff0c;是否c語言真得落伍了&#xff1f; 看一下許多招聘平臺有關于找純粹的c語言開發的占比確實沒有很多&#xff0c;都被Java&#xff0c;php&#xff0c;python等等語言刷屏。這對于入門正在學習c語言的小白真他媽就是驚天霹靂&#xf…

換熱站起停條件

循環泵 自動條件&#xff1a; 一、循環泵啟動條件 兩臺泵/三臺泵&#xff1a; 1&#xff09;本循環泵在遠程狀態 2&#xff09;本循環泵自動狀態 3&#xff09;本循環泵沒有故障 4&#xff09;二次網的回水壓力&#xff08;測量值&#xff09;>設定值 5&#xff09;…

云尚制片管理系統_電影制片廠的未來

云尚制片管理系統Data visualization is a key step of any data science project. During the process of exploratory data analysis, visualizing data allows us to locate outliers and identify distribution, helping us to control for possible biases in our data ea…

JAVA單向鏈表實現

JAVA單向鏈表實現 單向鏈表 鏈表和數組一樣是一種最常用的線性數據結構&#xff0c;兩者各有優缺點。數組我們知道是在內存上的一塊連續的空間構成&#xff0c;所以其元素訪問可以通過下標進行&#xff0c;隨機訪問速度很快&#xff0c;但數組也有其缺點&#xff0c;由于數組的…

軟件公司管理基本原則

商業人格&#xff1a;獨立履行責任 獨立堅持原則兩大要素&#xff1a;1)靠原則做事&#xff0c;原則高于一切。2)靠結果做交換&#xff0c;我要什么我清楚兩個標準&#xff1a; 1)我不是孩子&#xff0c;我不需要照顧2)承認邏輯&#xff0c;我履行我的責任社會人心態: 1)用社會…