将ID分配给类的实例(Pythonic)

将ID分配给类的实例(Pythonic),python,Python,我希望某个类的每个实例都有一个唯一的整数标识符,该标识符基于我创建它们的顺序,从(比如)0开始。在Java中,我可以使用一个静态类变量来实现这一点。我知道我可以用Python模仿同样的行为,但是最“Python”的方式是什么呢 感谢以下方法将是相对的pythonic(因为我对pythonic的主观判断——明确而简洁): 如果你面对大量的类,需要这样的属性,你也可以考虑编写一个元类。p> 元类的一个例子:。以下方法相对来说是pythonic的(对于我对pythonic的主观判断来说——明确但简洁)

我希望某个类的每个实例都有一个唯一的整数标识符,该标识符基于我创建它们的顺序,从(比如)0开始。在Java中,我可以使用一个静态类变量来实现这一点。我知道我可以用Python模仿同样的行为,但是最“Python”的方式是什么呢


感谢

以下方法将是相对的pythonic(因为我对pythonic的主观判断——明确而简洁):

如果你面对大量的类,需要这样的属性,你也可以考虑编写一个元类。p>


元类的一个例子:。

以下方法相对来说是pythonic的(对于我对pythonic的主观判断来说——明确但简洁):

如果你面对大量的类,需要这样的属性,你也可以考虑编写一个元类。p>


元类的一个例子:。

我想一个好问题是什么时候以及如何创建元类?如果您只是在某个时间点创建一定数量的对象,那么在for循环中使用一个范围

class A:
    def __init__ (self, id):
        self.id = id
        //do other stuff

class_list = []
for i in xrange(10):
    class_list.append(A(i))
那将是一种蟒蛇式的方式。如果你在需要的时候制作它们,那么我认为唯一的方法就是在某处保留一个id静态变量。虽然我不知道你是怎么做的


编辑:哦,还有,当你有疑问时,“导入这个”总能帮助你找到正确的途径,找出什么是“pythonic”;)

我想一个好问题是什么时候以及如何创建它们?如果您只是在某个时间点创建一定数量的对象,那么在for循环中使用一个范围

class A:
    def __init__ (self, id):
        self.id = id
        //do other stuff

class_list = []
for i in xrange(10):
    class_list.append(A(i))
那将是一种蟒蛇式的方式。如果你在需要的时候制作它们,那么我认为唯一的方法就是在某处保留一个id静态变量。虽然我不知道你是怎么做的


编辑:哦,还有,当你有疑问时,“导入这个”总能帮助你找到正确的途径,找出什么是“pythonic”;)

myyn的答案是好的——我认为类对象是存放计数器的绝佳位置。但是,请注意,正如所写的,它不是线程安全的。 因此,将其包装在使用锁的classmethod中:

import threading

class CounterExample(object):

    _next_id = 0
    _id_lock = threading.RLock()

    @classmethod
    def _new_id(cls):
        with cls._id_lock:
            new_id = cls._next_id
            cls._next_id += 1
        return new_id

    def __init__(self):
        self.id = self._new_id()

def test():
    def make_some(n=1000):
        for i in range(n):
            c = CounterExample()
            print "Thread %s; %s has id %i" % (threading.current_thread(), c, c.id)

    for i in range(10):
        newthread = threading.Thread(target=make_some)
        newthread.start()

test()
这将运行10个线程,每个线程创建1000个实例。
如果在没有锁定代码的情况下运行它,最后一个id很可能会低于9999,这表明了竞争条件。

myyn的答案很好——我认为类对象是存放计数器的绝佳位置。但是,请注意,正如所写的,它不是线程安全的。 因此,将其包装在使用锁的classmethod中:

import threading

class CounterExample(object):

    _next_id = 0
    _id_lock = threading.RLock()

    @classmethod
    def _new_id(cls):
        with cls._id_lock:
            new_id = cls._next_id
            cls._next_id += 1
        return new_id

    def __init__(self):
        self.id = self._new_id()

def test():
    def make_some(n=1000):
        for i in range(n):
            c = CounterExample()
            print "Thread %s; %s has id %i" % (threading.current_thread(), c, c.id)

    for i in range(10):
        newthread = threading.Thread(target=make_some)
        newthread.start()

test()
这将运行10个线程,每个线程创建1000个实例。
如果您在没有锁定代码的情况下运行它,那么最后一个id很可能会低于9999,这表明了竞争条件。

您可能还希望将
self.identifier=CounterExample.instances\u在
\uuu init\uuuuuu
的主体中创建,因为mellort似乎希望每个对象都有一个唯一的标识符。(这反过来意味着您不希望在删除过程中减少创建的
实例,因为这可能会导致以后初始化的对象具有非唯一标识符。)这可以正常工作,直到您尝试对内部类执行此操作,此时它会因“未定义反例”而失败。要使它与内部类一起工作,您还需要做些什么吗?您可能还需要将
self.identifier=CounterExample.instances\u创建的
放在
\u init\u\u
的主体中,因为mellort似乎希望每个对象都有一个唯一的标识符。(这反过来意味着您不希望在删除过程中减少创建的
实例,因为这可能会导致以后初始化的对象具有非唯一标识符。)这可以正常工作,直到您尝试对内部类执行此操作,此时它会因“未定义反例”而失败。为了使它与内部类一起工作,您还需要做其他事情吗?