Python继承类都返回相同的随机数字吗?

2024-06-01 05:46:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我有几个内容几乎相同的类,所以我尝试了两种方法来复制这些类及其属性。类复制正确,但是randint函数只在主类中调用,所以每次都输出相同的数字。有没有办法重新计算每个班级的随机数?你知道吗

class a:
    exampleData = random.randint(1,100)

b = type('b', a.__bases__, dict(a.__dict__))

class c(a):
    pass

例如,如果a.exampleData=50,那么b.exampleData和c.exampleData将是相同的。有什么办法吗?你知道吗

Edit——我的程序的一部分每次都显示具有随机统计信息的字符,并且类包含与每个字符相关联的统计信息。随机数从列表中选择统计信息,但是选择相同的统计信息,而不是在每个类中随机选择。我可能解释得不对,所以基本上:

data = [stat1,stat2,stat3,ect,,]
data[random.randint(1,3)]

Tags: 方法函数信息内容data属性数字random
2条回答

虽然my other answer涵盖了被问到的问题,但我怀疑这对于OP的实际问题来说是完全没有必要的。你知道吗

如果您只想创建一组独立的对象,每个对象都有一个独立的exampleData值,那么您只需要一个类的一组实例,而不是一组独立的类。你知道吗

类是一种特殊的对象,它除了处理所有普通的对象外,还充当其他对象的工厂,这些对象是该类的实例。不需要abc都是不同类型对象的工厂,只需要它们是同一类型的不同对象。所以:

class RandomThing:
    def __init__(self):
        self.exampleData = random.randint(1,100)

a = RandomThing()
b = RandomThing() 

…或者,如果您想确定b是与a相同的类型,但不知道是什么类型:

b = type(a)()

你到这里就需要这么花哨了。你知道吗

请参阅the official tutorial on Classes(或者搜索更友好的教程,因为可能有更好的教程)。你知道吗

当你写这个的时候:

b = type('b', a.__bases__, dict(a.__dict__))

…你只是在复制a.__dict__。由于a.__dict__只是{'exampleData': 50},因此最终成为b.__dict__的新副本也将是{'exampleData': 50}。你知道吗

有很多方法可以得到一个新的随机数。最简单的方法就是显式地为b创建一个新的随机数:

bdict = dict(a.__dict__)
b['exampleData'] = random.randint(1,100)
b = type('b', a.__bases__, bdict)

如果要以这种方式创建一组类,可以将其封装在函数中:

def make_clone(proto, name):
    clonedict = dict(proto.__dict__)
    clonedict['exampleData'] = random.randint(1,100)
    return type(name, proto.__bases__, clonedict)

如果您愿意的话,可以使工厂函数更复杂(参见^{}获得一个非常极端的例子)。你知道吗


你可以把这种行为包装在一个装饰器里:

def randomize(cls):
    cls.exampleData = random.randint(1,100)

@randomize
class a:
    pass

b = randomize(type('b', a.__bases__, dict(a.__dict__)))

注意,我必须在这里用正常的函数调用语法调用decorator,因为这里没有要附加@decorator的声明语句。你知道吗


或者你可以把它包装成一个元类:

class RandomMeta(type):
    def __new__(mcls, name, bases, namespace):
        d = dict(namespace)
        d['exampleData'] = random.randint(1,100)
        return type.__new__(mcls, name, bases, d)

class a(metaclass=RandomMeta):
    pass

b = type(a)('b', a.__bases__, dict(a.__dict__))

注意,我们必须在这里调用type(a),方法与class定义语句相同,而不是基元类type。你知道吗

还要注意,我没有在__new__方法中使用**kwds,而是直接调用type.__new__。这意味着,如果您尝试将RandomMeta与另一个元类(除了type)一起使用,您应该得到一个立即的TypeError,而不是可能正确或可能不正确的东西。你知道吗


同时,我怀疑您真正想做的是构建一个基于原型的继承系统,一个基于类的Python系统之上的la Self或JavaScript。虽然您可以通过使用一个特殊的Prototype元类和一堆类对象来实现这一点,但是只要有一个Prototype类和一堆实例对象就简单多了。元类方法的唯一优点是,您可以使用class语句(误导性地,但很方便)克隆原型,而您在这里没有显式地这样做。你知道吗

相关问题 更多 >