使用dataclass创建带随机属性值的对象时重复值问题求助
问题原因
你在@dataclass里直接写pos = (random.randint(0, 800), random.randint(0, 800)),这是把pos定义成了类属性,而非实例属性。类属性会在类被Python解释器加载时就计算一次值,也就是random.randint只执行了一回,后面所有实例化的Particle对象都会共用这个提前算好的固定元组,所以输出全一样。
普通类能正常工作,应该是你在普通类的__init__方法里给self.pos赋值——__init__会在每个实例创建时执行,每次都会重新生成随机数,自然每个实例的pos都不一样。
解决方法
有两种常用的正确写法:
方法1:使用dataclasses.field的default_factory
这个方法适合动态生成默认值的场景,default_factory接收一个无参函数,每次实例化时会调用该函数生成值:
from dataclasses import dataclass, field import random @dataclass class Particle: pos: tuple[int, int] = field(default_factory=lambda: (random.randint(0, 800), random.randint(0, 800))) for _ in range(3): p = Particle() print(p.pos)
方法2:在__post_init__方法里赋值
__post_init__是dataclass自带的钩子方法,会在实例初始化完成后自动执行,适合补充实例创建后的初始化逻辑:
from dataclasses import dataclass import random @dataclass class Particle: pos: tuple[int, int] def __post_init__(self): self.pos = (random.randint(0, 800), random.randint(0, 800)) for _ in range(3): p = Particle() print(p.pos)
如果不想给pos指定类型注解(不推荐,dataclass建议添加注解),也可以先给个占位默认值再覆盖:
from dataclasses import dataclass import random @dataclass class Particle: pos: tuple[int, int] = (0, 0) def __post_init__(self): self.pos = (random.randint(0, 800), random.randint(0, 800))
修改后,每次实例化Particle都会重新生成随机坐标,就能得到三个不同的元组了。
内容的提问来源于stack exchange,提问作者user14534957
相关产品推荐
相关产品推荐

