在astuple
函数下面的代码中,正在对数据类的类属性进行深层复制。为什么它不能产生与函数my_tuple
相同的结果?
import copy
import dataclasses
@dataclasses.dataclass
class Demo:
a_number: int
a_bool: bool
classy: 'YOhY'
def my_tuple(self):
return self.a_number, self.a_bool, self.classy
class YOhY:
def __repr__(self):
return (self.__class__.__qualname__ + f" id={id(self)}")
why = YOhY()
print(why) # YOhY id=4369078368
demo = Demo(1, True, why)
print(demo) # Demo(a_number=1, a_bool=True, classy=YOhY id=4369078368)
untrupled = demo.my_tuple()
print(untrupled) # YOhY id=4369078368
trupled = dataclasses.astuple(demo)
print(trupled) # YOhY id=4374460064
trupled2 = trupled
print(trupled2) # YOhY id=4374460064
trupled3 = copy.copy(trupled)
print(trupled3) # YOhY id=4374460064
trupled4 = copy.deepcopy(trupled)
print(trupled4) # YOhY id=4374460176
脚注
Anthony Sottile's出色的响应表明,这是Python 3.7中编码的行为。任何希望astuple与collections.namedtuple一样解压缩的人都需要用类似于Demo.my_tuple
的方法来替换它。以下代码比my_tuple脆弱,因为如果更改了数据类的字段,则无需修改。另一方面,如果使用__slots__
,它将无法正常工作。
只要在类或其超类中存在__hash__
方法,这两个版本的代码都会构成威胁。有关unsafe_hash
的信息,请参见Python 3.7文档,尤其是两段“此处是管理__hash__()
方法的隐式创建的规则”。
def unsafe_astuple(self):
return tuple([self.__dict__[field.name] for field in dataclasses.fields(self)])
答案 0 :(得分:2)
这似乎是| ID | fruit_id | totalqtypurchased | totalamountpurchased | totalqtysold | totalamountsold |
|----|----------|-------------------|----------------------|--------------|-----------------|
| 1 | 1 | 5 | 125 | 4 | 500 |
| 2 | 2 | 1 | 10 | 1 | 50 |
| 3 | 3 | 3 | 30 | 3 | 350 |
的{{3}}行为(似乎也是astuple
)。
asdict
将数据类
dataclasses.astuple(*, tuple_factory=tuple)
转换为元组(通过使用工厂函数instance
)。每个数据类都将转换为其字段值的元组。数据类,字典,列表和元组都递归到其中。
这里是undocumented:
tuple_factory
这里的深层复制似乎是有意的,尽管应该记录在案。