導航:首頁 > 編程語言 > pythonunbound

pythonunbound

發布時間:2023-06-05 08:16:17

『壹』 python如何調用自定義類中的函數

你好:
你要在自定義的函數裡面的第一個參數設置為:
self
這是python約定的;
調用的時候可以不用管它,它相當於this!

『貳』 如何在Python中使用static,class,abstract方法

方法在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在告訴你,屬性_get_size是類Pizza的一個未綁定方法。這是什麼意思呢?很快我們就會知道答案:

Python

>>> Pizza.get_size()
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
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 <mole>
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 <mole>
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中可以直接用類調用方法嗎

這里先肯定的回答一下:可以

python里方法在類中是作為類的屬性的,在解釋之前,這邊先給個例子

>>>classPizza(object):
...radius=42
...def__init__(self,size=10):
...self.size=size
...defget_size(self):
...returnself.size
...@staticmethod
...defmix_ingredients(x,y):
...returnx+y
...defcook(self):
...returnself.mix_ingredients(self.cheese,self.vegetables)
...@classmethod
...defget_radius(cls):
...returncls.radius
>>>Pizza.get_size
<unboundmethodPizza.get_size>
>>>Pizza.get_size()
Traceback(mostrecentcalllast):
File"<stdin>",line1,in<mole>
TypeError:unboundmethodget_size()(gotnothinginstead)
>>>Pizza.get_size(Pizza(42))
42
>>>Pizza(42).get_size
<boundmethodPizza.get_sizeof<__main__.Pizzaobjectat0x7f3138827910>>
>>>Pizza(42).get_size()
42
>>>m=Pizza(42).get_size
>>>m()
42
>>>m=Pizza(42).get_size
>>>m.__self__
<__main__.Pizzaobjectat0x7f3138827910>
>>>m==m.__self__.get_size
True
>>>Pizza().cookisPizza().cook
False
>>>Pizza().mix_ingredientsisPizza.mix_ingredients
True
>>>Pizza().mix_ingredientsisPizza().mix_ingredients
True
>>>Pizza.get_radius
<boundmethodtype.get_radiusof<class'__main__.Pizza'>>
>>>Pizza().get_radius
<boundmethodtype.get_radiusof<class'__main__.Pizza'>>
>>>Pizza.get_radiusisPizza().get_radius
True
>>>Pizza.get_radius()
42

在上面的例子中可以看出python中類有三種方法,分別是類方法,靜態方法,實例方法。而能讓類只接調用的只有類方法,或通過一些小技巧,類也可以調用實例方法如上面例子中的調用

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

這邊順便說明下這三中方法的區別

1類方法的特點是類方法不屬於任何該類的對象,只屬於類本身

2類的靜態方法類似於全局函數,因為靜態方法既沒有實例方法的self參數也沒有類方法的cls參數,誰都可以調用

3.實例方法只屬於實例,是實例化的對象才能調用

『肆』 python中怎樣判斷一個文件的類型

這種方法叫做調用父類的未綁定的構造方法。在調用一個實例的方法時,該方法的self參數會被自動綁定到實例上(稱為綁定方法)。
但如果直接調用類的方法(比如A.__init),那麼就沒有實例會被綁定。這樣就可以自由的提供需要的self參數,這種方法稱為未綁定unbound方法。

『伍』 Python中為什麼推薦使用isinstance來進行類型判斷

Python在定義變數的時候不用指明具體的的類型,解釋器會在運行的時候會自動檢查 變數的類型,並根據需要進行隱式的類型轉化。因為Python是動態語言,所以一般情 況下是不推薦進行類型轉化的。比如"+"操作時,如果加號兩邊是數據就進行加法操 作,如果兩邊是字元串就進行字元串連接操作,如果兩邊是列表就進行合並操作,甚 至可以進行復數的運算。解釋器會在運行時根據兩邊的變數的類型調用不同的內部方法。 當加號兩邊的變數類型不一樣的時候,又不能進行類型轉化,就會拋出TypeError的異常。
但是在實際的開發中,為了提高代碼的健壯性,我們還是需要進行類型檢查的。而進行 類型檢查首先想到的就是用type(),比如使用type判斷一個int類型。
import typesif type(1) is types.Integer: print('1是int類型')else: print('1不是int類型')

上面的程序會輸出:1是int類型
我們在types中可以找到一些常用的類型,在2.7.6中顯示的結果:
types.BooleanType # bool類型types.BufferType # buffer類型types.BuiltinFunctionType # 內建函數,比如len()types.BuiltinMethodType # 內建方法,指的是類中的方法types.ClassType # 類類型types.CodeType # 代碼塊類型types.ComplexType # 復數類型types.DictProxyType # 字典代理類型types.DictType # 字典類型types.DictionaryType # 字典備用的類型types.EllipsisTypetypes.FileType # 文件類型types.FloatType # 浮點類型types.FrameTypetypes.FunctionType # 函數類型types.GeneratorType
types.GetSetDescriptorTypetypes.InstanceType # 實例類型types.IntType # int類型types.LambdaType # lambda類型types.ListType # 列表類型types.LongType # long類型types.MemberDescriptorTypetypes.MethodType # 方法類型types.MoleType # mole類型types.NoneType # None類型types.NotImplementedTypetypes.ObjectType # object類型types.SliceTypehtypes.StringType # 字元串類型types.StringTypes
types.TracebackType
types.TupleType # 元組類型types.TypeType # 類型本身types.UnboundMethodTypetypes.UnicodeType
types.XRangeType

