2013-03-12 48 views
1

我想拼湊一些示例代碼,我遇到了一點,這對我來說並不合適。如果不包括整個資料來源,我會嘗試將我認爲重要的部分作爲目標,並希望我能完成所有工作。子類化字典,類變量

在這裏,他聲明瞭一個自定義的dict子類,我認爲應該是類變量'customer'和'film'。 (如,從一個類中設置這些,應該在所有情況下對其進行更新,是嗎?)

class Payment(dict): 
    customer = film = None 

而且這裏是他使用的付款...

columns = [item[0] for item in cursor.description] 
payments = [] 
for row in cursor.fetchall(): 
    payment = Payment(zip(columns, row)) #I believe this is where he loads dict items 
    payment.customer = customers[payment["customer_id"]] #This is where he assigns 'class variable' 
    payment.film = films[payment["film_id"]] 
    payments.append(payment) 

在最後的名單,不應該所有的'支付'具有相同的值(這是另一個字典)嗎?這是我的困惑所在。事實證明,這兩個屬性在整個董事會都有獨特的價值。這是否與子類Dict有關?這些值是被複制而不是被引用的(所以在技術上它們是類變量,但是因爲它們被複制,所以它們仍然是唯一的)。

就在我以爲我明白了簡單的OO機制,這將引發我...

回答

4

在下面:

payment.customer = customers[payment["customer_id"]] #This is where he assigns 'class variable' 
payment.film = films[payment["film_id"]] 

你不改變payment.customerpayment.film值。相反,你是重新綁定他們,使他們特定於該類的實例

請看下面的例子:

class X(object): 
    val = ['orig'] 

x1 = X() 
x2 = X() 
x3 = X() 
x1.val = ['rebound']  # rebind 
x2.val[0] = 'modified' # modify in place 
print x1.val, id(x1.val) 
print x2.val, id(x2.val) 
print x3.val, id(x3.val) 

這將打印

['rebound'] 2907552 
['modified'] 2771544 
['modified'] 2771544 

觀察如何x1.val成爲一個完全獨立的變量,一旦它已經反彈,而x2.valx3.val繼續都指向同一個列表。

2

當Python在對象上查找屬性時,它首先查看實例,然後查看該類,然後查看超級類。

payment = Payment(zip(columns, row)) #I believe this is where he loads dict items 

後,您可以檢查payment.__dict__customerfilm

沒有條目如果您嘗試訪問(GETATTR)payment.film,因爲實例沒有film屬性,你會得到payment.__class__.film

始終指定屬性(除非它是描述符)將在實例dict中創建條目,因此它與所有其他實例隔離。

還有一些有趣的解釋:

>>> class C(dict): 
... foo = "class foo" 
... 
>>> c = C() 
>>> c.__dict__ 
{} 
>>> c.foo 
'class foo' 
>>> c.foo = "instance foo" 
>>> c.__dict__ 
{'foo': 'instance foo'} 
>>> c.foo 
'instance foo' 
>>> del c.foo 
>>> c.foo 
'class foo' 

順便說一句,因爲在您的示例代碼不訪問這些類的屬性,這將很好的工作:

class Payment(dict): 
    pass 

作者可能喜歡由於某種原因「聲明」這些屬性,但在這種情況下,並不需要(也可能令人困惑)。

+0

我見過這種技術用於創建實例並不總是初始化所有實例屬性的情況。在這種情況下,它可能是一種有用的方法,可以將實例屬性的默認值賦給可能或可能不會在實例中初始化的實例屬性。 '金字塔'使用這種風格相當多。 – Duncan 2013-03-12 11:10:28

+0

NPE的答案有所幫助,但是這個更好地說明了屬性查找。我認爲我很困惑,因爲通常來自實例的類變量訪問通常是隻讀的。我只寫過靜態方法的類變量。 – user2097818 2013-03-12 14:24:28

+0

如果我真的想在我的實例中顯式地將'foo'作爲類變量(如你的例子),我需要從我的實例方法中使用C.foo嗎? (假設變量是一個整數) – user2097818 2013-03-12 14:28:04