方法在Python中是如何工作的
創新互聯是一家集網站建設,桐梓企業網站建設,桐梓品牌網站建設,網站定制,桐梓網站建設報價,網絡營銷,網絡優化,桐梓網站推廣為一體的創新建站企業,幫助傳統企業提升企業形象加強企業競爭力??沙浞譂M足這一群體相比中小企業更為豐富、高端、多元的互聯網需求。同時我們時刻保持專業、時尚、前沿,時刻以成就客戶成長自我,堅持不斷學習、思考、沉淀、凈化自己,讓我們為更多的企業打造出實用型網站。
方法就是一個函數,它作為一個類屬性而存在,你可以用如下方式來聲明、訪問一個函數:
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在告訴你,屬性_get_size是類Pizza的一個未綁定方法。這是什么意思呢?很快我們就會知道答案:
Python
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)
我們不能這么調用,因為它還沒有綁定到Pizza類的任何實例上,它需要一個實例作為第一個參數傳遞進去(Python2必須是該類的實例,Python3中可以是任何東西),嘗試一下:
Python
Pizza.get_size(Pizza(42))
42
Pizza.get_size(Pizza(42))
42
太棒了,現在用一個實例作為它的的第一個參數來調用,整個世界都清靜了,如果我說這種調用方式還不是最方便的,你也會這么認為的;沒錯,現在每次調用這個方法的時候我們都不得不引用這個類,如果不知道哪個類是我們的對象,長期看來這種方式是行不通的。
那么Python為我們做了什么呢,它綁定了所有來自類_Pizza的方法以及該類的任何一個實例的方法。也就意味著現在屬性get_size是Pizza的一個實例對象的綁定方法,這個方法的第一個參數就是該實例本身。
Python
Pizza(42).get_size
bound method Pizza.get_size of __main__.Pizza object at 0x7f3138827910
Pizza(42).get_size()
42
和我們預期的一樣,現在不再需要提供任何參數給_get_size,因為它已經是綁定的,它的self參數會自動地設置給Pizza實例,下面代碼是最好的證明:
Python
m = Pizza(42).get_size
m()
42
更有甚者,你都沒必要使用持有Pizza對象的引用了,因為該方法已經綁定到了這個對象,所以這個方法對它自己來說是已經足夠了。
也許,如果你想知道這個綁定的方法是綁定在哪個對象上,下面這種手段就能得知:
Python
m = Pizza(42).get_size
m.__self__
__main__.Pizza object at 0x7f3138827910
# You could guess, look at this:
...
m == m.__self__.get_size
True
顯然,該對象仍然有一個引用存在,只要你愿意你還是可以把它找回來。
在Python3中,依附在類上的函數不再當作是未綁定的方法,而是把它當作一個簡單地函數,如果有必要它會綁定到一個對象身上去,原則依然和Python2保持一致,但是模塊更簡潔:
Python
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
靜態方法
靜態方法是一類特殊的方法,有時你可能需要寫一個屬于這個類的方法,但是這些代碼完全不會使用到實例對象本身,例如:
Python
class Pizza(object):
@staticmethod
def mix_ingredients(x, y):
return x + y
def cook(self):
return self.mix_ingredients(self.cheese, self.vegetables)
這個例子中,如果把_mix_ingredients作為非靜態方法同樣可以運行,但是它要提供self參數,而這個參數在方法中根本不會被使用到。這里的@staticmethod裝飾器可以給我們帶來一些好處:
Python不再需要為Pizza對象實例初始化一個綁定方法,綁定方法同樣是對象,但是創建他們需要成本,而靜態方法就可以避免這些。
Python
Pizza().cook is Pizza().cook
False
Pizza().mix_ingredients is Pizza.mix_ingredients
True
Pizza().mix_ingredients is Pizza().mix_ingredients
True
可讀性更好的代碼,看到@staticmethod我們就知道這個方法并不需要依賴對象本身的狀態。
可以在子類中被覆蓋,如果是把mix_ingredients作為模塊的頂層函數,那么繼承自Pizza的子類就沒法改變pizza的mix_ingredients了如果不覆蓋cook的話。
類方法
話雖如此,什么是類方法呢?類方法不是綁定到對象上,而是綁定在類上的方法。
Python
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 is Pizza().get_radius
True
Pizza.get_radius()
42
無論你用哪種方式訪問這個方法,它總是綁定到了這個類身上,它的第一個參數是這個類本身(記住:類也是對象)。
什么時候使用這種方法呢?類方法通常在以下兩種場景是非常有用的:
工廠方法:它用于創建類的實例,例如一些預處理。如果使用@staticmethod代替,那我們不得不硬編碼Pizza類名在函數中,這使得任何繼承Pizza的類都不能使用我們這個工廠方法給它自己用。
Python
class Pizza(object):
def __init__(self, ingredients):
self.ingredients = ingredients
@classmethod
def from_fridge(cls, fridge):
return cls(fridge.get_cheese() + fridge.get_vegetables())
調用靜態類:如果你把一個靜態方法拆分成多個靜態方法,除非你使用類方法,否則你還是得硬編碼類名。使用這種方式聲明方法,Pizza類名明永遠都不會在被直接引用,繼承和方法覆蓋都可以完美的工作。
Python
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)
抽象方法
抽象方法是定義在基類中的一種方法,它沒有提供任何實現,類似于Java中接口(Interface)里面的方法。
在Python中實現抽象方法最簡單地方式是:
Python
class Pizza(object):
def get_radius(self):
raise NotImplementedError
任何繼承自_Pizza的類必須覆蓋實現方法get_radius,否則會拋出異常。
這種抽象方法的實現有它的弊端,如果你寫一個類繼承Pizza,但是忘記實現get_radius,異常只有在你真正使用的時候才會拋出來。
Python
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_radius
NotImplementedError
還有一種方式可以讓錯誤更早的觸發,使用Python提供的abc模塊,對象被初始化之后就可以拋出異常:
Python
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get_radius(self):
"""Method that should do something."""
使用abc后,當你嘗試初始化BasePizza或者任何子類的時候立馬就會得到一個TypeError,而無需等到真正調用get_radius的時候才發現異常。
Python
BasePizza()
Traceback (most recent call last):
File "stdin", line 1, in module
TypeError: Can't instantiate abstract class BasePizza with abstract methods get_radius
混合靜態方法、類方法、抽象方法
當你開始構建類和繼承結構時,混合使用這些裝飾器的時候到了,所以這里列出了一些技巧。
記住,聲明一個抽象的方法,不會固定方法的原型,這就意味著雖然你必須實現它,但是我可以用任何參數列表來實現:
Python
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
這樣是允許的,因為Calzone滿足BasePizza對象所定義的接口需求。同樣我們也可以用一個類方法或靜態方法來實現:
Python
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
這同樣是正確的,因為它遵循抽象類BasePizza設定的契約。事實上get_ingredients方法并不需要知道返回結果是什么,結果是實現細節,不是契約條件。
因此,你不能強制抽象方法的實現是一個常規方法、或者是類方法還是靜態方法,也沒什么可爭論的。從Python3開始(在Python2中不能如你期待的運行,見issue5867),在abstractmethod方法上面使用@staticmethod和@classmethod裝飾器成為可能。
Python
import abc
class BasePizza(object):
__metaclass__ = abc.ABCMeta
ingredient = ['cheese']
@classmethod
@abc.abstractmethod
def get_ingredients(cls):
"""Returns the ingredient list."""
return cls.ingredients
別誤會了,如果你認為它會強制子類作為一個類方法來實現get_ingredients那你就錯了,它僅僅表示你實現的get_ingredients在BasePizza中是一個類方法。
可以在抽象方法中做代碼的實現?沒錯,Python與Java接口中的方法相反,你可以在抽象方法編寫實現代碼通過super()來調用它。(譯注:在Java8中,接口也提供的默認方法,允許在接口中寫方法的實現)
Python
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()
這個例子中,你構建的每個pizza都通過繼承BasePizza的方式,你不得不覆蓋get_ingredients方法,但是能夠使用默認機制通過super()來獲取ingredient列表。
Python——Lambda表達式是一個匿名函數,Lambda 表達式基于數學中的lambda演算得名,直接對應于其中的 lambda 抽象,是一個匿名函數,即沒有函數名的函數。
Python由荷蘭數學和計算機科學研究學會的Guido van Rossum 于1990 年代初設計,作為一門叫做ABC語言的替代品。Python提供了高效的高級數據結構,還能簡單有效地面向對象編程。
Python語法和動態類型,以及解釋型語言的本質,使它成為多數平臺上寫腳本和快速開發應用的編程語言,隨著版本的不斷更新和語言新功能的添加,逐漸被用于獨立的、大型項目的開發。
python的發展歷程:
自從20世紀90年代初Python語言誕生至今,它已被逐漸廣泛應用于系統管理任務的處理和Web編程。
Python的創始人為荷蘭人吉多·范羅蘇姆。1989年圣誕節期間,在阿姆斯特丹,Guido為了打發圣誕節的無趣,決心開發一個新的腳本解釋程序,作為ABC語言的一種繼承。之所以選中Python(作為該編程語言的名字,是取自英國20世紀70年代首播的電視喜劇《蒙提·派森的飛行馬戲團》。
ABC是由Guido參加設計的一種教學語言。就Guido本人看來,ABC這種語言非常優美和強大,是專門為非專業程序員設計的。但是ABC語言并沒有成功,究其原因,Guido認為是其非開放造成的。Guido決心在Python中避免這一錯誤。同時,他還想實現在ABC中閃現過但未曾實現的東西。
在 Python 中創建一個類及其對象
在 Python 中創建一個空類
在 Python 中使用 Type 創建類
在 Python 中創建和調用類的方法
使用 __init__() 方法為數據屬性賦值
在 Python 中更新對象屬性
在 Python 中刪除對象屬性和對象
在 Python 中檢查和比較對象的類型
在Python中將對象的所有屬性復制到另一個對象
在 Python 中迭代對象屬性
在 Python 中打印對象的所有屬性
在python中在運行時創建類的數據屬性
在函數中將對象的實例作為參數傳遞
在 Python 中創建和使用自定義 Self 參數
使用self參數來維護對象的狀態
在 Python 中創建和使用靜態類變量
在 Python 中的一個函數上使用多個裝飾器
在 Python 中的方法中同時訪問 cls 和 self
從裝飾器訪問實例方法的類
使用給定的裝飾器獲取 Python 類的所有方法
裝飾一個 class
將類字段作為參數傳遞給類方法上的裝飾器
在 Python 中創建多個傳入參數列表的類變量
Python 中的 wraps 裝飾器
使用可選參數構建裝飾器
在 Python 中將參數傳遞給裝飾器
@property 裝飾器
類和函數的裝飾器
Python 中帶參數和返回值的裝飾器
Python 使用參數 wraps 裝飾器
Python 裝飾器獲取類名
簡單裝飾器示例
在 Python 中使用 print() 打印類的實例
在 Python 中的類中將裝飾器定義為方法
獲取在 Python 中修飾的給定類的所有方法
帶參數和不帶參數的 Python 裝飾器
Python 中帶有 self 參數的類方法裝飾器
在 Python 中的另一個類中使用隱藏的裝飾器
裝飾器內部的 self 對象
在 Python 中將多個裝飾器應用于單個函數
Python 裝飾器獲取類實例
__init__ 和 __call__ 有什么區別
在 Python 中使用 __new__ 和 __init__
Python 中的迭代重載方法
在 Python 中使用迭代器反轉字符串
Python 中 __reversed__ 魔術方法
Python 中的 __getitem__ 和 __setitem__
在 Python 中使用 __getattr__ 和 __setattr__ 進行屬性賦值
什么是 __del__ 方法以及如何調用它
創建類的私有成員
一個 Python 封裝的例子
一個 Python 組合的例子
一個Python聚合的例子
Python 中的單級、多級和多級繼承
在 Python 中獲取一個類的父類
Python 中的多態性
訪問 Child 類中的私有成員
Python 中的抽象類
創建一個抽象類來覆蓋 Python 中的默認構造函數
使一個抽象類繼承另一個抽象類
Python 中的 super 是做什么的
super() 如何在多重繼承中與 __init__() 方法一起工作
將 super 與類方法一起使用
mro 是做什么的
Python 中的元類是什么
元類的具體案例
在 Python 中使用元類的單例類
@staticmethod 和 @classmethod 有什么區別
Python 中的裝飾器是什么
制作函數裝飾器鏈
網站題目:python實驗抽象函數的簡單介紹
網站路徑:http://m.newbst.com/article8/dogocop.html
成都網站建設公司_創新互聯,為您提供動態網站、域名注冊、靜態網站、關鍵詞優化、服務器托管、手機網站建設
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