在Python 3中,類型已經明顯減少了很多
types.BuiltinFunctionType
types.BuiltinMethodType
types.CodeType
types.DynamicClassAttribute
types.FrameType
types.FunctionType
types.GeneratorType
types.GetSetDescriptorType
types.LambdaType
types.MappingProxyType
types.MemberDescriptorType
types.MethodType
types.MoleType
types.SimpleNamespace
types.TracebackType
types.new_class
types.prepare_class

但是我們並不推薦使用type來進行類型檢查,之所以把這些類型列出來,也是為了擴展知識 面。那為什麼不推薦使用type進行類型檢查呢?我們來看一下下面的例子。
import typesclass UserInt(int): def __init__(self, val=0): self.val = int(val)i = 1n = UserInt(2)print(type(i) is type(n))

上面的代碼輸出:False
這就說明i和n的類型是不一樣的,而實際上UserInt是繼承自int的,所以這個判斷是存在問題的, 當我們對Python內建類型進行擴展的時候,type返回的結果就不夠准確了。我們再看一個例子。
class A(): passclass B(): passa = A()b = B()print(type(a) is type(b))

代碼的輸出結果: True
type比較的結果a和b的類型是一樣的,結果明顯是不準確的。這種古典類的實例,type返回的結果都 是一樣的,而這樣的結果不是我們想要的。對於內建的基本類型來說,使用tpye來檢查是沒有問題的, 可是當應用到其他場合的時候,type就顯得不可靠了。這個時候我們就需要使用isinstance來進行類型 檢查。
isinstance(object, classinfo)

object表示實例,classinfo可以是直接或間接類名、基本類型或者有它們組成的元組。
>>> isinstance(2, float)
False
>>> isinstance('a', (str, unicode))
True
>>> isinstance((2, 3), (str, list, tuple))
True

『陸』 本人python新手,現在在看python基礎教程,這幾天敲了一下後面的項目5,出現了很奇怪的錯誤,大神幫看看

Room.add(self)這一句改成
Room().add()
當然,只是一個比喻,具體怎麼樣改,還要看你的程序。
Room是一個類,除非它有特殊的方法。否則不能使用Room.add這樣的方法,在python不讓。

你可以先實例化Room,比如Room(),然後在這個實例上就可以使用權Room().add()

此外你Room.add(self)里的self顯然不是Room實例,否則也許能成功。

『柒』 Python中靜態方法和類方法的區別

面相對象程序設計中,類方法和靜態方法是經常用到的兩個術語。
邏輯上講:類方法是只能由類名調用;靜態方法可以由類名或對象名進行調用。
在C++中,靜態方法與類方法邏輯上是等價的,只有一個概念,不會混淆。
而在python中,方法分為三類實例方法、類方法、靜態方法。代碼如下:
class Test(object):
def InstanceFun(self):
print("InstanceFun");
print(self);
@classmethod
def ClassFun(cls):
print("ClassFun");
print(cls);
@staticmethod
def StaticFun():
print("StaticFun");
t = Test();
t.InstanceFun();# 輸出InstanceFun,列印對象內存地址「」
Test.ClassFun(); # 輸出ClassFun,列印類位置
Test.StaticFun(); # 輸出StaticFun
t.StaticFun(); # 輸出StaticFun
t.ClassFun(); # 輸出ClassFun,列印類位置
Test.InstanceFun(); # 錯誤,TypeError: unbound method instanceFun() must be called with Test instance as first argument

Test.InstanceFun(t); # 輸出InstanceFun,列印對象內存地址「」
t.ClassFun(Test); # 錯誤 classFun() takes exactly 1 argument (2 given)
可以看到,在PYTHON中,兩種方法的主要區別在於參數。實例方法隱含的參數為類實例self,而類方法隱含的參數為類本身cls。
靜態方法無隱含參數,主要為了類實例也可以直接調用靜態方法。

所以邏輯上類方法應當只被類調用,實例方法實例調用,靜態方法兩者都能調用。主要區別在於參數傳遞上的區別,實例方法悄悄傳遞的是self引用作為參數,而類方法悄悄傳遞的是cls引用作為參數。
Python實現了一定的靈活性使得類方法和靜態方法,都能夠被實例和類二者調用

閱讀全文

與pythonunbound相關的資料

熱點內容
C面向切面編程aop例子 瀏覽:368
windowsrar命令 瀏覽:379
單片機編程語言有哪些 瀏覽:441
蘋果安卓系統筆記本怎麼設置密碼 瀏覽:982
只能加密不能解密有什麼用 瀏覽:239
怎麼製造app 瀏覽:121
電腦解壓死機了怎麼辦 瀏覽:607
歐洲伺服器雲進銷存 瀏覽:192
程序員python和java 瀏覽:949
文件夾怎麼插入幻燈 瀏覽:282
帶孩子到崩潰怎麼解壓 瀏覽:63
戰地一被踢出伺服器會顯示什麼 瀏覽:837
怎麼看手機上所有的app 瀏覽:365
網路拚命令怎麼拼 瀏覽:836
產品經理和程序員優先選哪個 瀏覽:393
樸素的app應用怎麼推廣 瀏覽:586
怎麼查校園卡app專屬流量 瀏覽:437
少兒編程教育培訓視頻 瀏覽:562
華為平板如何裝兩個一樣的app 瀏覽:728
程序員與劫匪 瀏覽:623