Pregunta

No recuerdo si estaba soñando o no, pero creo recordar que había una función que permitía algo como,

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

Revisé los documentos, pero este tipo de cosas no se incluyen en ningún encabezado obvio.

¿Fue útil?

Solución

El uso de una lista por comprensión crearía una lista temporal, que podría consumir toda su 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 in podría iniciar su búsqueda.

La lista temporal se puede evitar utilizando una expresión generadora:

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

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

Como sugirió @Matt, es una buena idea utilizar hasattr si alguno de los objetos en bar puede faltar un id atributo:

foo = 12
foo in (obj.id for obj in bar if hasattr(obj, 'id'))

Otros consejos

¿Está buscando obtener una lista de objetos que tienen un determinado atributo?Si es así, un comprensión de la lista es la forma correcta de hacer esto.

result = [obj for obj in listOfObjs if hasattr(obj, 'attributeName')]

siempre puedes escribir uno tú mismo:

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

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

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

No, no estabas soñando.Python tiene un excelente sistema de comprensión de listas que le permite manipular listas de manera bastante elegante y, dependiendo exactamente de lo que quiera lograr, esto se puede hacer de dos maneras.En esencia, lo que estás haciendo es decir "Para el elemento de la lista si los criterios coinciden", y a partir de ahí puedes simplemente iterar a través de los resultados o volcarlos en una nueva lista.

Voy a tomar un ejemplo de Sumérgete en 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 para 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)]

Podrías hacer esto sin expresiones regulares, por ejemplo, para cualquier cosa en la que tu expresión al final devuelva verdadero para una coincidencia.Hay otras opciones como usar la función filter(), pero si tuviera que elegir, elegiría esta.

Eric Sipple

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

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

Si desea verificar si la lista contiene un objeto con una identificación == 12, entonces un método limpio y eficiente (es decir,no itera toda la lista innecesariamente) la forma de hacerlo es:

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

Si desea utilizar 'in' con attrgetter, manteniendo al mismo tiempo la iteración diferida de la lista:

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

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

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

La mítica forma funcional:

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

La forma de comprensión de la lista:

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

En retrospectiva, la forma de comprender la lista es bastante clara de todos modos.

Si planea buscar algo de un tamaño remotamente decente, lo mejor que puede hacer será utilizar un diccionario o un conjunto.De lo contrario, básicamente tienes que recorrer cada elemento del iterador hasta llegar al que deseas.

Si este no es necesariamente un código sensible al rendimiento, entonces la forma de comprensión de listas debería funcionar.Pero tenga en cuenta que es bastante ineficiente porque revisa cada elemento del iterador y luego REGRESA sobre él hasta que encuentra lo que busca.

Recuerde, Python tiene uno de los algoritmos hash más eficientes que existen.Úselo a su favor.

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 formas de comprobarlo.Primero es el has_key() método adjunto al diccionario y el segundo es el ejemplo dado anteriormente.Devolverá un valor booleano.

Eso debería responder a su pregunta.

Y ahora un poco fuera de tema para vincular esto con el comprensión de la lista respuesta dada anteriormente (para un poco más de claridad). Lista de comprensiones construir una lista a partir de un básico en bucle con modificadores.Como ejemplo (para aclarar un poco), una forma de utilizar el in dict construcción del lenguaje en un comprensión de la lista:

Digamos que tienes un diccionario bidimensional. foo y solo quieres los diccionarios de segunda dimensión que contienen la clave bar.Una forma relativamente sencilla de hacerlo sería utilizar un comprensión de la lista con un condicional de la siguiente manera:

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

Nota la if bar in value al final de la declaración**, esta es una cláusula modificadora que le dice al comprensión de la lista mantener solo aquellos pares clave-valor que cumplan el condicional.** En este caso baz es un nuevo diccionario que contiene solo los diccionarios de foo que contienen bar (espero no haberme perdido nada en ese ejemplo de código...es posible que tengas que echar un vistazo a la documentación de comprensión de la lista que se encuentra en Tutoriales de docs.python.org y en secnetix.de, ambos sitios son buenas referencias si tiene preguntas en el futuro).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top