簡體   English   中英

如何使用裝飾器修改可變的類變量?

[英]How to use a decorator to modify mutable class variables?

我有以下代碼:

class X(object):
    items = []

class Y(X):
    pass

class Z(X):
    pass

我正在嘗試創建一個裝飾器,該裝飾器僅將一個對象添加到Y的“項目”列表中。 所以下面的代碼,

@addItems
class Y(X):
    pass

應該在Y.items后面附加一些內容(例如,整數1),但不要修改X.items,Z.items或X的任何其他子類。基本上,Y.items應該具有items = [1]但X.items和Z.items都應具有items = [] 這是我創建的裝飾器函數定義,旨在實現該目標:

def addItems(cls):
    cls.items.append(1)
    return cls

但是,這不起作用-當我使用裝飾器時,它最終會修改X和X的所有其他子類的“項目”列表。這有什么用? 我知道Python的類屬性在X的所有實例之間共享,但是,我不知道子類會受到影響。 也許這種行為只發生在可變屬性上?

實現目標的正確方法是什么?

問題不在於裝飾器。 您對items屬性的存儲位置/方式存在誤解。 YZ沒有自己的items屬性。 而是只有一個items屬性。 您在X上定義了它,如果執行Y.items (或Z.items ),則由於在子類上找不到該屬性,因此會在超類上動態查找它。 如果你X.items is Y.items你會看到它演算值為真---只有一個items清單。 這意味着,當您對其進行修改時,所有類都會看到該修改。

如果要為每個班級提供自己的items列表,則必須為每個班級提供自己的items列表:

class X(object):
    items  = []

class Y(object):
    items  = []

class Z(object):
    items  = []

除非您告知,否則Python絕不會復制任何內容。 僅僅因為您定義了一個繼承自具有屬性的類的子類,但這並不意味着Python會為該子類創建該屬性的新副本。 它只是重復使用超類中的同一對象。

如果您想“神奇地”為每個類賦予自己的項目屬性,則可以在裝飾器中進行操作:

def addItems(cls):
    cls.items = []
    cls.items.append(1)
    return cls

這首先將類的items設置為空列表。 這實際上將屬性設置在它所操作的特定類上,而不是在任何子類或超類上。 現在,當您訪問它時,它將按預期工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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