簡體   English   中英

__init__之外的初始化字段

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM