130 votes

One-liner pour vérifier si un itérateur des rendements au moins un élément?

Actuellement, je fais ceci:

try:
    something = iterator.next()
    # ...
except StopIteration:
    # ...

Mais je voudrais une expression que j'arrive à placer à l'intérieur d'un simple ifdéclaration. Est-il rien de construit-en ce qui ferait de ce code semble moins maladroit?

any() retours False si un objet iterable est vide, mais il est possible que itération sur tous les éléments si elle ne l'est pas. J'ai uniquement besoin de vérifier le premier élément.


Quelqu'un me demande ce que je suis en train de faire. J'ai écrit une fonction qui exécute une requête SQL et donne ses résultats. Parfois, lorsque j'appelle cette fonction, je veux juste savoir si la requête a retourné tout, et de prendre une décision sur cette base.

163voto

Jochen Ritzel Points 42916

any ne vont pas au-delà du premier élément si c'est Vrai. Dans le cas où l'itérateur rendements quelque chose de faux-ish, vous pouvez écrire any(True for _ in iterator).

52voto

Alex Martelli Points 330805

Dans la version 2.6 de Python+, si le nom sentinel est lié à une valeur de l'itérateur ne peut pas le rendement,

if next(iterator, sentinel) is sentinel:
    print('iterator was empty')

Si vous n'avez aucune idée de ce que l'itérateur peut, éventuellement, de rendement, de faire votre propre sentinelle (par exemple, en haut de votre module) avec

sentinel = object()

Sinon, vous pourriez utiliser, dans le rôle de sentinelle, toute valeur qui vous "savez" (basée sur des considérations d'application) que l'itérateur ne peut pas le rendement.

25voto

Matthew Flaschen Points 131723

Ce n'est pas vraiment propre, mais il montre un moyen de paquet dans une fonction sans perte:

def has_elements(iter):
  from itertools import tee
  iter, any_check = tee(iter)
  try:
    any_check.next()
    return True, iter
  except StopIteration:
    return False, iter

has_el, iter = has_elements(iter)
if has_el:
  # not empty

Ce n'est pas vraiment pythonic, et pour les cas particuliers, il y a probablement mieux (mais moins générale) des solutions, comme le suivant par défaut.

first = next(iter, None)
if first:
  # Do something

Ce n'est pas générale, car Aucun ne peut être un élément valide dans de nombreux iterables.

6voto

mykhal Points 5873

vous pouvez utiliser:

if zip([None], iterator):
    # ...
else:
    # ...

mais c'est un peu nonexplanatory pour le lecteur de code

-1voto

miku Points 63392

__length_hint__ des estimations de la durée de l' list(it) - il est privé de la méthode, si:

x = iter( (1, 2, 3) )
help(x.__length_hint__)
      1 Help on built-in function __length_hint__:
      2 
      3 __length_hint__(...)
      4     Private method returning an estimate of len(list(it)).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X