簡體   English   中英

如何在 Python Class 中創建增量 ID

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM