[英]Initializing field outside __init__
我需要一點幫助來了解python初始化的工作原理。 我有一個班級(Bar),另一個班級(Foo)作為字段/變量。 當我嘗試直接在Bar中初始化此變量(而不是在類__init__中)時,Bar的所有實例都指向同一Foo。 但是,如果我有一個__init__方法(如Bar2),則每個Bar2實例將具有一個唯一的Foo實例。 這是怎么回事
class Foo():
number = 0
class Bar():
foo = Foo()
class Bar2():
foo = None
def __init__(self):
self.foo = Foo()
first = Bar()
second = Bar()
print "Bar"
print first
print second
print first.foo
print second.foo
first = Bar2()
second = Bar2()
print "\nBar2"
print first
print second
print first.foo
print second.foo
例如,輸出將是:
Bar
<\__main__.Bar instance at 0x025B2AF8>
<\__main__.Bar instance at 0x025B2B20>
<\__main__.Foo instance at 0x004A3AA8>
<\__main__.Foo instance at 0x004A3AA8>
Bar2
<\__main__.Bar2 instance at 0x025B2B48>
<\__main__.Bar2 instance at 0x025B2AF8>
<\__main__.Foo instance at 0x025B2B70>
<\__main__.Foo instance at 0x025B2B98>
使用Bar,兩個實例將引用相同的Foo實例。 為什么?
編輯:更正了Bar兩次打印first.foo的錯誤。 產生的行為仍然如輸出所示。
Bar.foo
是一個類變量。 創建類后,它將初始化一次。
(請注意,您的代碼first.foo
打印first.foo
兩次,所以難怪輸出是一樣的。)
Python是一種動態語言。 在Java之類的靜態語言中,編譯器讀取代碼,查找類定義,弄清楚它們是否正確,並相應地生成一些代碼。 在python中,類定義(或函數定義)就像其他任何聲明一樣,就像對變量的賦值一樣。 語法略有不同。
定義類時,解釋器運行類定義,即,它在類行之后運行所有代碼。 如果找到函數定義,它也會運行它們,即定義函數並將它們綁定到函數名稱。 由於類和函數定義與其他任何賦值一樣都是語句,因此也可以在許多地方使用它們。 例如如下:
def foo():
class A: pass
a = A()
a.msg = "Hello"
return a
因為python是鴨子類型的(如果它像鴨子一樣嘎嘎叫起來,看起來像一只鴨子,那是一個),所以foo函數的用戶甚至不必知道該類是什么,他們只需要知道foo返回一個對象即可與成員味精。 您可以這樣使用它:
a = foo()
print a.msg
因此,在您的示例中,執行Bar的定義時,將運行classes語句,包括創建Foo對象。 當執行Bar2的定義時,將在其中運行class語句的名為init的函數的定義。 創建對象時,Python使用此名稱作為要調用的函數的名稱(在調用另一個函數__new__
,但這並不重要)。
同樣,類定義(類內部的代碼,Bar在其中創建Foo對象)在引入類時僅運行一次。 每次創建新對象時,都會反復調用__init__
,因此在Bar2中也一次又一次地創建Foo。
據我所知,“ foo = None”是多余的,並不是真正需要的。 在python中,您可以從任何地方添加實例變量,甚至從類外部也可以從__init__
內部添加。
first = Bar()
second = Bar()
print "Bar"
print first
print second
print first.foo
print first.foo
在這里,您將first.foo打印兩次,這就是為什么打印相同的foo對象的原因。
first = Bar2()
second = Bar2()
print "\nBar2"
print first
print second
print first.foo
print second.foo
在這里,foo是Bar2類中的一個靜態變量,這就是為什么兩個對象都指向同一個foo對象的原因,該對象由second構造而成。
class Bar2():
foo = None
def __init__(self):
self.foo = Foo()
class Bar():
def __init__(self):
self.foo = Foo()
在Bar2中,Bar2的所有對象都將具有foo對象,該foo對象指向在構造最后一個Bar2的對象時構造的同一對象。
在Bar中,除非另有說明,否則所有foo對象對於Bar的每個對象都是唯一的。
類也是對象,它們具有自己的變量集。 不僅如此,當Python在對象中找不到變量時,它會在類中查找是否可以在其中找到它,這就是它的用途。 由於該類在該類的所有對象之間共享,因此該類中的變量也是如此。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.