En Python 3, comment puis-je vérifier si un objet est un conteneur (au lieu d'un itérateur qui peut permettre à une seule passe)
Voici un exemple: p>
def weighted_average(it): ''' returns weighted average of an iterator it it yields values and weights in tuples weights don't need to sum up 1 (automatically renormalized) ''' total_value = 0 total_weight = 0 for v, w in it: total_value += v total_weight += w return total_value / total_weight
3 Réponses :
Vous pouvez utiliser les classes de base abstraites définies dans le module code> Collections CODE> pour vérifier et voir si IT code> est une instance de collections.itéator.
if isinstance(it, collections.Iterator):
# handle the iterator case
Oui je suis d'accord. J'ai mis à jour ma question pour montrer un exemple où il ne semble pas être réalisable d'utiliser une passe.
Joli! On dirait qu'il y a une manière standard en 3.x.
Cela semble fonctionner, même pour les objets tels que le "conteneur virtuel" plage (5) code>. A l'air super!
Cela ne fonctionne pas pour moi. Si j'exécute a = (x pour x dans [1, 2, 3]) code>, alors
isinstance (a, collections.atiform) code>, il renvoie
vrai < / Code>, même s'il doit renvoyer
false code> car
A code> est quelque chose qui ne peut être itéré sur une fois.
Le meilleur moyen serait d'utiliser l'infrastructure de classe de base abstraite:
Bien que tous les itérables soient des collections de sous-classement. Sans toutes les personnes ne le font malheureusement. Voici une réponse basée sur la mise en œuvre de l'interface des objets, au lieu de ce qu'ils "déclarent".
un "conteneur" à mesure que vous l'appelez, c'est-à-dire une liste / tuple pouvant être itérale sur plus d'une fois par opposition à être un générateur qui sera Être épuisé, mettra typiquement mettre en œuvre les deux Cependant, vous pouvez faire une ierérable qui ne sera pas épuisée Et ne supporte pas getItem fort>. Par exemple, une fonction qui génère des nombres premiers. Vous pouvez répéter la génération plusieurs fois si vous le souhaitez, mais avoir une fonction pour récupérer le 1065e Prime prendrait beaucoup de calcul, vous ne voudrez peut-être pas supporter cela. : -) p> y a-t-il plus de manière "fiable"? p> Eh bien, tous les itérables implémenteront une fonction donc si elle a un itérables qui ne sont pas encore des itérateurs n'auront pas de fonction afin que vous puissiez vérifier que l'objet a itérateurs a également un , vous pouvez faire ces variations de la vérification: p> qui échouerait si vous implémentez un objet qui renvoie un itérateur brisé, celui qui fait pas em> Retournez-vous quand vous appelez iTer () dessus. Mais alors, votre code (ou un tiers modules) fait de mal à faire mal. P> Cela dépend de la création d'un itérateur, et appelez donc les objets __ iter __ code> et
__ getItem __ code>. Par conséquent, vous pouvez faire ceci: p>
__ iTer __ code> qui retournera un itérateur. Les itérateurs auront une fonction
__ suivante __ code>. C'est ce qui est utilisé lors de l'itération sur elle. Appelant
__ Suivant __ code> sera à plusieurs reprises échapper à l'éruptement à plusieurs reprises l'itérateur. P>
__ suivant __ code> Il s'agit d'un itérateur et sera épuisé.
__ suivant __ code>, mais implémentera un
__ iter __ code> fonctionner Renvoie une iérente: p>
__ iter __ code> mais qu'il n'a pas
__ suivant __ code>. p>
__ iTer __ code> fonction, qui retournera soi-même. p>
__ iter __ code>, qui dans La théorie peut avoir des effets secondaires, tandis que les appels HASATTR ci-dessus ne devraient pas avoir d'effets secondaires. Ok, alors ça appelle
>>> def is_container_iterable(o):
... try:
... object.__getattribute__(o, '__iter__')
... except AttributeError:
... return False
... try:
... object.__getattribute__(o, '__next__')
... except AttributeError:
... return True
... return False
...
>>> is_container_iterable([])
True
>>> is_container_iterable(())
True
>>> is_container_iterable({})
True
>>> is_container_iterable(range(5))
True
>>> is_container_iterable(iter(range(5)))
False
+1: Je ne m'attendais pas à ce qu'il y aurait un moyen de faire cela si la classe ne se dérange pas de la sous-classe de collections.itéable code>. (BTW, une classe peut-elle dériver de manière significative des deux
itérant code> et
itérateur code>?)
Itérant dérive de itérateur, donc non.
Je ne vois pas le problème avec la version générale, avez-vous profils? Et qu'entendez-vous par la complexité visuelle?
« Où il est pas évident quand exactement la seconde passe »? Qu'est-ce que cela peut vouloir dire? Vous pouvez utiliser
itertools.tee () code> pour la garantie inconditionnelle que vous pouvez itérer autant de fois que nécessaire. Comment peut-il pas évident quand vous concevez les algorithmes?
@LionelBarret: Je suis d'accord, je suis d'accord, il n'y a aucune raison de ne pas utiliser le général
pondéded_oovery code>. J'ai mis à jour la question pour donner un exemple différent.
@ S. Lott: Je voulais juste dire que si l'algorithme n'est pas linéaire, cela peut se produire à plusieurs endroits dans le code; et il pourrait même ne pas être totalement évident où ces endroits sont (par exemple, si une nouvelle passe est demandée quand une condition est violée). Pensant que une fois est assez mauvais; le faire chaque fois que le algoirhtm est peaufiné est vraiment mauvais. D'où ma préférence est de faire la validation au début.
@max: Vous faites que l'algorithme ne soit pas conçu par une sorte d'arrive spontanément sur la scène. C'est troublant. Pouvez-vous expliquer pourquoi le design ordinaire ne fonctionne pas?
@ S.Lott. Je verrai si je peux parvenir à un exemple simple; Ou bien arriver à la conclusion qu'un algorithme bien écrit nécessitant de multiples passes aura un point clair lorsque chaque nouveau passage commence.
@max: veuillez faire. Le
iTERTOOLS.EEE () code> semble être la solution à votre problème. Je sais aussi qu'une boucle est généralement i> un problème de conception très grave. Donc, je suis confondu par notre question et vous avez intéressé à voir s'il y a un exemple de crypto-boucle qui n'est pas une partie de première classe de la conception.
@ S.Lott Vous avez raison. Je n'ai pas de bon exemple.
@max: J'ai lu avec le même
iTertools.tee code> en essayant de trouver un moyen de le faire "invisible" pour les algorithmes qui nécessitent deux passes à travers une iérienne. Cela n'a jamais été obscutable ou mystérieux pour moi, il suffit de prendre soin de s'assurer que l'itérateur était "tee-d" correctement. J'étais très curieux de voir comment cela pourrait obtenir plus b> complexe à travers une boucle qui n'était pas "totalement évidente". Merci d'avoir pensé à cela au lieu de faire ce que certaines personnes font: Soit insister sur le fait que c'est une exigence (quand elle n'est pas ") ou de dire" ils sont juste curieux ". La curiosité ne fait pas une mauvaise question bien.