【发布时间】:2010-06-07 13:23:43
【问题描述】:
我想让某个类的每个实例都有一个基于我创建它们的顺序的唯一整数标识符,从(比如)0 开始。在 Java 中,我可以使用静态类变量来做到这一点。我知道我可以用 Python 模拟同样的行为,但是最“Pythonic”的方法是什么?
谢谢
【问题讨论】:
标签: python
我想让某个类的每个实例都有一个基于我创建它们的顺序的唯一整数标识符,从(比如)0 开始。在 Java 中,我可以使用静态类变量来做到这一点。我知道我可以用 Python 模拟同样的行为,但是最“Pythonic”的方法是什么?
谢谢
【问题讨论】:
标签: python
以下方法相对pythonic(对于我对pythonic的主观判断-明确但简洁):
class CounterExample(object):
instances_created = 0
def __init__(self):
CounterExample.instances_created += 1
def __del__(self):
""" If you want to track the current number of instances
you can add a hook in __del__. Otherwise use
__init__ and just count up.
"""
CounterExample.instances_created -= 1
如果您面临大量需要这种属性的类,您也可以考虑为此编写一个元类。
【讨论】:
self.identifier = CounterExample.instances_created 放在__init__ 的主体中,因为 mellort 似乎希望每个对象都有一个唯一的标识符。 (反过来,这意味着您不想在删除期间减少 instances_created,因为这可能会导致稍后初始化的对象具有非唯一标识符。)
the-myyn 的回答很好——我认为类对象是存放柜台的绝佳场所。但是,请注意,正如所写的那样,它不是线程安全的。 所以将它包装在一个使用锁的类方法中:
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 个实例。 如果你在没有锁定代码的情况下运行它,你可能会得到最后一个低于 9999 的 id,这表明了竞态条件。
【讨论】:
我想一个很好的问题是它们是何时以及如何创建的?如果您只是在某个时间点创建一定数量的它们,那么在 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”;)
【讨论】: