为类的实例分配ID(Pythonic)
我想让某个类的每个实例都有一个独特的整数标识符,这个标识符是根据我创建它们的顺序来的,从0开始。比如在Java中,我可以用一个静态类变量来实现这个功能。我知道在Python中也可以模拟这种行为,但最“Pythonic”的做法是什么呢?
谢谢
3 个回答
0
我想问一个好问题,那就是它们是什么时候以及怎么被创建的?如果你只是想在某个时间点创建一定数量的它们,那就可以在一个循环里用范围来做。
class A:
def __init__ (self, id):
self.id = id
//do other stuff
class_list = []
for i in xrange(10):
class_list.append(A(i))
这是一种很符合Python风格的方法。如果你是根据需要随时创建它们,那我觉得唯一的方法就是在某个地方保持一个静态的ID变量。不过,我不太确定你是怎么创建它们的。
补充一下:哦,如果不确定的话,输入“import this”总能帮你找到一些关于什么是“Python风格”的线索;)
1
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个实例。如果你不加锁直接运行,最后的id很可能会小于9999,这就说明出现了竞争条件。
3
以下的方法可以算是比较“python风格”的(这是我个人对python风格的理解——既清晰又简洁):
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
如果你需要处理很多类,并且这些类都需要那种属性,你也可以考虑为它们写一个元类。
这里有一个元类的例子:http://www.youtube.com/watch?v=E_kZDvwofHY#t=0h56m10s。