2009-04-24 31 views
0

好了,我花了一些時間來縮小這個問題,但它似乎蟒蛇是這樣做的一個目的。有人可以解釋爲什麼會發生這種情況,我能做些什麼來解決這個問題?Python模塊/類變量出血

文件:Library/testModule.py

class testClass: 

    myvars = dict() 

    def __getattr__(self, k): 
     if self.myvars.has_key(k): 
      return self.myvars[k] 

    def __setattr__(self, k, v): 
     self.myvars[k] = v 

    def __str__(self): 
     l = [] 
     for k, v in self.myvars.iteritems(): 
      l.append(str(k) + ":" + str(v)) 

     return " - ".join(l) 

test.py

from library import testModule 

#I get the same result if I instantiate both classes one after another 
c1 = testClass() 
c1.foo = "hello" 
c2 = testClass() 

print("c1: " + str(c1) + "\n") 
print("c2: " + str(c2) + "\n") 

輸出:

c1: foo:hello 
c2: foo:hello 

我最好的猜測是,由於library"__init__.py"文件時,整個模塊像類對象一樣加載,現在它成爲持久對象的一部分..是這樣的情況?

+0

由於這是類/實例變量的問題,並且與模塊無關,您是否可以修改問題標題? – 2009-04-24 10:04:22

回答

7

myvars的屬性,而不是實例。這意味着,當你從實例c1插入屬性爲myvars,屬性獲取與類testClass,而不是實例c1特別相關。由於c2是同一個類的實例,因此它也具有相同的屬性。

您可以通過寫這得到你想要的行爲:

class testClass: 
    def __init__(self): 
     self.myvars = dict() 

    def __getattr__(self, k): 
     if self.myvars.has_key(k): 
      return self.myvars[k] 

    def __setattr__(self, k, v): 
     self.myvars[k] = v 

    def __str__(self): 
     l = [] 
     for k, v in self.myvars.iteritems(): 
      l.append(str(k) + ":" + str(v)) 
     return " - ".join(l) 
+0

實際上,在__init __()中賦值self.myvars = dict()會導致遞歸錯誤。嘿,我認爲解決方法是放棄__setattr__並改用__dict__ var。 – Ian 2009-04-24 01:11:16

2

其他的答案是正確的,給點意見。讓我談談一些我認爲你的誤解是。

我最好的猜測是,因爲圖書館有一個「__init__.py」文件,整個模塊被加載一樣的類對象,它現在成爲一個持久對象的一部分。這是這種情況?

所有軟件包都有__init__.py文件。有必要做一些python包。該軟件包可能有也可能沒有任何代碼。如果它確實會保證執行。在一般情況下,這不會有什麼與包裝中的其他模塊如何執行的,儘管它們確實有可能放了很多很酷的掛羊頭賣狗肉的在那裏,不影響它。

至於模塊和類是如何工作的,它往往是想到一個模塊作爲被實例化一旦類對象的一個​​很好的主意。加載程序只執行一次這些文件,然後可以將該文件末尾可用的所有變量,類定義和函數定義作爲該模塊的一部分進行訪問。

同樣是類真實的,與主要的例外的類中聲明的功能轉化爲方法(和一個特殊的方法,讓我們實例化類)。所以testModule有-A testClass具有-一個myvars。所有三個對象都是唯一的:不會有多個實例。無論我們說「模塊有 - 一個類對象」還是「類對象有 - 一個類變量」,這個有一個相互關係實際上或多或少都是相同的。 (所不同的是,你不應該與關注的實施細則。)