[英]How is the self argument magically passed to instance methods?
我正在做代碼學院流,我有一點Ruby經驗。 我不明白為什么check_angles(self)
函數需要self
參數。
我感到困惑的原因是我不明白在調用函數時是什么將self參數傳遞給函數。 似乎函數調用(代碼塊的最后一行)是隱式傳遞,但該函數需要將self明確定義為參數。
為什么是這樣?
class Triangle(object):
def __init__(self, angle1, angle2, angle3):
self.angle1 = angle1
self.angle2 = angle2
self.angle3 = angle3
number_of_sides = 3
def check_angles(self):
sum_angles = self.angle1 + self.angle2 + self.angle3
if sum_angles == 180:
return True
else:
return False
tri = Triangle(45,34,78)
tri.check_angles(EMPTY BUT WHY)
這在Python中的工作方式是,一旦你使用方法bar(self)
實例化一個類Foo
,用於創建方法的函數將包裝在instancemethod
類型的對象中,該對象將它“綁定”到實例,以便調用foo_inst.bar()
實際上調用了Foo.bar(foo_inst)
。
class Foo(object):
def bar(self):
print "called bar on %s" % self
foo_inst = Foo()
# these 2 calls are equivalent
foo_inst.bar()
Foo.bar(foo_inst)
或者,以交互方式:
>>> Foo.bar
<unbound method Foo.bar>
>>> Foo().bar
<bound method Foo.bar of <__main__.Foo object at 0x10675ecd0>>
所以你可以看到,雖然仍然直接附加到類, bar
是一個未綁定的方法 ,但仍然有self
參數,但是,當從Foo
實例檢索方法對象時,它已成為一個綁定方法,其self
參數已經預先-set到從中檢索方法對象的實例。
這也是為什么self
可以被稱為任何你想要的東西,如arg0
(或stifflersmom
或allyourbase
)。
另請參閱 Python描述符@ https://docs.python.org/2/howto/descriptor.html ,了解其實現方式以及如何自行實現類似方案。
事實上,在這個例子中,方法實際上是功能更加明顯:
class Foo(object):
pass
def bar(arg0):
print "called bar with %s" % arg0
Foo.bar = bar
Foo().bar() # prints: called bar with <Foo object at 0x10675b2d0>
注意:在聲明了類對象之后將它們分配給類對象(稱為monkeypatching)並不是動態語言(如Python)中推薦的編程風格,因為它是A)容易出錯(可能會覆蓋同一類的未來版本中的某些內容,因為沒有編譯器來驗證不是這種情況)和B)難以理解(不可能通過查看類定義來知道類的實例具有哪些實例,因為沒有編譯器/ IDE來查找添加的方法)。
當你調用tri.check_angles()
你會感到困惑,因為函數check_angles
只有一個參數。 事實上,你是對的。 tri
是作為self
傳遞的論證。
self
在類中用於保存類的特定實例的本地變量。
class A():
def __init__(self):
self.x = 2
>>> a = A()
>>> b = A()
>>> print a.x
2
>>> print b.x
2
>>> a.x = 5
>>> print a.x
5
>>> print b.x
2
然而,如果您只有x
而不是self.x
並且您為一個實例更改了x
的值,則所有實例的x
值都將更改。
希望有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.