5 回答

TA貢獻1786條經(jīng)驗 獲得超13個贊
將用戶定義的方法設置為類的屬性,這是錯誤的方式
考慮以下示例類A和函數(shù)f:
class A:
pass
def f(self):
print("I\'m in user-defined function")
a = A()
該函數(shù)f是單獨定義的,不在類內(nèi)部。
假設您想添加函數(shù)f作為a對象的實例方法。
f通過設置為屬性來添加它a是行不通的:
import types
class A:
pass
def f(self):
print("I\'m in user-defined function")
a = A()
a.f = f
# <function f at 0x000002D81F0DED30>
print(a.f)
# TypeError: f() missing 1 required positional argument: 'self'
# a.f()
因為函數(shù)f沒有綁定到對象a。
這就是為什么在調(diào)用a.f()它時會引發(fā)有關缺少參數(shù)的錯誤(如果f已綁定到a,則該對象a就是缺少參數(shù)self)。
這部分是文檔提到的內(nèi)容:
還需要注意的是,作為類實例屬性的用戶定義函數(shù)不會轉換為綁定方法。
f當然,如果 function已在 class 內(nèi)定義,則所有這一切都不會發(fā)生A,這就是文檔中的以下部分所述:
...只有當函數(shù)是類的屬性時才會發(fā)生這種情況。
將用戶定義的方法設置為類的屬性,正確的方法
要將函數(shù)添加f到對象,a您應該使用:
import types
class A:
pass
def f(self):
print("I\'m in user-defined function")
a = A()
a.f = types.MethodType( f, a )
# <bound method f of <__main__.A object at 0x000001EDE4768E20>>
print(a.f)
# Works! I'm in user-defined function
a.f()
它將用戶定義的方法綁定f到實例a。

TA貢獻2016條經(jīng)驗 獲得超9個贊
當您以通常的方式創(chuàng)建一個方法時,它將是一個綁定方法:它接收實例作為第一個參數(shù)(我們通常將其分配給“self”):
class A:
def meth(*args):
print(args)
a = A()
a.meth()
# (<__main__.A object at 0x7f56a137fd60>,)
如果您采用一個普通函數(shù)并將其添加到類屬性中,它將以相同的方式工作:
def f(*args):
print(args)
A.f = f
a = A()
a.f()
# (<__main__.A object at 0x7f56a137f700>,)
實例作為第一個參數(shù)傳遞,它是一個綁定方法。
另一方面,如果您將函數(shù)作為類實例的屬性,則它將不是綁定方法=調(diào)用時不會將實例作為第一個參數(shù)傳遞:
a = A()
a.f = f
a.f()
# ()

TA貢獻1854條經(jīng)驗 獲得超8個贊
我不認為花哨的形式邏輯符號在這里有幫助。
然而,要回答這個問題:“作為類實例的屬性的用戶定義函數(shù)不會轉換為綁定方法;只有當函數(shù)是類的屬性時才會發(fā)生這種情況”是什么意思?
綁定方法是依賴于類的實例作為第一個參數(shù)的方法。它將實例作為第一個參數(shù)傳遞,用于訪問變量和函數(shù)。在 Python 3 和更高版本的 python 中,類中的所有函數(shù)默認都是綁定方法。
因此,如果您創(chuàng)建用戶定義函數(shù)作為類實例的屬性,它不會自動轉換為綁定方法。“類實例”只是 Python 中表達“對象”或“對象實例”在其他語言中含義的一種方式。
例如:
class HelloClass:
greeting = 'Hello'
def greet(self, name):
print(f'{greeting} {name}')
hc = HelloClass()
hc.greet('John')
這HelloClass是類,而hc是類實例。greet是一個綁定方法,至少需要一個參數(shù)(按照約定調(diào)用),該參數(shù)在調(diào)用時自動分配給類實例 - 即打印之前self的值是類實例。selfhello Johnhc
現(xiàn)在,如果你嘗試這樣做:
def greet_with_hi(self, name):
print(f'Hi {name}')
class HiClass:
greet = greet_with_hi
hc = HiClass()
hc.greet('John')
這可行(盡管你的 IDE 可能會反對),但這根本不起作用:
def greet_with_hi(self, name):
print(f'Hi {name}')
class HiClass:
def __init__(self):
self.greet = greet_with_hi
hc = HiClass()
hc.greet('John')
它導致TypeError: greet_with_hi() missing 1 required positional argument: 'name'. 它應該,因為.greet在 的實例上HiClass不是綁定方法,并且self greet_with_hi期望不會自動填充。

TA貢獻1836條經(jīng)驗 獲得超3個贊
我認為最好通過例子來闡明其含義。
假設我們有一個包含各種屬性的類實例,這些屬性是用戶定義的函數(shù)。
add1
通過將其定義為類定義的一部分來添加。add2
在實例化之前通過對類進行猴子修補來添加。add3
通過在實例化后對類進行猴子修補來添加add4
通過在實例化后對實例進行猴子修補來添加
class Number:
def __init__(self, x):
self.x = x
def add1(self):
return self.x + 1
def add2(self):
return self.x + 2
def add3(self):
return self.x + 3
def add4(self):
return self.x + 4
setattr(Number, 'add2', add2)
two = Number(2)
setattr(Number, 'add3', add3)
setattr(two, 'add4', add4)
print(two.add1()) # prints 3
print(two.add2()) # prints 4
print(two.add3()) # prints 5
print(two.add4()) # TypeError: add4() missing 1 required positional argument: 'self'
我們嘗試調(diào)用這些。
前三個都有效(在add3實例化時它不是類的屬性甚至沒有關系)。
請注意,當我們調(diào)用這些函數(shù)時,我們不會顯式傳遞與函數(shù)內(nèi)第一個位置參數(shù)相對應的任何內(nèi)容(即self)——它會自動為我們添加。這就是綁定方法的含義。它是用一個位置參數(shù)聲明的,而我們明確不傳遞任何位置參數(shù)。
但在這種情況下,add4它會抱怨缺少位置參數(shù) - 這是因為該實例不會自動添加為第一個參數(shù)。(如果你明確使用它就會起作用two.add4(two)。)

TA貢獻1780條經(jīng)驗 獲得超4個贊
綁定方法 python 綁定方法是依賴于類的實例作為第一個參數(shù)的方法。它將實例作為第一個參數(shù)傳遞,用于訪問變量和函數(shù)。在 Python 3 和更高版本的 python 中,類中的所有函數(shù)默認都是綁定方法。
讓我們通過一個例子來理解這個概念:
# Python code to demonstrate
# use of bound methods
class A:
def func(self, arg):
self.arg = arg
print("Value of arg = ", arg)
# Creating an instance
obj = A()
# bound method
print(obj.func)
Output:
< bound method A.func of <__main__.A object at 0x7fb81c5a09e8>>
這里,
obj.func(arg) 由 python 翻譯為 A.func(obj, arg)。實例 obj 自動作為第一個參數(shù)傳遞給被調(diào)用的函數(shù),因此函數(shù)的第一個參數(shù)將用于訪問對象的變量/函數(shù)。
讓我們看一下 Bound 方法的另一個示例。
# Python code to demonstrate
# use of bound methods
class Car:
# Car class created
gears = 5
# a class method to change the number of gears
@classmethod
def change_gears(cls, gears):
cls.gears = gears
# instance of class Car created
Car1 = Car()
print("Car1 gears before calling change_gears() = ", Car1.gears)
Car1.change_gears(6)
print("Gears after calling change_gears() = ", Car1.gears)
# bound method
print(Car1.change_gears)
Output:
Car1 gears before calling change_gears() = 5
Gears after calling change_gears() = 6
<bound method Car.change_gears of <class '__main__.Car'>>
上面的代碼是類方法的示例。類方法類似于綁定方法,只不過實例的類作為參數(shù)而不是實例本身傳遞。在上面的示例中,當我們調(diào)用 Car1.change_gears(6) 時,類“Car”作為第一個參數(shù)傳遞。
對這些綁定方法的需求 類內(nèi)的方法至少需要一個參數(shù)。為了使它們成為零參數(shù)方法,必須使用“裝飾器”。類的不同實例具有與其關聯(lián)的不同值。
例如,如果有一個類“Fruits”,那么像蘋果、橙子、芒果這樣的實例都是可能的。每個實例可能有不同的大小、顏色、味道和營養(yǎng)成分。因此,要更改特定實例的任何值,該方法必須將“self”作為參數(shù),以允許它僅更改其屬性。
例子:
class sample(object):
# Static variable for object number
objectNo = 0
def __init__(self, name1):
# variable to hold name
self.name = name1
# Increment static variable for each object
sample.objectNo = sample.objectNo + 1
# each object's unique number that can be
# considered as ID
self.objNumber = sample.objectNo
def myFunc(self):
print("My name is ", self.name,
"from object ", self.objNumber)
def alterIt(self, newName):
self.name = newName
def myFunc2():
print("I am not a bound method !!!")
# creating first instance of class sample
samp1 = sample("A")
samp1.myFunc()
# unhide the line below to see the error
# samp1.myFunc2() #----------> error line
# creating second instance of class sample
samp2 = sample("B")
samp2.myFunc()
samp2.alterIt("C")
samp2.myFunc()
samp1.myFunc()
Output:
My name is A from object 1
My name is B from object 2
My name is C from object 2
My name is A from object 1
在上面的示例中,創(chuàng)建了兩個實例,即 samp1 和 samp2。請注意,當函數(shù) alterIt() 應用于第二個實例時,僅更改該特定實例的值。samp1.myFunc() 行將擴展為sample.myFunc(samp1)。對于此方法,不需要傳遞顯式參數(shù)。實例 samp1 將作為參數(shù)傳遞給 myFunc()。samp1.myFunc2() 行將生成錯誤:
Traceback (most recent call last):
File "/home/4f130d34a1a72402e0d26bab554c2cf6.py", line 26, in
samp1.myFunc2() #----------> error line
TypeError: myFunc2() takes 0 positional arguments but 1 was given
這意味著該方法是未綁定的。它不接受任何實例作為參數(shù)。這些函數(shù)是未綁定函數(shù)。
添加回答
舉報