我有几个类几乎具有相同的内容,因此我尝试了两种方法来复制类及其属性。这些类可以正确复制,但是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将相同。有什么办法解决吗?
编辑-我的程序的一部分每次都会显示具有随机统计信息的字符,并且该类包含与每个字符相关的统计信息。随机数从列表中选择统计数据,但选择的统计数据相同,而不是在每个类别中都是随机的。我可能没有解释这个权利,所以基本上是这样:
data = [stat1,stat2,stat3,ect,,]
data[random.randint(1,3)]
答案 0 :(得分:2)
当您写这篇文章时:
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)
如果愿意,可以使工厂功能更复杂(有关一个极端示例,请参见namedtuple
)。
您可以将该行为包装在装饰器中
def randomize(cls):
cls.exampleData = random.randint(1,100)
@randomize
class a:
pass
b = randomize(type('b', a.__bases__, dict(a.__dict__)))
请注意,我这里必须使用普通的函数调用语法来调用装饰器,因为没有声明语句可以将@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
。
还要注意,我没有在**kwds
方法中使用__new__
,而是直接呼叫type.__new__
。这意味着,如果您尝试将RandomMeta
与另一个元类(除了type
一起使用),则应该获得立即TypeError
,而不是可能正确或不正确的东西。>
与此同时,我怀疑您在这里真正想做的是建立一个基于原型的继承系统,在Python基于类的系统之上构建一个Self或JavaScript。尽管您可以通过使用特殊的Prototype
元类和一堆类对象来做到这一点,但是拥有Prototype
类和一堆实例对象要简单得多。元类方法的唯一优点是,您可以使用class
语句(具有误导性,但很方便)来克隆原型,而在这里您显然没有这样做。
答案 1 :(得分:0)
尽管my other answer涵盖了所问的问题,但我怀疑这对OP的实际问题完全没有必要。
如果您只想创建一堆单独的对象,每个对象都具有isDisposed()
的单独值,则只需要一堆单个类的实例,而不是一堆单独的类。
类是一种特殊的对象,除了完成所有常规对象的工作外,它还充当该类实例的其他对象的工厂。您不需要将exampleData
,a
和b
都用作不同类型对象的工厂,只需要它们是同一类型的不同对象即可。所以:
c
…,或者,如果要确保class RandomThing:
def __init__(self):
self.exampleData = random.randint(1,100)
a = RandomThing()
b = RandomThing()
与b
是同一类型的东西,但不知道是什么类型,
a
那真是太奇妙了。
请参见the official tutorial on Classes(或搜索更友好的教程,因为那里可能有更好的教程)。