2017-04-14 68 views
0

我正在嘗試創建一個具有從多個文件中讀入的各種數據的類。通常的方法可能是定義構造函數(__init__),本程序讀取裏面的數據,例如,Python類的頭部分中的可執行語句

from SomeOtherMod import reader # some data reader 

class Myclass: 

    def __init__(self): 
     self.N = reader.readN() 
     self.data = reader.readdata() 
     self.foo = self.data.foo() 
     self.bar = self.data.bar() 
     ... # more data to read and associated properties follow 

    def othefunc(self): 
     ... # use self.N, self.data, ... 

但它也似乎我可以寫在類的頭部分同樣的事情,而無需使用__init__,例如,

class Myclass: 

    N = reader.readN() 
    data = reader.readdata() 
    foo = data.foo() 
    bar = data.bar() 
    ... 

    def otherfunc(self): 
     ... 

看起來比第一個代碼更簡潔。所以我想知道這個第二個代碼是否是定義Python類的各個領域的有效方法?這是否被認爲是不好的做法,或者第一種方法和第二種方法有什麼區別?我將不勝感激任何建議,因爲我仍然是Python的新手。非常感謝!

+1

第一種方法定義實例屬性,它可以在類的實例之間變化。第二種方法定義了類將被該類的所有實例共享的類屬性。 [9。類(https://docs.python.org/3/tutorial/classes.html)。 ... https://docs.python.org/3/reference/datamodel.html – wwii

+0

你可以考慮像Java或C++語言中的「靜態屬性」類的屬性 –

+0

嗯,真的...... Acutually,當我讀關於Python的一些入門書籍,我仍然無法理解Python中的實例和類字段如何區分(語法),除了用法{Classname}。{fieldname}。我將檢查更多... – septc

回答

1

是 - 他們有很大的不同 - 當你分配到self.attribute的方法中,你正在它,而當你分配給attribute實例屬性 - 在類體中,您正在創建一個類屬性。 類屬性在所有實例之間共享。

在某些情況下,但並非總是如此,您可能需要這樣做。你必須記住的是,如果yu改變一個類的屬性,它將立即改變該類的所有實例。

當然,Python處理屬性檢索和賦值使得類中的任務非常方便的方式是自然而然的。如果有,應該是一類的所有實例的默認值 - 比如,員工獎金 - 但應該在對象的生命週期的某個時刻,自然會發生定製:

class Employee: 
    payout = 100 

e1 = Employee() 
e2 = Employee() 

print(e1.payout, e2.payout) 
# Payout is read from the class as it does not exist in any instance 
# Python prints 100, 100 

e1.payout = 120 
# Now, an "payout" attribute is created in the "e1" instance 
print(e1.payout, e2.payout) 
# shows 120, 100 

# And the outpt of the following lines will make 
# really clear what is going on: 
print(e1.__class__.__dict__, e2.__class__.__dict__) 
# shows "{'payout': 100, ...}, {'payout': 100, ...} 
print(e1.__dict__, e2.__dict__) 
# shows "{'payout': 120}, {} 
1

在第一種方法中,N,data,foo和bar是Myclass實例的簡單成員。每個MYCLASS對象都有自己的和不斷變化的一個會對其他實例沒有影響:

class X(): 
    def __init__(self): 
    self.x = [] 

a = X() 
b = X() 
a.x.append(1) 
a.x != b.x 

在第二種方法中,他們是類的成員。您仍然可以通過實例訪問它們,但它們將由所有實例共享。

class X(): 
    x = [] 

a = X() 
b = X() 
a.x.append(1) 
a.x == b.x == [1] 

都是有效的代碼,但它們的目的不同

1

有這兩種方法之間的重要差異。在某些使用情況下,您可以採取任何方式,但絕對不等同。

使用第一種方法,__init__方法中的語句在您實例化類的實例之前不會執行;即,直到您的代碼執行形式爲a = MyClass()的語句。

第二種方法是在解釋器第一次到達代碼時執行類定義塊中的語句。這可能在您的程序開始時(或接近),並且會在您導入包含類定義的模塊時發生。這可能會,也可能不會,你的應用程序可以。

此外,請閱讀juanpa評論中提供的鏈接。arrivilaga,或這一個:Why do attribute references act like this with Python inheritance?