2011-03-03 30 views
8

Disculpas si esta pregunta ya se ha formulado, pero no creo conocer la terminología correcta para buscar una solución adecuada a través de google.cómo seleccionar un objeto de una lista de objetos por su atributo en python

me gustaría seleccionar un objeto de una lista de objetos por el valor de la misma es atributo, por ejemplo:

class Example(): 
    def __init__(self): 
     self.pList = [] 
    def addPerson(self,name,number): 
     self.pList.append(Person(self,name,number)) 

class Person(): 
    def __init__(self,name,number): 
     self.nom = name 
     self.num = number 


a = Example() 
a.addPerson('dave',123) 
a.addPerson('mike',345) 

a.pList #.... somehow select dave by giving the value 123 

en mi caso el número siempre será único

Gracias por la ayuda

+0

en 'self.pList.append (Persona (self, nombre, número))', 'self' no debe ser una de las argumentos. está en la definición de 'Persona .__ init __()' bien, pero allí representa la instancia recién creada 'Persona'. usted tampoco lo ve en 'a = Example()'. – flow

Respuesta

10

Trate

dave = next(person for person in a.pList if person.num == 123) 

o

for person in a.pList: 
    if person.num == 123: 
     break 
else: 
    print "Not found." 
dave = person 
+0

No había mirado todavía los siguientes bucles y solucionó mi problema, ¡salud! – Anake

3

La terminología que necesita es 'mapa' o 'dictionnary': esto lo llevará a the right page in the python doc.

ejemplo extremadamente básico:

>>> a = {123:'dave', 345:'mike'} 
>>> a[123] 
'dave' 
+0

Gracias, el código que di fue una simplificación excesiva, la clase Person contenía 7 atributos. Estoy bastante seguro de que está más allá del propósito de los diccionarios, aunque no estoy seguro acerca de los mapas – Anake

0

El subrayado que falta hace plist una propiedad pública. No creo que sea eso lo que quiere, ya que no encapsula la funcionalidad y puede llamar al a.plist.append en lugar de a.addPerson.

class Example(): 
    ... 
    def filter(self, criteria): 
     for p in self.plist: 
      if criteria(p): 
       yield p 

    def getByNum(self, num): 
     return self.filter(lambda p: p.num == num) 

dave = next(a.getByNum(123)) 

Si los números son únicos, también puede considerar usar un diccionario que correlacione de un número a nombre o persona en lugar de una lista. Pero eso depende de tu implementación.

2

Si esos nombres son claves únicas, y todo lo que siempre va a hacer es acceder a sus personas con esta clave única, en realidad debería usar un diccionario.

Sin embargo, si desea agregar más atributos con el tiempo y si le gustaría ser capaz de recuperar uno o más persona por cualquiera de esos atributos, es posible que quiera ir con una solución más compleja:

class Example(): 
    def __init__(self): 
     self.__pList = [] 
    def addPerson(self,name,number): 
     self.__pList.append(Person(name,number)) 
    def findPerson(self, **kwargs): 
     return next(self.__iterPerson(**kwargs)) 
    def allPersons(self, **kwargs): 
     return list(self.__iterPerson(**kwargs)) 
    def __iterPerson(self, **kwargs): 
     return (person for person in self.__pList if person.match(**kwargs)) 

class Person(): 
    def __init__(self,name,number): 
     self.nom = name 
     self.num = number 
    def __repr__(self): 
     return "Person('%s', %d)" % (self.nom, self.num) 
    def match(self, **kwargs): 
     return all(getattr(self, key) == val for (key, val) in kwargs.items()) 

Así que vamos a suponer que tenemos una Mike y

a = Example() 
a.addPerson('dave',123) 
a.addPerson('mike',345) 
a.addPerson('dave',678) 

Ahora se pueden encontrar personas de dos de Dave por número:

>>> a.findPerson(num=345) 
Person('mike', 345) 

O por nombre:

>>> a.allPersons(nom='dave') 
[Person('dave', 123), Person('dave', 678)] 

O las dos cosas:

>>> a.findPerson(nom='dave', num=123) 
Person('dave', 123) 
Cuestiones relacionadas