Usando 'in' per abbinare un attributo di oggetti Python in un array

voti
39

Non mi ricordo se stavo sognando o no, ma mi sembra di ricordare che vi sia una funzione che ha permesso una cosa del genere,

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

Ho guardato oltre i documenti, ma questo genere di cose non rientra in nessun intestazioni quotate evidenti

È pubblicato 03/08/2008 alle 12:19
fonte dall'utente
In altre lingue...                            


8 risposte

voti
4

No, non state sognando. Python ha una bella eccellente sistema di lista che consente di manipolare le liste piuttosto elegante e, a seconda esattamente ciò che si vuole realizzare, questo può essere fatto un paio di modi. In sostanza, quello che stai facendo sta dicendo "Per la voce in elenco, se criteria.matches", e da che si può solo scorrere i risultati o scaricare i risultati in un nuovo elenco.

Ho intenzione di presepe un esempio da Dive Into Python qui, perché è piuttosto elegante e loro sono più intelligente di me. Ecco che stanno ottenendo un elenco di file in una directory, quindi filtrare l'elenco di tutti i file che corrispondono a un normale criterio di espressione.

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

Si potrebbe fare questo senza le espressioni regolari, per il tuo esempio, per qualsiasi cosa in cui la tua espressione alla fine restituisce true per una partita. Ci sono altre opzioni, come utilizzando la funzione di filtro (), ma se dovessi scegliere, mi piacerebbe andare con questo.

Eric Sipple

Risposto il 03/08/2008 a 13:30
fonte dall'utente

voti
-1

Credo:

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

È quello che stai pensando. Quando si cerca di vedere se una certa chiave esiste all'interno di un dizionario in Python (versione di Python di una tabella di hash) ci sono due modi per controllare. Il primo è il has_key()metodo allegata al dizionario e secondo è l'esempio di cui sopra. Si restituirà un valore booleano.

Questo dovrebbe rispondere alla tua domanda.

Ed ora un po 'fuori tema per legare questo alla lista di comprensione risposta data in precedenza (per un po' più di chiarezza). Di lista costruire un elenco da un semplice ciclo for con modificatori. A titolo di esempio (per chiarire un po '), un modo per utilizzare il in dictcostrutto del linguaggio in una lista di comprensione :

Diciamo che avete un dizionario bidimensionale fooe si desidera solo la seconda dizionari dimensione che contengono la chiave bar. Un modo relativamente semplice per farlo sarebbe quello di utilizzare una lista di comprensione con un condizionale come segue:

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

Si noti il if bar in valuealla fine dell'istruzione **, si tratta di una clausola di modifica che racconta la lista di comprensione per mantenere solo le coppie chiave-valore che soddisfano il condizionale. ** In questo caso bazè un nuovo dizionario, che contiene solo i dizionari da foo che contengono bar (Speriamo che non mi manca nulla in questo esempio di codice ... potrebbe essere necessario dare un'occhiata alla documentazione di lista si trovano in docs.python.org tutorial ea secnetix.de , entrambi i siti sono buone referenze se avete domande in futuro.).

Risposto il 03/08/2008 a 14:47
fonte dall'utente

voti
10

Stai cercando per ottenere un elenco di oggetti che hanno un determinato attributo? Se è così, un di lista è il modo giusto per farlo.

result = [obj for obj in listOfObjs if hasattr(obj, 'attributeName')]
Risposto il 03/08/2008 a 14:59
fonte dall'utente

voti
3

Quello che stavo pensando può essere realizzato utilizzando list comprehension, ma ho pensato che ci fosse una funzione che ha fatto questo in un modo un po 'più ordinato.

cioè 'bar' è un elenco di oggetti, che hanno tutti l'attributo 'id'

Il modo funzionale mitica:

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

Il modo di lista:

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

Col senno di poi il modo di lista è abbastanza carino comunque.

Risposto il 03/08/2008 a 15:13
fonte dall'utente

voti
8

si può sempre scrivere uno voi stessi:

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

lavorerà con qualsiasi cosa che scorre, che si tratti di una tupla, lista, o qualsiasi altra cosa.

Amo python, rende cose come questa molto semplice e non più di una seccatura di neccessary, e in uso cose come questa è estremamente elegante.

Risposto il 27/08/2008 a 19:13
fonte dall'utente

voti
3

Se hai intenzione di cercare qualche cosa di dimensioni decenti in remoto, la cosa migliore è andare a essere quella di utilizzare un dizionario o un set. In caso contrario, si deve fondamentalmente per scorrere ogni elemento del iteratore fino ad arrivare a quello che si desidera.

Se questo non è necessariamente il codice sensibile delle prestazioni, allora la lista di comprensione modo dovrebbe funzionare. Ma si noti che è abbastanza inefficiente perché va oltre ogni elemento del iteratore e poi torna su di esso di nuovo finché non trova quello che vuole.

Ricordate, Python ha uno degli algoritmi di hashing più efficienti in tutto. Usatelo a vostro vantaggio.

Risposto il 27/08/2008 a 19:30
fonte dall'utente

voti
38

Usando una lista di comprensione avrebbe costruito una lista provvisoria, che potrebbe mangiare tutto la memoria se la sequenza viene cercato è di grandi dimensioni. Anche se la sequenza non è di grandi dimensioni, la costruzione della lista significa iterazione su tutta la sequenza prima inpotrebbe iniziare la sua ricerca.

L'elenco temporaneo può essere evitando utilizzando un generatore di espressione:

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

Ora, fino a quando obj.id == 12in prossimità della partenza della bar, la ricerca sarà veloce, anche se barè infinitamente lungo.

Come suggerito @ Matt, è una buona idea usare hasattrse uno qualsiasi degli oggetti in barpuò mancare un idattributo:

foo = 12
foo in (obj.id for obj in bar if hasattr(obj, 'id'))
Risposto il 11/09/2008 a 21:42
fonte dall'utente

voti
4

La funzione si sta pensando di è probabilmente operator.attrgettter. Ad esempio, per ottenere un elenco che contiene il valore dell'attributo "id" di ciascun oggetto:

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

Se si desidera controllare se l'elenco contiene un oggetto con un == id 12, quindi un modo pulito ed efficiente (cioè non scorrere l'intera lista inutilmente) per farlo è:

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

Se si desidera utilizzare 'in' con attrgetter, pur mantenendo l'iterazione pigro della lista:

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

Risposto il 05/02/2011 a 07:10
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more