Je suis sûr qu'il existe un moyen plus simple de le faire qui ne m'est tout simplement pas venu à l'esprit.
J'appelle un tas de méthodes qui renvoient une liste. La liste est peut-être vide. Si la liste n'est pas vide, je veux retourner le premier élément; sinon, je veux retourner Aucun. Ce code fonctionne:
my_list = get_list()
if len(my_list) > 0: return my_list[0]
return None
Il me semble qu'il devrait y avoir un idiome d'une seule ligne pour faire cela, mais pour la vie de moi, je ne peux pas y penser. Y a-t-il?
Éditer:
La raison pour laquelle je recherche une expression sur une ligne ici n'est pas que j'aime le code incroyablement concis, mais parce que je dois écrire beaucoup de code comme ceci:
x = get_first_list()
if x:
# do something with x[0]
# inevitably forget the [0] part, and have a bug to fix
y = get_second_list()
if y:
# do something with y[0]
# inevitably forget the [0] part AGAIN, and have another bug to fix
Ce que j'aimerais faire peut certainement être accompli avec une fonction (et le sera probablement):
def first_item(list_or_none):
if list_or_none: return list_or_none[0]
x = first_item(get_first_list())
if x:
# do something with x
y = first_item(get_second_list())
if y:
# do something with y
J'ai posé la question parce que je suis souvent surpris par ce que les expressions simples en Python peuvent faire, et je pensais que l'écriture d'une fonction était une chose stupide à faire si une expression simple pouvait faire l'affaire. Mais en voyant ces réponses, il semble qu'une fonction soit la solution simple.
la source
next(iter(your_list), None)
au lieu defirst_item(your_list)
supposer que ceyour_list
n'est pas le casNone
(get_first_list()
etget_second_list()
doit toujours renvoyer un itérable).next(iter(your_list))
, puisque si vous fournissez un deuxième argumentiter
, vous lui dites que le premier argument peut être appelé.None
voici le deuxième paramètre pournext()
, noniter()
.next()
retourne son deuxième paramètre s'il est donné au lieu d'augmenterStopIteration
siyour_list
est vide.Réponses:
Python 2.6+
Si
your_list
peut êtreNone
:Python 2.4
Exemple:
Une autre option consiste à intégrer la fonction ci-dessus:
Pour éviter,
break
vous pourriez écrire:Où:
la source
""
dans la liste, elle est supprimée et remplacée par une liste vide[]
. Si vous avez un 0, également remplacé par[]
. Si vous en avezFalse
là, également remplacé. Etc. Vous pourriez vous en tirer dans un cas particulier, mais c'est une mauvaise habitude à développer.bool(lst)
nous indique s'illen(lst) > 0
ne nous dit rien sur ce que les élémentslst
contiennent, par exemple,bool([False]) == True;
l'expression[False] or []
retourne[False]
, la même chose est pour[0] or []
elle retourne[0]
.yield_first()
pour éviter labreak
déclaration.La meilleure façon est la suivante:
Vous pouvez également le faire sur une seule ligne, mais il est beaucoup plus difficile à lire pour le programmeur:
la source
next(iter(your_list), None)
next(iter(your_list))
est en fait suffisantNone
comme OP le demande. Essayez:next(iter([]))
.Cela devrait fonctionner.
BTW Je n'ai pas utilisé la variable
list
, car cela écrase lalist()
fonction intégrée .Edit: j'avais une version légèrement plus simple, mais incorrecte ici plus tôt.
la source
La manière la plus idiomatique en python est d'utiliser le next () sur un itérateur puisque list est itérable . tout comme ce que @JFSebastian a mis dans le commentaire du 13 décembre 2011.
next(iter(the_list), None)
Cela renvoie None sithe_list
est vide. voir next () Python 2.6+ou si vous savez à coup sûr
the_list
n'est pas vide:iter(the_list).next()
voir iterator.next () Python 2.2+la source
return l[0] if l else None
si la liste était une libcomp. Lorsque la liste est en fait un genexpr, c'est encore mieux car vous n'avez pas à construire la liste entière comme dansnext(iter(x for x in range(10) if x % 2 == 0), None)
the_list
n'est pas vide, vous écririezthe_list[0]
.Si vous essayez de saisir la première chose (ou aucune) d'une compréhension de liste, vous pouvez passer à un générateur pour le faire comme:
Pro: fonctionne si blah n'est pas indexable Con: c'est une syntaxe inconnue. C'est utile pour pirater et filtrer des trucs en ipython.
la source
La solution de l'OP est presque là, il y a juste quelques choses pour le rendre plus Pythonic.
D'une part, il n'est pas nécessaire d'obtenir la longueur de la liste. Les listes vides en Python sont évaluées à False dans une vérification if. Dites simplement
De plus, c'est une très mauvaise idée à attribuer à des variables qui se chevauchent avec des mots réservés. "list" est un mot réservé en Python.
Alors changeons cela en
Un point très important que beaucoup de solutions manquent ici est que toutes les fonctions / méthodes Python renvoient None par défaut . Essayez ce qui suit ci-dessous.
Sauf si vous devez retourner None pour terminer une fonction plus tôt, il n'est pas nécessaire de retourner explicitement None. Très succinctement, renvoyez simplement la première entrée, si elle existe.
Et finalement, c'était peut-être implicite, mais juste pour être explicite (car explicite vaut mieux qu'implicite ), vous ne devriez pas demander à votre fonction de récupérer la liste d'une autre fonction; il suffit de le passer en paramètre. Ainsi, le résultat final serait
Comme je l'ai dit, l'OP était presque là, et quelques touches lui donnent la saveur Python que vous recherchez.
la source
get_first_item
devrait accepter undefault
paramètre (commedict.get
) qui se définit par défaut sur None. Ainsi, l'interface de fonction communique explicitement ce qui se passe simy_list
est vide.la source
Franchement, je ne pense pas qu'il y ait un meilleur idiome: votre est clair et concis - pas besoin de quelque chose de "meilleur". Peut-être, mais c'est vraiment une question de goût, vous pouvez changer
if len(list) > 0:
avecif list:
- une liste vide sera toujours évaluée à Faux.Sur une note connexe, Python n'est pas Perl (sans jeu de mots!), Vous n'avez pas à obtenir le code le plus cool possible.
En fait, le pire code que j'ai vu en Python, était aussi très cool :-) et complètement incontrôlable.
Soit dit en passant, la plupart des solutions que j'ai vues ici ne prennent pas en compte lorsque list [0] est évalué à False (par exemple une chaîne vide ou zéro) - dans ce cas, ils renvoient tous None et pas l'élément correct.
la source
if lst:
plutôt queif len(lst) > 0:
. N'utilisez pas non plus de mots clés Python comme noms de variables; ça finit en larmes. Il est courant d'utiliserL
oulst
comme nom de variable pour une liste. Je suis sûr que dans ce cas, vous ne vouliez pas suggérer d'utiliser réellementlist
comme nom de variable, vous vouliez simplement dire "une liste". Et, +1 pour "lorsque lst [0] est évalué à False".L'approche la plus pythonique est ce que la réponse la plus votée a démontré, et c'était la première chose qui m'est venue à l'esprit lorsque j'ai lu la question. Voici comment l'utiliser, d'abord si la liste éventuellement vide est passée dans une fonction:
Et si la liste est renvoyée par une
get_list
fonction:D'autres façons ont démontré de le faire ici, avec des explications
for
Quand j'ai commencé à essayer de trouver des moyens intelligents de le faire, c'est la deuxième chose à laquelle j'ai pensé:
Cela suppose que la fonction se termine ici, renvoyant implicitement
None
siget_list
renvoie une liste vide. Le code explicite ci-dessous est exactement équivalent:if some_list
Ce qui suit a également été proposé (j'ai corrigé le nom de variable incorrect) qui utilise également l'implicite
None
. Ce serait préférable à ce qui précède, car il utilise la vérification logique au lieu d'une itération qui peut ne pas se produire. Cela devrait être plus facile à comprendre immédiatement ce qui se passe. Mais si nous écrivons pour la lisibilité et la maintenabilité, nous devons également ajouter l'explicitereturn None
à la fin:couper
or [None]
et sélectionner l'index zerothCelui-ci est également dans la réponse la plus votée:
La tranche n'est pas nécessaire et crée une liste supplémentaire d'un élément en mémoire. Les éléments suivants devraient être plus performants. Pour expliquer,
or
retourne le deuxième élément si le premier estFalse
dans un contexte booléen, donc siget_list
retourne une liste vide, l'expression contenue dans les parenthèses retournera une liste avec 'None', qui sera ensuite accessible par l'0
index:Le suivant utilise le fait que et retourne le deuxième élément si le premier est
True
dans un contexte booléen, et comme il fait référence à my_list deux fois, ce n'est pas mieux que l'expression ternaire (et techniquement pas une ligne):next
Ensuite, nous avons l'utilisation intelligente suivante de la fonction intégrée
next
etiter
Pour expliquer,
iter
renvoie un itérateur avec une.next
méthode. (.__next__
En Python 3.) Ensuite , les BUILTINnext
appels.next
méthode, et si le iterator est épuisé, retourne la valeur par défaut que nous donnons,None
.expression ternaire redondante (
a if b else c
) et retour en arrièreCe qui suit a été proposé, mais l'inverse serait préférable, car la logique est généralement mieux comprise dans le positif plutôt que dans le négatif. Puisque
get_list
est appelé deux fois, à moins que le résultat ne soit mémorisé d'une manière ou d'une autre, cela fonctionnerait mal:Le meilleur inverse:
Encore mieux, utilisez une variable locale pour qu'elle
get_list
ne soit appelée qu'une seule fois, et vous avez d'abord discuté de la solution Pythonic recommandée:la source
En ce qui concerne les idiomes, il existe une recette itertools appelée
nth
.Des recettes d'itertools:
Si vous voulez une ligne, envisagez d'installer une bibliothèque qui implémente cette recette pour vous, par exemple
more_itertools
:Un autre outil est disponible qui ne renvoie que le premier élément, appelé
more_itertools.first
.Ces outils sont évolutifs de manière générique pour tout itérable, pas seulement pour les listes.
la source
my_list[0] if len(my_list) else None
la source
len
sans raison. Si vous le supprimiez, le code ci-dessus ferait la même chose.Par curiosité, j'ai exécuté des timings sur deux des solutions. La solution qui utilise une déclaration de retour pour terminer prématurément une boucle for est légèrement plus coûteuse sur ma machine avec Python 2.5.1, je soupçonne que cela a à voir avec la configuration de l'itérable.
Voici les horaires que j'ai obtenus:
la source
la source
if len(a) > 0:
mais cela est considéré comme un bon style. Notez à quel point cela exprime bien le problème: "essayez d'extraire la tête d'une liste, et si cela ne fonctionne pas, revenezNone
". Recherchez "EAFP" sur Google ou regardez ici: python.net/~goodger/projects/pycon/2007/idiomatic/…BTW: Je retravaillerais votre flux de programme général en quelque chose comme ceci:
(Éviter la répétition autant que possible)
la source
Que dis-tu de ça:
(my_list and my_list[0]) or None
Remarque: Cela devrait fonctionner correctement pour les listes d'objets, mais cela pourrait retourner une réponse incorrecte en cas de nombre ou de liste de chaînes selon les commentaires ci-dessous.
la source
([0,1] and 0) or None
!.(['','A'] and '') or None
.my_list[0]
est évalué commeFalse
, le résultat devrait êtreNone
.my_list[0] if len(my_list) else None
Je ne sais pas à quel point c'est pythonique, mais jusqu'à ce qu'il y ait une première fonction dans la bibliothèque, je l'inclus dans la source:
C'est juste une ligne (conforme au noir) et évite les dépendances.
la source
Utilisation de l'astuce and-or:
la source
Probablement pas la solution la plus rapide, mais personne n'a mentionné cette option:
si
get_list()
peut revenir,None
vous pouvez utiliser:Avantages:
-une ligne
-Tu appelles juste
get_list()
une fois-facile à comprendre
la source
Mon cas d'utilisation consistait uniquement à définir la valeur d'une variable locale.
Personnellement j'ai trouvé l'essayeur et le style à lire
que de trancher une liste.
la source
Plusieurs personnes ont suggéré de faire quelque chose comme ceci:
Cela fonctionne dans de nombreux cas, mais cela ne fonctionnera que si la liste [0] n'est pas égale à 0, False ou une chaîne vide. Si la liste [0] est 0, False ou une chaîne vide, la méthode ne renvoie pas correctement None.
la source
Vous pouvez utiliser la méthode d'extraction . En d'autres termes, extrayez ce code dans une méthode que vous appelleriez ensuite.
Je n'essaierais pas de le compresser beaucoup plus, les doublures un semblent plus difficiles à lire que la version verbeuse. Et si vous utilisez la méthode d'extraction, c'est une doublure;)
la source
la source
n'est pas le python idiomatique équivalent aux opérateurs ternaires de style C
c'est à dire.
la source