我需要创建类,每个实例化的对象将具有唯一的id(简单地递增计数器)。目前,所有3个对象(b,b1,b2)共享一个A .__ COUNTER变量。
class A(type):
__COUNTER = 0
def __call__(cls, *args, **kwargs):
setattr(cls, "id", A.__COUNTER)
A.__COUNTER += 1
return type.__call__(cls, *args, **kwargs)
class B():
__metaclass__ = A
def __init__(self):
self.id
b = B()
b1 = B()
b2 = B()
print(b.id, b1.id, b2.id) -> (2, 2, 2)
好像我正朝着错误的方向挖掘
P.S。的解决
对不起,伙计们,我没有提到可以有几个类应该共享相同的id序列。 有很多解决方案,我在这里解决了它
class A(type):
__COUNTER = 0
def __call__(cls, *args, **kwargs):
obj = type.__call__(cls, *args, **kwargs)
obj.setId(A.__COUNTER)
A.__COUNTER += 1
return obj
class B():
__metaclass__ = A
def setId(self, id):
self.id = id
class C():
__metaclass__ = A
def setId(self, id):
self.id = id
b = B()
b1 = B()
b2 = B()
c = C()
b3 = B()
print(b.id, b1.id, b2.id, c.id, b3.id) -> (0, 1, 2, 3, 4)
答案 0 :(得分:2)
您可以改为使用类变量:
class B ():
__lastId = 1
def __init__ (self):
self.id = B.__lastId
B.__lastId += 1
>>> [B().id for _ in range(10)]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
如What is a metaclass?中所述,元类是类的类,而您只想修改单个类型的实际实例化对象。所以这里没有必要深入到元类复杂度级别。
答案 1 :(得分:1)
嗯,Python中的所有对象都有一个唯一的id
>>> id("a string")
140588614961168
但是如果你想要一个单独的计数器,你使用的方法应该可行。 有关您想要什么的更多信息可能有所帮助。
答案 2 :(得分:1)
一个好的解决方案取决于用例。我提供了一个非常通用的。
IDAssigner
是一个将ID粘贴到所有内容上的工厂。为新的ID池创建IDAssigner
的实例。您调用IDAssigner
的实例将类实例化为第一个参数,然后是类的__init__
方法的参数。
from itertools import count
class IDAssigner(object):
def __init__(self):
self._next_id = count()
def __call__(self, klass, *args, **kwargs):
obj = klass(*args, **kwargs)
setattr(obj, 'id', next(self._next_id))
return obj
class Foo(object):
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
create = IDAssigner()
foo_1 = create(Foo, 'Hello')
foo_2 = create(Foo, 'World')
print(foo_1, foo_1.id)
print(foo_2, foo_2.id)