【发布时间】:2021-04-17 21:14:43
【问题描述】:
我将dataclass 理解为“自动”创建__init__ 和__repr__ 和其他功能的装饰器。
但我注意到了一些令我意想不到的事情,我会知道这是否是预期的,因为我在官方文档中找不到任何相关的内容(至少我没有相关)
第一个例子:
from dataclasses import dataclass
class CustomObj():
def __init__(self, x):
self.x = x
print(f'called custom obj with {x}')
class Normal():
i : int
o : CustomObj
f : float = 100.
s : str = 'this is a string'
@dataclass
class Data():
i : int
o : CustomObj
f : float = 100.
s : str = 'this is a string'
object_1 = Normal()
object_2 = Data(i = 1., o = CustomObj('custom_from_2'))
try:
object_1.i
except AttributeError:
print('it is ok, detecting an expected attribute error')
assert object_2.i == 1.
print('it is ok, because dataclass makes us set i value')
assert object_1.f == object_2.f
print('it is ok, because it is an "native" value')
try:
object_1.o
except AttributeError:
print('it is ok, detecting an expected attribute error, we didnt set o for object_1')
assert Normal.f == Data.f
print('it is ok, both classes have the same values and we did mess with it yet')
object_1.o = CustomObj('custom_from_1')
print('we set a customObj for obj_1 here')
Normal.f = 222.
Data.f = 222.
assert Normal.f == Data.f
print('it is ok, we set both values to same thing')
assert object_1.f == 222 and object_2.f == 100.
print(f'1: {object_1.f} 2: {object_2.f}')
print('By setting Normal.f we set object_1.f to 222 but object_2.f still 100')
object_1.s = 'changing object_1.s to something else'
object_2.s = 'changing object_2.s to something else'
Normal.s = 'changing Normal.s to something else'
Data.s = 'changing Data.s to something else'
print(object_1.s, object_2.s)
print(Normal.s, Data.s)
object_3 = Normal()
object_4 = Data(i = 4., o = CustomObj('custom_from_4'))
assert object_3.s == 'changing Normal.s to something else'
print('it is expected to have new value for the class definitions of Normal here')
print(f'Normal.s: {Normal.s}')
print(f'Data.s: {Data.s}')
print(f'object_1.s: {object_1.s}')
print(f'object_2.s: {object_2.s}')
print(f'object_3.s: {object_3.s}')
print(f'object_4.s: {object_4.s}')
输出是:
called custom obj with custom_from_2
it is ok, detecting an expected attribute error
it is ok, because dataclass makes us set i value
it is ok, because it is an "native" value
it is ok, detecting an expected attribute error, we didnt set o for object_1
it is ok, both classes have the same values and we did mess with it yet
called custom obj with custom_from_1
we set a customObj for obj_1 here
it is ok, we set both values to same thing
1: 222.0 2: 100.0
By setting Normal.f we set object_1.f to 222 but object_2.f still 100
changing object_1.s to something else changing object_2.s to something else
changing Normal.s to something else changing Data.s to something else
called custom obj with custom_from_4
it is expected to have new value for the class definitions of Normal here
Normal.s: changing Normal.s to something else
Data.s: changing Data.s to something else
object_1.s: changing object_1.s to something else
object_2.s: changing object_2.s to something else
object_3.s: changing Normal.s to something else
object_4.s: this is a string
我的三个问题是:
- 为什么在检查
object_1.i和object_2.i时更改Normal.i与更改Data.i不同 - 为什么
Data.s已更改但object_4.s未更改 - 此行为在文档中的哪个位置进行了说明?
我的猜测是,使用装饰器会导致返回对__new__ 运算符的引用并更改定义中的值应该是这种方式。
但是我在文档中找不到它的说明,所以我很困惑。
有人知道吗?
【问题讨论】:
-
因为在
class Normal、f和s中是类属性。