2009-06-25 5 views
13

ich für jedes Objekt eine eindeutige ID erstellen möchte ich geschaffen - hier ist die Klasse:Wie Sie eine inkrementelle ID in einer Python-Klasse erstellen

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

Ich mag würde eine self.ID haben, das Auto jedes Mal wenn ich eine neue Referenz auf die Klasse, wie erhöht:

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

ich weiß, ich resource_cl verweisen kann, aber ich bin nicht sicher, wie von dort aus gehen ...

Antwort

3

Kennen Sie die id function in Python, und könnten Sie es anstelle Ihrer Gegenidee verwenden?

class C(): pass 

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

Ich habe id (self) in der Klasse verwendet - scheint das richtige zu sein Lösung für meine Bedürfnisse - danke – meade

+8

Denken Sie daran, dass die von id() zurückgegebenen Werte innerhalb einer Programmausführung nicht eindeutig sind (sie können wiederverwendet werden, wenn Objekte gesammelt werden). Es ist auch nicht garantiert, dass sie einem bestimmten Muster folgen (Sie haben ursprünglich nach einem automatischen Inkrementieren gefragt). –

+0

R. Pate: absolut korrekt und wichtig zu beachten; Ich wollte nur sicherstellen, dass er sich der Existenz der ID-Funktion bewusst war und sie richtig ausgewertet hat, bevor sie sich dazu entschloss, etwas manuell zu tun. – llimllib

12

verwenden Sie zuerst Versalien- Namen für Classe s. Kleinbuchstaben Namen für Attribute.

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

Innerhalb von __init__ ist der Verweis class_counter eine Eigenschaft der Klasse. Es sollte so aussehen: Resource.class_counter + = 1 –

+0

S.Lott, ich habe es versucht. Bei Ihrer ersten Version hat jedes Objekt eine ID von 0 und ein Klassenzähler von 1. –

+2

self wird funktionieren, wenn Sie auf den Wert zugreifen. Also: self.id = self.class_counter Wird sich wie gewünscht verhalten, da die Attributauflösung auf die Klasseneigenschaft zurückfällt. Dies ist nicht der Fall für das Festlegen des Attributs, da der Wert im Bereich der Instanz und nicht in der zugrunde liegenden Klasse liegt. –

10

Zählung Verwendung von itertools ist für diese:

>>> 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 

Die gleiche Schnittstelle funktioniert, wenn Sie später ändern müssen, wie die Werte erzeugt werden, die Sie gerade die Definition von id_generator ändern.

38

Concise und elegant:

import itertools 

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

+1: Dies ist die einzige zuverlässige und Thread-sichere Art, dies unter allen aktuellen Antworten zu tun. "id" kann nicht eindeutige Werte zurückgeben und das einfache Erhöhen einer Klassenvariablen innerhalb von "__init__" kann zu Rennbedingungen führen. Ich mag auch die Idee, ein Referenc auf "count(). Next" zu speichern, anstatt das Ergebnis von "count()" direkt zu speichern. –

+0

Es passiert dasselbe Objekt unter Verwendung der ID(), z. a = "123" b = "123" id (a) == id (b) – clsung

+0

@clsung Python-Strings sind "interniert" und sie sind nicht änderbar. "123" ist das gleiche Objekt durch Ihre Python-Sitzung. 'a' und 'b' heißen Referenzen, keine "Objekte" oder "Instanzen" von "123". In diesem Fall zeigen sie auf eine interne Zeichenfolge. Google Python-Praktikant für weitere Informationen. – DevPlayer

0

Noch ein Hinweis auf id() und darüber andere Antwort zu überdenken. id() kann eine eindeutige Zahl zurückgeben, genau dann, wenn sie sich an jede zurückgegebene ID erinnert, selbst wenn ein Objekt gelöscht wird; was es (id()) nicht tut. Also also ...

Zur Unterstützung dessen, was andere sagten, dass id() keine eindeutige Nummer zurückgibt; Es ist wahr, dass es keinen eindeutigen Wert garantieren kann, wenn und nur wenn Sie diese ID() -Werte als Referenzen auf Objekte speichern und Sie die Instanzen von Objekten löschen, für die Sie IDs() erhalten. ABER ! Die Verwendung von id() als Referenz bedeutet, dass Sie grundsätzlich ein Objekt haben, bei dem ein Schlüssel irgendwie mit einem anderen Objekt verknüpft ist.

Dies wird durch die Nichteindeutigkeit von id() nicht ungültig gemacht. Es wird nur ungültig gemacht, wenn Sie nicht überprüfen, ob beim Hinzufügen eines neuen Objekts eine bereits vorhandene ID() bereits als Verweis auf eine andere Instanz des Objekts gespeichert ist.

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 

ABER storeit [4357891223] gibt eine andere Objektinstanz zurück, nicht object3; daher bleibt die <-Verknüpfung gültig, aber die Eindeutigkeit schlägt fehl.

0

Ich mag Generatoren für IDs verwenden. Erlaube dem Generator, eine Liste von bereits verwendeten IDs zu führen.

# [email protected] 
# 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 

Dies ist zwar keine speichereffektive Methode für große In-Memory-Datensätze. Wenn Sie so etwas verwenden möchten, ändern Sie dies, damit das Betriebssystem das Zwischenspeichern in eine Datei übernimmt ... sagen Sie es über eine Named Pipe.

1

Ids profitieren manchmal von der Verwendung einiger Felder des Objekts, auf das Sie verweisen möchten. Dies ist eine alte Datenbank-Technik.

zum Beispiel, wenn Sie eine App haben, die Datensätze für eingehende Kundentelefonanrufe hält, dann mögliche Verwendung eine id von Zeit erzeugt = etwas, was sonst

ident = '%s:%.4s:%.9s' % (time.time(), time.clock(), agent.name) 
# don't forget to time.clock() once to initialize it 

nur die time.time() und Zeit beaware. clock() ist ein individueller Computer-Rückgabewert, sofern nicht auf dem Server generiert. Und wenn auf dem Server, stellen Sie sicher, dass Ihre Serveruhr richtig eingestellt ist; wie immer.

Verwandte Themen