You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 22:05:24