在Python中为每个对象设置唯一ID

时间:2014-12-11 22:50:19

标签: python design-patterns

我需要创建类,每个实例化的对象将具有唯一的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)

3 个答案:

答案 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)