Utiliser 'in' pour faire correspondre un attribut d'objets Python dans un tableau

StackOverflow https://stackoverflow.com/questions/683

  •  08-06-2019
  •  | 
  •  

Question

Je ne me souviens pas si je rêvais ou non, mais il me semble qu'il y avait une fonction qui permettait quelque chose comme :

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

J'ai consulté la documentation, mais ce genre de chose ne relève d'aucun en-tête évident.

Était-ce utile?

La solution

L'utilisation d'une compréhension de liste créerait une liste temporaire, qui pourrait consommer toute votre mémoire si la séquence recherchée est volumineuse.Même si la séquence n'est pas grande, construire la liste signifie parcourir toute la séquence avant in pourrait commencer ses recherches.

La liste temporaire peut être évitée en utilisant une expression génératrice :

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

Maintenant, tant que obj.id == 12 vers le début de bar, la recherche sera rapide, même si bar est infiniment long.

Comme @Matt l'a suggéré, c'est une bonne idée d'utiliser hasattr si l'un des objets dans bar il peut manquer un id attribut:

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

Autres conseils

Cherchez-vous à obtenir une liste d’objets possédant un certain attribut ?Si c'est le cas, un compréhension de liste est la bonne façon de procéder.

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

vous pouvez toujours en écrire un vous-même :

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

fonctionnera avec tout ce qui itère, que ce soit un tuple, une liste ou autre.

J'adore Python, cela rend des choses comme celle-ci très simples et pas plus compliquées que nécessaire, et l'utilisation de choses comme celle-ci est extrêmement élégante.

Non, tu ne rêvais pas.Python dispose d'un excellent système de compréhension de liste qui vous permet de manipuler les listes de manière assez élégante, et en fonction de ce que vous souhaitez accomplir exactement, cela peut être fait de plusieurs manières.Essentiellement, ce que vous faites, c'est dire "Pour l'élément de la liste si les critères correspondent", et à partir de là, vous pouvez simplement parcourir les résultats ou transférer les résultats dans une nouvelle liste.

Je vais citer un exemple de Plongez dans Python ici, parce que c'est plutôt élégant et qu'ils sont plus intelligents que moi.Ici, ils obtiennent une liste de fichiers dans un répertoire, puis filtrent la liste pour tous les fichiers qui correspondent aux critères d'une expression régulière.

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

Vous pouvez le faire sans expressions régulières, par exemple, pour tout ce où votre expression à la fin renvoie vrai pour une correspondance.Il existe d'autres options comme l'utilisation de la fonction filter(), mais si je devais choisir, j'opterais pour celle-ci.

Eric Sipple

La fonction à laquelle vous pensez est probablement operator.attrgettter.Par exemple, pour obtenir une liste contenant la valeur de l'attribut "id" de chaque objet :

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

Si vous souhaitez vérifier si la liste contient un objet avec un identifiant == 12, alors une méthode soignée et efficace (c'est-à-direne parcourt pas toute la liste inutilement) la façon de procéder est la suivante :

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

Si vous souhaitez utiliser 'in' avec attrgetter, tout en conservant l'itération paresseuse de la liste :

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

Ce à quoi je pensais peut être réalisé en utilisant la compréhension de liste, mais je pensais qu'il existait une fonction qui faisait cela d'une manière légèrement plus soignée.

c'est à dire.'bar' est une liste d'objets, qui ont tous l'attribut 'id'

La voie fonctionnelle mythique :

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

La méthode de compréhension de liste :

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

Rétrospectivement, la manière de comprendre la liste est de toute façon assez intéressante.

Si vous envisagez de rechercher quelque chose de taille assez décente, le mieux sera d'utiliser un dictionnaire ou un ensemble.Sinon, vous devez essentiellement parcourir chaque élément de l'itérateur jusqu'à ce que vous arriviez à celui que vous souhaitez.

S'il ne s'agit pas nécessairement d'un code sensible aux performances, la méthode de compréhension de liste devrait fonctionner.Mais notez qu'il est assez inefficace car il parcourt chaque élément de l'itérateur puis y retourne jusqu'à ce qu'il trouve ce qu'il veut.

N'oubliez pas que Python possède l'un des algorithmes de hachage les plus efficaces du marché.Utilisez-le à votre avantage.

Je pense:

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

C'est ce à quoi vous pensez.Lorsque vous essayez de voir si une certaine clé existe dans un dictionnaire en python (la version python d'une table de hachage), il existe deux façons de vérifier.Le premier est le has_key() méthode attachée au dictionnaire et la seconde est l’exemple donné ci-dessus.Il renverra une valeur booléenne.

Cela devrait répondre à votre question.

Et maintenant, un peu hors sujet pour lier cela au compréhension de liste réponse donnée précédemment (pour un peu plus de clarté). Compréhensions des listes construire une liste à partir d'une base pour la boucle avec des modificateurs.A titre d'exemple (pour clarifier légèrement), une façon d'utiliser le in dict construction du langage dans un compréhension de liste:

Disons que vous avez un dictionnaire bidimensionnel foo et vous voulez uniquement les dictionnaires de deuxième dimension qui contiennent la clé bar.Une façon relativement simple de procéder serait d'utiliser un compréhension de liste avec un conditionnel comme suit :

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

Noter la if bar in value à la fin de l'instruction**, il s'agit d'une clause modificative qui indique au compréhension de liste pour conserver uniquement les paires clé-valeur qui répondent au conditionnel.** Dans ce cas baz est un nouveau dictionnaire qui contient uniquement les dictionnaires de foo qui contiennent bar (j'espère que je n'ai rien manqué dans cet exemple de code...vous devrez peut-être jeter un œil à la documentation sur la compréhension de la liste trouvée dans Tutoriels docs.python.org et à secnetix.de, les deux sites sont de bonnes références si vous avez des questions à l'avenir.).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top