如何在Python类中创建增量ID

时间:2009-06-25 18:00:22

标签: python class

我想为我创建的每个对象创建一个唯一的ID - 这是类:

class resource_cl :
    def __init__(self, Name, Position, Type, Active):
        self.Name = Name
        self.Position = Position
        self.Type = Type
        self.Active = Active

我想有一个self.ID,每当我创建一个对类的新引用时自动递增,例如:

resources = []
resources.append(resource_cl('Sam Sneed', 'Programmer', 'full time', True))

我知道我可以参考resource_cl,但我不确定如何从那里开始......

10 个答案:

答案 0 :(得分:50)

简洁优雅:

import itertools

class resource_cl():
    newid = itertools.count().next
    def __init__(self):
        self.id = resource_cl.newid()
        ...

答案 1 :(得分:17)

首先,使用类的大写名称。属性的小写名称。

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

答案 2 :(得分:15)

使用itertools中的计数非常有用:

>>> 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的定义。

答案 3 :(得分:6)

您是否了解python中的id function,是否可以使用它而非您的反思?

class C(): pass

x = C()
y = C()
print(id(x), id(y))    #(4400352, 16982704)

答案 4 :(得分:3)

尝试使用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)
        ...

答案 5 :(得分:1)

Ids有时会受益于您想要引用的对象的某些字段。这是一种旧式的数据库技术。

例如,如果您有一个应用程序可以保留传入的客户来电记录,那么可以使用时间生成的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()是单独的计算机返回值,除非在服务器上生成。如果在服务器上确保您的服务器时钟设置正确;一如既往。

答案 6 :(得分:1)

您好,这可能是冗长的方法,但是对我来说非常流畅。希望能帮助到你。 我使用名为 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()

如果任何读者觉得有用,请发表评论,并让我知道我的工作是否还清。

希望有帮助。 谢谢...

答案 7 :(得分:0)

关于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;因此<链接>仍然有效,但唯一性失败。

答案 8 :(得分:0)

我喜欢使用生成器进行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

虽然这不是内存数据集的记忆效应方式。如果你想使用类似的东西,那么修改它以让操作系统处理缓存到文件...比如通过命名管道。

答案 9 :(得分:0)

您可以将计数作为类参数附加到该类,然后在初始化时将该值复制到一个实例参数。

这使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]