2009-06-25 11 views
13

Me gustaría crear un identificador único para cada objeto que creé - aquí está la clase:¿Cómo se crea un ID incrementales en una clase de Python

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

Me gustaría tener un automóvil que self.ID incrementa cada vez que cree una nueva referencia a la clase, tales como:

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

sé que puedo hacer referencia a resource_cl, pero no estoy seguro de cómo proceder a partir de ahí ...

Respuesta

3

¿Conoces el id function en python, y podrías usarlo en lugar de tu idea de contador?

class C(): pass 

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

Utilicé id (self) dentro de la clase - parece ser el correcto solución para mis necesidades: gracias – meade

+8

Recuerde que no se garantiza que los valores devueltos por id() sean únicos dentro de una ejecución del programa (pueden reutilizarse a medida que se recopilan los objetos). Tampoco se garantiza que sigan un patrón específico (usted solicitó el auto-incremento originalmente). –

+0

R. Pate: absolutamente correcto, e importante a tener en cuenta; Solo quería asegurarme de que conocía la existencia de la función de identificación y la evaluaba adecuadamente antes de elegir hacer algo manualmente. – llimllib

12

en primer lugar, el uso de mayúsculas Nombres para Classe s. nombres en minúscula para los atributos.

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

Dentro de __init__, la referencia class_counter es una propiedad de la clase. Debería verse así: Resource.class_counter + = 1 –

+0

S.Lott, lo probé. Con su primera versión, cada objeto tendrá una identificación de 0, y un class_counter de 1. –

+2

self funcionará en el caso de acceder al valor. Por lo tanto: self.id = autoclass_counter Se comportará como se desee ya que la resolución del atributo volverá a la propiedad de la clase. Este no es el caso para establecer el atributo ya que el conjunto de valores estará en el alcance de la instancia y no en la clase subyacente. –

10

Usando el recuento de itertools es ideal para esto:

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

La misma interfaz funciona si más adelante necesita cambiar cómo se generan los valores, que acaba de cambiar la definición de id_generator.

38

conciso y elegante:

import itertools 

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

+1: esta es la única forma confiable e inamovible de hacer esto entre todas las respuestas actuales. 'id' puede devolver valores no únicos, y simplemente aumentar una variable de clase dentro de' __init__' puede conducir a condiciones de carrera. También me gusta la idea de almacenar un referenec para 'count(). Next' en lugar de almacenar directamente el resultado de' count() '. –

+0

Ocurre el mismo objeto usando el id(), p. a = "123" b = "123" id (a) == id (b) – clsung

+0

@clsung Las cadenas de Python están "internados" y no son mutables. "123" es el mismo objeto a través de su sesión de Python. 'a' y 'b' son referencias nombradas, no "objetos" o "instancias" de "123". En este caso, apuntan a una cadena interna. Google python pasante para más información. – DevPlayer

0

Otra nota de id() y repensar la respuesta de otros al respecto. id() puede devolver un número único, si y solo si recuerda cada identificación devuelta incluso si se elimina un objeto; cual it (id()) no funciona. Entonces, por lo tanto ...

En apoyo de lo que otros decían que id() no devuelve un número único; Es cierto que no puede garantizar un valor único si y solo si está almacenando esos valores id() como referencias a objetos Y que está eliminando las instancias de los objetos para los que obtiene los id(). PERO ! El uso de id() como referencia significa que básicamente tienes un objeto que tiene una clave vinculada de algún modo con otro objeto.

Esto no se invalida por la no exclusividad de id(). Solo se invalida si no se comprueba si la adición de un nuevo objeto tiene una identificación preexistente() ya almacenada como referencia a alguna otra instancia del objeto.

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 

PERO storeit [4357891223] devuelve otra instancia de objeto no object3; por lo tanto, el enlace <> sigue siendo válido pero la unicidad falla.

0

Me gusta usar generadores para identificadores. Permita que el generador mantenga una lista de identificadores ya utilizados.

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

Aunque esta no es una forma eficiente de memoria para enormes conjuntos de datos en memoria. Si desea utilizar algo así, modifíquelo para que el sistema operativo maneje el almacenamiento en caché de un archivo ... digamos a través de un conducto con nombre.

1

Ids a veces se benefician del uso de algunos campos del objeto al que desea hacer referencia. Esta es una técnica de base de datos de estilo antiguo.

por ejemplo, si usted tiene una aplicación que mantiene los registros de llamadas telefónicas entrantes de clientes, a continuación, es posible utilizar un ID generado por el tiempo = alguna otra cosa

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

única Beaware la time.time() y hora. clock() es el valor de retorno de la computadora individual a menos que se genere en el servidor. Y si está en el servidor, asegúrese de que el reloj del servidor esté configurado correctamente; como siempre.

Cuestiones relacionadas