[英]How do you create an incremental ID in a Python Class
我想为我创建的每个 object 创建一个唯一 ID - 这是 class:
class resource_cl :
def __init__(self, Name, Position, Type, Active):
self.Name = Name
self.Position = Position
self.Type = Type
self.Active = Active
我想要一个 self.ID,每次我创建对 class 的新引用时都会自动递增,例如:
resources = []
resources.append(resource_cl('Sam Sneed', 'Programmer', 'full time', True))
我知道我可以参考 resource_cl,但我不知道如何从那里开始......
简洁优雅:
import itertools
class resource_cl():
newid = itertools.count().next
def __init__(self):
self.id = resource_cl.newid()
...
尝试在 python 3 中投票最高的答案你会遇到错误,因为.next()
已被删除。
相反,您可以执行以下操作:
import itertools
class BarFoo:
id_iter = itertools.count()
def __init__(self):
# Either:
self.id = next(BarFoo.id_iter)
# Or
self.id = next(self.id_iter)
...
首先,对类使用大写名称。 属性的小写名称。
class Resource( object ):
class_counter= 0
def __init__(self, name, position, type, active):
self.name = name
self.position = position
self.type = type
self.active = active
self.id= Resource.class_counter
Resource.class_counter += 1
使用itertools 中的count 非常有用:
>>> import itertools
>>> counter = itertools.count()
>>> a = next(counter)
>>> print a
0
>>> print next(counter)
1
>>> print next(counter)
2
>>> class A(object):
... id_generator = itertools.count(100) # first generated is 100
... def __init__(self):
... self.id = next(self.id_generator)
>>> objs = [A(), A()]
>>> print objs[0].id, objs[1].id
100 101
>>> print next(counter) # each instance is independent
3
如果您以后需要更改值的生成方式,则相同的接口可以工作,您只需更改id_generator
的定义。
你知道 python 中的id 函数吗,你可以用它来代替你的反面想法吗?
class C(): pass
x = C()
y = C()
print(id(x), id(y)) #(4400352, 16982704)
您可以将计数作为类参数附加到类,然后在初始化时您可以将此值复制到实例参数。
这使得count
成为一个类参数, id
成为一个实例参数。 这是有效的,因为整数在 python 中是不可变的,因此当前值被复制而不是属性本身。
class Counter:
count = 0
@classmethod
def incr(self):
self.count += 1
return self.count
def __init__(self):
self.id = self.incr()
assert [Counter().id for _ in range(3)] == [1, 2, 3]
Id 有时会受益于使用您想要引用的对象的某些字段。 这是一种旧式的数据库技术。
例如,如果您有一个应用程序可以记录客户来电的记录,则可以使用时间生成的 ID = 其他事情
ident = '%s:%.4s:%.9s' % ( time.time(), time.clock(), agent.name )
# don't forget to time.clock() once to initialize it
只需要注意 time.time() 和 time.clock() 是单独的计算机返回值,除非在服务器上生成。 如果在服务器上,请确保您的服务器时钟设置正确; 一如既往。
关于 id() 的另一个注释并重新考虑其他人的答案。 id() 可能会返回一个唯一的数字,当且仅当它记住每个曾经返回的 id,即使对象被删除; 它 (id()) 不这样做。 所以因此...
支持其他人所说的 id() 不返回唯一数字; 确实,当且仅当您将这些 id() 值存储为对对象的引用并且您正在删除要为其获取 id() 的对象实例时,它确实无法保证唯一值。 但 ! 使用 id() 作为参考意味着您基本上拥有一个对象,该对象的键以某种方式与另一个对象链接。
这不会因 id() 的非唯一性而无效。 仅当您不检查添加新对象是否已将预先存在的 id() 存储为对该对象的某个其他实例的引用时,它才会失效。
storeit = {}
object1 = object()
print id(object1)
4357891223
storeit[ id(object1) ] = object1
object2 = object()
print id(object2)
9834923411
storeit[ id(object2) ] = object2
storeit[ id(object1) ] = object()
del object1
object3 = object()
print id(object3)
# after some 2 gigawatt tries magically i got
4357891223
# the same id as object1 had
但是 storeit[4357891223] 返回一些其他的对象实例而不是 object3; 因此 < link > 仍然有效但唯一性失败。
我喜欢使用生成器来生成 id。 允许生成器维护已使用的 id 列表。
# devplayer@gmail.com
# 2012-07(jul)-19
class MakeUniqueStr(object):
'''
unqstr = MakeUniqueStr(default_name='widget', sep='_')
print(repr(unqstr('window')))
print(repr(unqstr('window')))
print(repr(unqstr('window')))
print(repr(unqstr('hello')))
print(repr(unqstr('hello')))
print(repr(unqstr('window')))
print(repr(unqstr('hello')))
'window'
'window_00000'
'window_00001'
'hello'
'hello_00000'
'window_00002'
'hello_00001'
'''
def __init__(self, default_name='default', sep='_'):
self.default_name = default_name
self.last_base_name = default_name
self.sep = sep
self.used_names = []
self.generator = self.Generator()
self.generator.next() # initialize
def __call__(self, name=None):
if name <> None: self.last_base_name = name
return self.generator.send(self.last_base_name)
def _MakeName(self, name, index=1):
'''_MakeName is called by the Generator.
Generator will always have a name and an index to pass to _MakeName.
Over ride this method to customize it.'''
return name + self.sep + '%0.5d' % index
def Generator(self):
try_name = yield 'ready' # initialize
index = 0
while 1:
if try_name not in self.used_names:
self.used_names.append( try_name )
sent_name = yield try_name
try_name = sent_name
continue
try_name = self._MakeName( sent_name, index )
while try_name in self.used_names:
index += 1
try_name = self._MakeName( sent_name, index )
index = 0
尽管对于巨大的内存数据集来说,这不是一种高效的内存方式。 如果你想使用类似的东西,那么修改它以使操作系统处理缓存到文件......说通过命名管道。
def create_next_id(cnt=0):
def create_next_id_inner():
nonlocal cnt
cnt += 1
return cnt - 1
return create_next_id_inner
...
next_id = create_next_id()
...
my_data = {'id': next_id(), ...}
my_data2 = {'id': next_id(), ...}
...
您好,这可能是冗长的方式,但对我来说非常流利。 希望能帮助到你。 我使用名为id.txt的外部文本文件完成了它。
只需创建一个如上命名的空文件。 然后运行这个片段。 那肯定会奏效。
def id_generator():
with open("id.txt", "r") as f:
f.seek(0)
fc = f.read(1)
if not fc:
with open("id.txt", "w") as f1:
f1.write("1")
id = 1
else:
f.seek(0)
fc = f.read(1)
nv = int(fc) + 1
with open("id.txt", "w") as f2:
f2.write(str(nv))
id = nv
return id
并从该代码段中获取值,请执行此操作。
id = id_generator()
如果任何读者觉得它有用,请通过评论并让我知道我的工作是否得到了回报。
希望能帮助到你。 谢谢......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.