2010-11-11 38 views
1

我有以下Python代碼:爲什麼對象中的字典與其他字典沒有區別?

#!/usr/bin/env python2.6 

class container(object): 
    name = 'container' 
    configuration = {'var1': 'var1', 
        'var2': 'var2'} 

if __name__ == "__main__": 
    container1 = container() 
    container2 = container() 
    container2.name = 'container2' 
    container2.configuration['var2'] = 'newvar2' 

    print container1.name 
    print container1.configuration['var2'] 

我預計這將打印「容器」和「VAR2」,但是對於後者它打印「newvar2」,而不是

爲什麼配置變量點兩個對象都使用同一個字典嗎?我怎樣才能解決這個問題?

大多數答案已經解釋說名稱和配置是類變量。爲什麼container2.name的更改不會影響container1.name?

回答

3

因爲configuration是一個類變量而不是一個實例變量。解決這個問題應該解決你的問題。

class container(object): 
    def __init__(self): 
     self.name = 'container' 

     self.configuration = {'var1': 'var1', 
          'var2': 'var2'} 

這是怎麼回事是configuration結束了住在containter.__dict__而不是它的實例的字典,當你把它一類變量。這意味着c.configuration只是訪問container.__dict__['configuration']所有實例c

對於任何類變量,形式c.foo = x的分配,創建用於在foo其中c.__dict__陰影其在container.__dict__條目的條目。因此,查找將首先返回。如果刪除它,則查找將返回檢索類實例。你可以做

c = container() 
c.configuration = x 

然後c.configuration是什麼x了。但是插入一個鍵不是一個賦值,它是對通過現有綁定訪問的現有對象的方法調用。

你可以避開name一個類變量,但如果你希望它從一個實例改變到另一個實例,那麼它應該是一個實例變量(除非你想要一個類寬的默認值)。

這樣:

  1. 賦值上的一個實例(使用=setattr__dict__直接插入)將跟隨一個類變量。類變量仍然存在。
  2. 實例上的查找(調用方法,訪問該值)將獲取實例屬性(如果存在),否則將獲取實例屬性。
+0

爲什麼'name'不是一個類變量呢?我不希望那個人也改變嗎? – 2010-11-11 07:39:05

+0

@Peter Smit查看我的更新。 – aaronasterling 2010-11-11 07:43:20

0
self.name = 'container' 
self.configuration = {'var1': 'var1', 
         'var2': 'var2'} 

INIT(),如果他們是類變量。

3

因爲nameconfiguration是容器類的類或靜態成員,並且它們爲容器的所有實例共享。使用self.name,self.configuration作爲實例變量:

class container(object): 
    def __init__(self): 
     self.name = "container" 
     self.configuration = {}