[英]How to not instantiate dataclass members as class variables in Python?
默認情況下,Python 似乎將類成員視為 ClassVar。 雖然來自文檔: https : //docs.python.org/3/library/dataclasses.html#class-variables
dataclass() 實際檢查字段類型的兩個地方之一是確定字段是否是 PEP 526 中定義的類變量。它通過檢查字段的類型是否為 Typing.ClassVar 來實現。 如果字段是 ClassVar,則將其作為字段排除在外,並被數據類機制忽略。 模塊級 fields() 函數不會返回此類 ClassVar 偽字段。
問題的最小再現:
from dataclasses import dataclass
import numpy as np
@dataclass
class Color:
r: int = 0
g: int = 0
b: int = 0
@dataclass
class NumberColor:
color: Color = Color()
number: int = 0
alpha = np.zeros(3)
x = NumberColor()
y = NumberColor()
print("Id of x:", id(x))
print("Id of y:", id(y))
print('-----------')
print("Id of x.color:", id(x.color))
print("Id of y.color:", id(y.color))
print('-----------')
print("Id of x.number:", id(x.number))
print("Id of y.number:", id(y.number))
print('-----------')
print("Id of x.alpha:", id(x.alpha))
print("Id of y.alpha:", id(y.alpha))
print('-----------')
x.color.r = 255
x.number = 10
print(x.__dict__)
print(y.__dict__)
產量:
Id of x: 140660354709392
Id of y: 140660357249008
-----------
Id of x.color: 140660355994096
Id of y.color: 140660355994096
-----------
Id of x.number: 9788960
Id of y.number: 9788960
-----------
Id of x.alpha: 140660289932624
Id of y.alpha: 140660289932624
-----------
{'color': Color(r=255, g=0, b=0), 'number': 10}
{'color': Color(r=255, g=0, b=0), 'number': 0}
不,您的NumberColor
類的color
屬性不被視為類變量。 相反,它是由dataclass
裝飾器為您的類創建的__init__
方法的共享默認參數。
它與可變默認參數的任何其他問題沒有太大不同:
def foo(c = Color()): # default value is created here
return c
x = foo() # get the default value
print(x.r) # 0, as is expected
x.r = 255
y = foo() # get the default again
print(y.r) # 255, not 0 as you might naively expect
在您的代碼中,與x
和y
等效的是x.color
和y.color
屬性。
為避免此問題,您可以使用作為Color
類的default_factory
參數將dataclasses.field
對象分配給類主體中的名稱(您還需要對用作alpha
的默認值的 numpy 數組執行類似操作) :
from dataclasses import dataclass, field
@dataclass
class NumberColor:
color: Color = field(default_factory=Color) # use a field!
number: int = 0
alpha = field(default_factory=lambda: np.zeros(3)) # here too
不需要將field
用於number
(或用於Color
的屬性),因為int
對象是不可變的,並且您不應該關心是否將相同的對象用於任何給定的0
值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.