Aquí podría ser tu PUBLICIDAD


Usar 'in' para hacer coincidir un atributo de los objetos de Python en una matriz

votos
39

No recuerdo si estaba soñando o no, pero me parece recordar que hay una función que permite algo así como,

foo in iter_attr(array of python objects, attribute name)

He revisado los documentos, pero este tipo de cosas no entran en ningún encabezado enumerado obvio

Publicado el 03/08/2008 a las 14:19
fuente por usuario Brendan
En otros idiomas...        العربية       

8 respuestas

votos
38

Usar una lista de comprensión crearía una lista temporal, que podría consumir toda tu memoria si la secuencia que se busca es grande. Incluso si la secuencia no es grande, construir la lista significa iterar sobre toda la secuencia antes de que inpueda comenzar su búsqueda.

La lista temporal puede evitarse mediante el uso de una expresión de generador:

foo = 12
foo in (obj.id for obj in bar)

Ahora, mientras esté obj.id == 12cerca del inicio de bar, la búsqueda será rápida, incluso si bares infinitamente larga.

Como @Matt sugirió, es una buena idea usar hasattrsi alguno de los objetos en los barque falta un idatributo:

foo = 12
foo in (obj.id for obj in bar if hasattr(obj, 'id'))
Respondida el 11/09/2008 a las 11:42
fuente por usuario Will Harris


Aquí podría ser tu PUBLICIDAD


votos
10

¿Estás buscando obtener una lista de objetos que tienen cierto atributo? Si es así, una lista de comprensión es la forma correcta de hacerlo.

result = [obj for obj in listOfObjs if hasattr(obj, 'attributeName')]
Respondida el 03/08/2008 a las 04:59
fuente por usuario Matt

votos
8

siempre puedes escribir uno tú mismo:

def iterattr(iterator, attributename):
    for obj in iterator:
        yield getattr(obj, attributename)

funcionará con cualquier cosa que itere, ya sea una tupla, lista o lo que sea.

Me encanta Python, hace cosas como esta muy simples y no más complicadas de lo necesario, y en uso cosas como esta son muy elegantes.

Respondida el 27/08/2008 a las 09:13
fuente por usuario dwestbrook

votos
4

La función que está pensando es probablemente operator.attrgettter. Por ejemplo, para obtener una lista que contiene el valor del atributo "id" de cada objeto:

import operator
ids = map(operator.attrgetter("id"), bar)

Si desea comprobar si la lista contiene un objeto con un id == 12, a continuación de manera ordenada y eficiente (es decir, no repetir innecesariamente toda la lista) para hacerlo es:

any(obj.id == 12 for obj in bar)

Si desea utilizar 'en' con attrgetter, al tiempo que conserva iteración perezoso de la lista:

import operator,itertools
foo = 12
foo in itertools.imap(operator.attrgetter("id"), bar)

Respondida el 05/02/2011 a las 09:10
fuente por usuario shang

votos
4

No, no estabas soñando. Python tiene un excelente sistema de comprensión de listas que le permite manipular listas de forma muy elegante, y dependiendo de exactamente lo que quiere lograr, esto se puede hacer de varias maneras. Básicamente, lo que está haciendo es decir "Para el elemento en la lista si criteria.matches", y de eso puede simplemente iterar a través de los resultados o volcar los resultados en una nueva lista.

Voy a cibear un ejemplo de Dive Into Python aquí, porque es bastante elegante y son más inteligentes que yo. Aquí obtienen una lista de archivos en un directorio y luego filtran la lista de todos los archivos que coinciden con un criterio de expresión regular.

    files = os.listdir(path)                               
    test = re.compile("test\.py$", re.IGNORECASE)          
    files = [f for f in files if test.search(f)]

Puedes hacer esto sin expresiones regulares, para tu ejemplo, para cualquier cosa donde tu expresión al final devuelva verdadero para una coincidencia. Hay otras opciones como usar la función filter (), pero si fuera a elegir, iría con esto.

Eric Sipple

Respondida el 03/08/2008 a las 03:30
fuente por usuario saalon

votos
3

Si planeas buscar algo de tamaño remotamente decente, tu mejor opción será usar un diccionario o un conjunto. De lo contrario, básicamente tiene que recorrer cada elemento del iterador hasta llegar al que desea.

Si esto no es necesariamente un código sensible al rendimiento, la forma de comprensión de la lista debería funcionar. Pero tenga en cuenta que es bastante ineficiente porque repasará todos los elementos del iterador y luego volverá sobre él hasta que encuentre lo que quiere.

Recuerde, Python tiene uno de los algoritmos de hash más eficientes. Úselo para su ventaja.

Respondida el 27/08/2008 a las 09:30
fuente por usuario Jason Baker

votos
3

Lo que estaba pensando se puede lograr usando listas de comprensión, pero pensé que había una función que lo hizo de una manera un poco más ordenada.

es decir, 'barra' es una lista de objetos, todos los cuales tienen el atributo 'id'

La forma mítica funcional:

foo = 12
foo in iter_attr(bar, 'id')

La lista de manera de comprensión:

foo = 12
foo in [obj.id for obj in bar]

En retrospectiva, la lista de comprensión es bastante ordenada de todos modos.

Respondida el 03/08/2008 a las 05:13
fuente por usuario Brendan

votos
-1

Creo:

#!/bin/python
bar in dict(Foo)

Es en lo que estás pensando. Al intentar ver si existe una determinada clave dentro de un diccionario en python (la versión de Python de una tabla hash), hay dos maneras de verificar. Primero está el has_key()método adjunto al diccionario y el segundo es el ejemplo dado arriba. Devolverá un valor booleano.

Eso debería responder a su pregunta.

Y ahora un poco fuera del tema para vincular esto a la lista de respuesta de comprensión dada previamente (para un poco más de claridad). List Comprehensions construye una lista a partir de un bucle for con modificadores. Como ejemplo (para aclarar un poco), una forma de usar el in dictconstructo del lenguaje en una lista de comprensión :

Supongamos que tiene un diccionario bidimensional fooy solo desea los diccionarios de segunda dimensión que contienen la clave bar. Una forma relativamente sencilla de hacerlo sería usar una lista de comprensión con un condicional de la siguiente manera:

#!/bin/python
baz = dict([(key, value) for key, value in foo if bar in value])

Tenga if bar in valueen cuenta que al final del enunciado **, esta es una cláusula modificadora que le dice a la lista de comprensión que solo conserve esos pares clave-valor que cumplen con el condicional. ** En este caso bazes un nuevo diccionario que contiene solo los diccionarios de foo que contienen barra (con suerte no me perdí nada en ese ejemplo de código ... es posible que tengas que echar un vistazo a la lista de documentación de comprensión encontrada en los tutoriales de docs.python.org y en secnetix.de , ambos sitios son buenas referencias si usted tiene preguntas en el futuro).

Respondida el 03/08/2008 a las 04:47
fuente por usuario akdom