Question

Y at-il une méthode comme isiterable? La seule solution que j'ai trouvé est d'appeler à ce jour

hasattr(myObj, '__iter__')

Mais je ne sais pas comment cette épreuve fou est.

Était-ce utile?

La solution

  1. Vérification des __iter__ fonctionne sur les types de séquence, mais il échouerait par exemple cordes en Python 2 . Je voudrais connaître la bonne réponse aussi, jusque-là, voici une possibilité (qui travaillerait sur les cordes, aussi):

    try:
        some_object_iterator = iter(some_object)
    except TypeError as te:
        print some_object, 'is not iterable'
    

    Le iter contrôles intégrés pour le procédé de __iter__ ou dans le cas de chaînes de la méthode de __getitem__.

  2. Une autre approche pythonique générale est de prendre une itératives, puis échouer avec élégance si elle ne fonctionne pas sur l'objet donné. Le glossaire Python:

      

    style de programmation Pythonic qui détermine le type d'un objet par l'examen de sa méthode ou la signature d'attribut plutôt que par relation explicite à un objet de type ( "Si cela ressemble à un canard et caquette comme un canard , il doit être un canard . ») en mettant l'accent sur les interfaces plutôt que des types spécifiques, le code bien conçu améliore sa flexibilité en permettant la substitution polymorphes. Typage canard évite les tests en utilisant le type () ou isinstance (). Au lieu de cela, il emploie généralement le style de programmation EAFP (plus facile de demander pardon que la permission).

         

    ...

    try:
       _ = (e for e in my_object)
    except TypeError:
       print my_object, 'is not iterable'
    
  3. Le collections le module fournit quelques classes abstraites de base, qui permettent de demander des cours ou des cas si elles fournissent une fonctionnalité particulière, par exemple:

    from collections.abc import Iterable
    
    if isinstance(e, Iterable):
        # e is iterable
    

    Cependant, cela ne vérifie pas pour les classes qui sont itérables par __getitem__.

Autres conseils

taper Duck

try:
    iterator = iter(theElement)
except TypeError:
    # not iterable
else:
    # iterable

# for obj in iterator:
#     pass

Typage

Utilisez le Résumé des classes de base . Ils ont besoin d'au moins Python 2.6 et ne fonctionnent que pour les classes de type nouveau.

from collections.abc import Iterable   # import directly from collections for Python < 3.3

if isinstance(theElement, Iterable):
    # iterable
else:
    # not iterable

Cependant, iter() est un peu plus fiable comme décrit par la documentation :

  

Checking isinstance(obj, Iterable) détecte les classes qui sont   enregistrée en tant Iterable ou qui ont un procédé de __iter__(), mais   il ne détecte pas les classes qui le __getitem__() itèrent   méthode. Le seul moyen fiable pour déterminer si un objet   est itérable est d'appeler iter(obj).

Je voudrais jeter un peu plus de lumière sur l'interaction entre iter, __iter__ et __getitem__ et ce qui se passe derrière les rideaux. Armé de cette connaissance, vous serez en mesure de comprendre pourquoi le mieux que vous pouvez faire est

try:
    iter(maybe_iterable)
    print('iteration will probably work')
except TypeError:
    print('not iterable')

Je vais énumérer les faits d'abord, puis suivi par un rappel rapide de ce qui se passe lorsque vous utilisez une boucle de for en python, suivie d'une discussion pour illustrer les faits.

Faits

  1. Vous pouvez obtenir un itérateur de tout o objet en appelant iter(o) si au moins l'une des conditions suivantes est vraie:
    a) o a une méthode de __iter__ qui retourne un objet iterator. Un itérateur est un objet avec un __iter__ et un __next__ (Python 2: next) Méthode.
    b) o a une méthode de __getitem__.

  2. Vérification d'une instance de Iterable ou Sequence, ou le contrôle de la attribut __iter__ ne suffit pas.

  3. Si un o objet implémente uniquement __getitem__, mais pas __iter__, iter(o) construira un itérateur qui tente d'extraire les articles de o par l'indice entier, à partir de l'indice 0. L'itérateur va attraper toute IndexError (mais pas d'autres erreurs) qui est soulevé et soulève alors StopIteration lui-même.

  4. Dans le plus grand sens, il n'y a aucun moyen de vérifier si l'itérateur retourné par iter est sain d'esprit autre que pour l'essayer.

  5. Si un o objet implémente __iter__, la fonction iter fera en sorte que l'objet retourné par __iter__ est un itérateur. Il n'y a pas de bon sens contrôle si un objet implémente uniquement __getitem__.

  6. __iter__ gagne. Si un o objet implémente à la fois __iter__ et __getitem__, iter(o) appellera __iter__.

  7. Si vous voulez faire vos propres objets itératives, hériteront de la classe de base abstraite Iterable ou un de ses sous-classes. Vous aurez soit à mettre en œuvre la méthode __iter__, ou bien il sera fourni comme dans le cas de Sequence.

boucles for

Pour suivre, vous devez comprendre ce qui se passe lorsque vous utilisez une boucle de for en Python. Ne hésitez pas à aller directement à la section suivante si vous connaissez déjà.

Lorsque vous utilisez for item in o pour certains o objet itérable, Python appelle iter(o) et attend un objet iterator que la valeur de retour. Un itérateur est un objet qui met en œuvre un procédé __next__ (ou next dans le python 2) et un procédé de __iter__.

Par convention, le procédé de __iter__ d'un itérateur doit renvoyer l'objet lui-même (à savoir return self). Python appelle ensuite next sur le iterator jusqu'à ce que StopIteration est élevé. Tout cela se produit implicitement, mais la démonstration suivante rend visible:

import random

class DemoIterable(object):
    def __iter__(self):
        print('__iter__ called')
        return DemoIterator()

class DemoIterator(object):
    def __iter__(self):
        return self

    def __next__(self):
        print('__next__ called')
        r = random.randint(1, 10)
        if r == 5:
            print('raising StopIteration')
            raise StopIteration
        return r

itérer sur un DemoIterable:

>>> di = DemoIterable()
>>> for x in di:
...     print(x)
...
__iter__ called
__next__ called
9
__next__ called
8
__next__ called
10
__next__ called
3
__next__ called
10
__next__ called
raising StopIteration

Discussion et illustrations

Sur le point 1 et 2: obtenir un itérateur et des contrôles peu fiables

Considérez la classe suivante:

class BasicIterable(object):
    def __getitem__(self, item):
        if item == 3:
            raise IndexError
        return item

Appel iter avec une instance de BasicIterable retourne un itérateur sans aucun problème, car BasicIterable implémente __getitem__.

>>> b = BasicIterable()
>>> iter(b)
<iterator object at 0x7f1ab216e320>

Cependant, il est important de noter que b ne possède pas l'attribut __iter__ et in'est pas considérée comme une instance de Iterable ou Sequence:

>>> from collections import Iterable, Sequence
>>> hasattr(b, '__iter__')
False
>>> isinstance(b, Iterable)
False
>>> isinstance(b, Sequence)
False

C'est pourquoi Fluent Python par Luciano Ramalho recommande d'appeler iter et la manipulation du potentiel TypeError comme la façon la plus précise pour vérifier si un objet est itérable. Citant directement du livre:

  

de Python 3.4, la façon la plus précise pour vérifier si un objet est x itérables est d'appeler iter(x) et gérer une exception TypeError si elle est pas. Ceci est plus précis que l'utilisation isinstance(x, abc.Iterable), car iter(x) considère également la méthode __getitem__ héritage, alors que le Iterable ABC ne fonctionne pas.

Sur le point 3: Enumérer les objets qui ne fournissent que __getitem__, mais pas __iter__

Enumérer les une instance de BasicIterable fonctionne comme prévu: Python construit un itérateur qui tente d'extraire les éléments par index, en commençant par zéro, jusqu'à ce qu'une IndexError est soulevée. La méthode de __getitem__ de l'objet de démonstration retourne simplement le item qui a été fourni comme argument de __getitem__(self, item) par le itérateur retourné par iter.

>>> b = BasicIterable()
>>> it = iter(b)
>>> next(it)
0
>>> next(it)
1
>>> next(it)
2
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

Notez que le iterator soulève StopIteration quand il ne peut pas retourner l'élément suivant et que la IndexError qui est soulevée pour item == 3 est traitée en interne. C'est pourquoi en boucle sur une BasicIterable avec des œuvres de boucle de for comme prévu:

>>> for x in b:
...     print(x)
...
0
1
2

Voici un autre exemple pour conduire à la maison le concept de la façon dont l'itérateur retourné par iter tente d'accéder à des articles par index. WrappedDict ne hérite pas de dict, ce qui signifie que les instances n'auront pas une méthode __iter__.

class WrappedDict(object): # note: no inheritance from dict!
    def __init__(self, dic):
        self._dict = dic

    def __getitem__(self, item):
        try:
            return self._dict[item] # delegate to dict.__getitem__
        except KeyError:
            raise IndexError

Notez que les appels à __getitem__ sont déléguées à dict.__getitem__ pour lesquels la notation de support carré est tout simplement un raccourci.

>>> w = WrappedDict({-1: 'not printed',
...                   0: 'hi', 1: 'StackOverflow', 2: '!',
...                   4: 'not printed', 
...                   'x': 'not printed'})
>>> for x in w:
...     print(x)
... 
hi
StackOverflow
!

Sur le point 4 et 5: vérifie iter pour un itérateur quand il appelle __iter__ :

Quand iter(o) est appelé à un o objet, iter fera en sorte que la valeur de retour de __iter__, si la méthode est présente, est un itérateur. Cela signifie que l'objet retourné doit mettre en œuvre __next__ (ou next en Python 2) et __iter__. iter ne peut pas effectuer des vérifications de bonne santé pour les objets qui ne fournir __getitem__, car il n'a aucun moyen de vérifier si les éléments de l'objet sont accessibles par index entier.

class FailIterIterable(object):
    def __iter__(self):
        return object() # not an iterator

class FailGetitemIterable(object):
    def __getitem__(self, item):
        raise Exception

Notez que la construction d'un iterator des instances de FailIterIterable échoue immédiatement, tout en construisant un itérateur de FailGetItemIterable réussit, mais jeter une exception sur le premier appel à __next__.

>>> fii = FailIterIterable()
>>> iter(fii)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: iter() returned non-iterator of type 'object'
>>>
>>> fgi = FailGetitemIterable()
>>> it = iter(fgi)
>>> next(it)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/iterdemo.py", line 42, in __getitem__
    raise Exception
Exception

Le point 6: gagne __iter__

Celui-ci est simple. Si un objet implémente __iter__ et __getitem__, iter appellera __iter__. Considérez la classe suivante

class IterWinsDemo(object):
    def __iter__(self):
        return iter(['__iter__', 'wins'])

    def __getitem__(self, item):
        return ['__getitem__', 'wins'][item]

et la sortie lors de la boucle sur une occurrence:

>>> iwd = IterWinsDemo()
>>> for x in iwd:
...     print(x)
...
__iter__
wins

Sur le point 7: vos classes itérables devraient mettre en œuvre __iter__

Vous pourriez vous demander pourquoi des séquences les plus BUILTIN comme list mettre en œuvre une méthode de __iter__ quand __getitem__ serait suffisante.

class WrappedList(object): # note: no inheritance from list!
    def __init__(self, lst):
        self._list = lst

    def __getitem__(self, item):
        return self._list[item]

Après tout, l'itération sur les instances de la classe ci-dessus, les délégués appels à __getitem__ à list.__getitem__ (en utilisant la notation de crochets), fonctionnera bien:

>>> wl = WrappedList(['A', 'B', 'C'])
>>> for x in wl:
...     print(x)
... 
A
B
C

Raisons pour lesquelles votre iterables personnalisés doivent mettre en œuvre __iter__ sont les suivantes:

  1. Si vous implémentez __iter__, les instances sera considéré comme iterables et isinstance(o, collections.abc.Iterable) retournera True.
  2. Si l'objet retourné par __iter__ n'est pas un itérateur, iter échouera immédiatement et élever une TypeError.
  3. Le traitement spécial de __getitem__ existe pour des raisons de compatibilité ascendante. Courant citer encore une fois Python:
  

C'est pourquoi une séquence Python est itérable: ils sont tous à mettre en œuvre __getitem__. En réalité,   les séquences standards mettent également en œuvre __iter__, et le vôtre devriez aussi, parce que la   un traitement spécial de __getitem__ existe pour des raisons de compatibilité descendante et peut-être   allé à l'avenir (bien qu'il ne soit pas dépréciée que je vous écris).

Cela ne suffit pas: l'objet renvoyé par __iter__ doit mettre en oeuvre le protocole d'itération (à savoir la méthode de next). Voir la section pertinente du .

En Python, une bonne pratique consiste à « essayer de voir » au lieu de « vérifier ».

En Python <= 2.5, vous ne pouvez pas et ne devrait pas -. Itérables est une interface "informelle"

Mais depuis Python 2.6 et 3.0, vous pouvez tirer parti de la nouvelle infrastructure ABC (classe abstraite de base) ainsi que quelques ABCs builtin qui sont disponibles dans le module de recouvrement:

from collections import Iterable

class MyObject(object):
    pass

mo = MyObject()
print isinstance(mo, Iterable)
Iterable.register(MyObject)
print isinstance(mo, Iterable)

print isinstance("abc", Iterable)

Maintenant, si cela est souhaitable ou fonctionne réellement, est juste une question de conventions. Comme vous pouvez le voir, vous peut enregistrer un objet non itérables comme Iterable - et il déclenche une exception lors de l'exécution. Par conséquent, isinstance acquiert une « nouvelle » sens -. Il vérifie que pour la compatibilité de type « déclarée », ce qui est une bonne façon d'aller en Python

D'autre part, si votre objet ne satisfait pas l'interface dont vous avez besoin, qu'est-ce que tu vas faire? Prenons l'exemple suivant:

from collections import Iterable
from traceback import print_exc

def check_and_raise(x):
    if not isinstance(x, Iterable):
        raise TypeError, "%s is not iterable" % x
    else:
        for i in x:
            print i

def just_iter(x):
    for i in x:
        print i


class NotIterable(object):
    pass

if __name__ == "__main__":
    try:
        check_and_raise(5)
    except:
        print_exc()
        print

    try:
        just_iter(5)
    except:
        print_exc()
        print

    try:
        Iterable.register(NotIterable)
        ni = NotIterable()
        check_and_raise(ni)
    except:
        print_exc()
        print

Si l'objet ne satisfait pas à ce que vous attendez, vous venez de jeter un TypeError, mais si le bon ABC a été enregistré, votre chèque est unuseful. Au contraire, si la méthode de __iter__ est disponible Python reconnaîtra automatiquement objet de cette classe comme étant Iterable.

Alors, si vous vous attendez juste un itératives, itérer et l'oublier. D'autre part, si vous avez besoin de faire des choses différentes selon le type d'entrée, vous trouverez peut-être l'infrastructure ABC très utile.

try:
  #treat object as iterable
except TypeError, e:
  #object is not actually iterable

Ne pas effectuer des vérifications pour voir si votre canard est vraiment un canard pour voir si elle est itérables ou non, le traiter comme si elle était et se plaindre si ce n'était pas.

La meilleure solution que j'ai trouvé à ce jour:

hasattr(obj, '__contains__')

qui vérifie essentiellement si l'objet implémente l'opérateur in.

Avantages (aucune des autres solutions a tous les trois):

  • il est une expression (fonctionne comme lambda , par opposition à la try ... except variante)
  • il est (devrait être) mis en œuvre par tous les iterables, y compris les chaînes (par opposition à __iter__)
  • travaille sur un python> = 2,5

Notes:

  • la philosophie Python de « demander pardon, pas la permission » ne fonctionne pas quand par exemple dans une liste que vous avez deux iterables et non-iterables et vous devez traiter chaque élément différemment selon son type (le traitement iterables sur essai et non iterables à l'exception de serait le travail, mais il chercherait bout à bout laid et trompeur)
  • des solutions à ce problème qui tentent de itérer en fait sur l'objet (par exemple [x pour x dans obj]) pour vérifier si elle est itérables peut induire des pénalités de performances pour les grandes iterables (surtout si vous avez juste besoin les premiers éléments de la itératives, par exemple) et doit être évité

Depuis Python 3.5 vous pouvez utiliser le taper Module de la bibliothèque standard pour les choses liées au type:

from typing import Iterable

...

if isinstance(my_item, Iterable):
    print(True)

Vous pouvez essayer ceci:

def iterable(a):
    try:
        (x for x in a)
        return True
    except TypeError:
        return False

Si nous pouvons faire un générateur qui itère (mais ne jamais utiliser le générateur de sorte qu'il ne prend pas de place), il est itérable. On dirait une sorte de chose « duh ». Pourquoi avez-vous besoin pour déterminer si une variable est itérable en premier lieu?

J'ai trouvé une belle solution ici :

isiterable = lambda obj: isinstance(obj, basestring) \
    or getattr(obj, '__iter__', False)

Selon le Python 2 Glossaire , iterables sont

  

tous les types de séquences (telles que list, str et tuple) et certains types de non-séquences comme dict et file et objets de toutes les classes que vous avez définies avec une méthode de __iter__() ou __getitem__(). Iterables peut être utilisé dans une boucle et dans beaucoup d'autres endroits où une séquence est nécessaire (zip (), map (), ...). Lorsqu'un objet iterable est passée comme argument de la fonction intégrée iter (), il renvoie un itérateur pour l'objet.

Bien sûr, étant donné le style de codage général pour Python basé sur le fait qu'il est « plus facile de demander pardon que la permission. », L'attente générale est d'utiliser

try:
    for i in object_in_question:
        do_something
except TypeError:
    do_something_for_non_iterable

Mais si vous devez vérifier explicitement, vous pouvez tester les itérables par hasattr(object_in_question, "__iter__") or hasattr(object_in_question, "__getitem__"). Vous devez vérifier les deux, parce que strs ne sont pas une méthode de __iter__ (au moins pas en Python 2, en Python 3 ils le font) et parce que les objets generator n'ont pas une méthode __getitem__.

Je trouve souvent pratique, dans mes scripts, pour définir une fonction iterable. (Intègre désormais la simplification proposée Alfe):

import collections

def iterable(obj):
    return isinstance(obj, collections.Iterable):

afin que vous puissiez tester si un objet est itérables sous la forme très lisible

if iterable(obj):
    # act on iterable
else:
    # not iterable

comme vous le feriez avec thecallable fonction

EDIT: si vous avez installé numpy, vous pouvez simplement faire: à partir numpy import iterable, ce qui est tout simplement quelque chose comme

def iterable(obj):
    try: iter(obj)
    except: return False
    return True

Si vous n'avez pas numpy, vous pouvez simplement mettre en œuvre ce code, ou celui ci-dessus.

a une fonction intégrée comme que:

from pandas.util.testing import isiterable
def is_iterable(x):
    try:
        0 in x
    except TypeError:
        return False
    else:
        return True

Cela dit oui à toutes sortes d'objets itératives, mais il dire non à des chaînes en Python 2 . (C'est ce que je veux par exemple quand une fonction récursive peut prendre une chaîne ou un contenant de chaînes. Dans cette situation, demander pardon peut conduire à obfuscode, et il est préférable de demander la permission d'abord.)

import numpy

class Yes:
    def __iter__(self):
        yield 1;
        yield 2;
        yield 3;

class No:
    pass

class Nope:
    def __iter__(self):
        return 'nonsense'

assert is_iterable(Yes())
assert is_iterable(range(3))
assert is_iterable((1,2,3))   # tuple
assert is_iterable([1,2,3])   # list
assert is_iterable({1,2,3})   # set
assert is_iterable({1:'one', 2:'two', 3:'three'})   # dictionary
assert is_iterable(numpy.array([1,2,3]))
assert is_iterable(bytearray("not really a string", 'utf-8'))

assert not is_iterable(No())
assert not is_iterable(Nope())
assert not is_iterable("string")
assert not is_iterable(42)
assert not is_iterable(True)
assert not is_iterable(None)

Beaucoup d'autres stratégies ici vont dire oui à cordes. Utilisez-les si c'est ce que vous voulez.

import collections
import numpy

assert isinstance("string", collections.Iterable)
assert isinstance("string", collections.Sequence)
assert numpy.iterable("string")
assert iter("string")
assert hasattr("string", '__getitem__')

Note: is_iterable () va dire oui à des chaînes de type bytes et bytearray

.
  • objets bytes en Python 3 sont True == is_iterable(b"string") == is_iterable("string".encode('utf-8')) itérables Il n'y a pas ce type en Python 2.
  • objets bytearray en Python 2 et 3 sont True == is_iterable(bytearray(b"abc")) iterable

L'approche hasattr(x, '__iter__') O.P. va dire oui à des chaînes en Python 3 et pas en Python 2 (peu importe si '' ou b'' ou u''). Merci à @LuisMasuelli pour le remarquer aussi vous laisser tomber sur un __iter__ buggy.

Il est toujours éludé me savoir pourquoi python a callable(obj) -> bool mais pas iterable(obj) -> bool ...
sûrement il est plus facile de le faire hasattr(obj,'__call__') même si elle est plus lente.

Depuis presque toutes les autres réponses vous recommande d'utiliser try / except TypeError, où les essais des exceptions est généralement considérée comme une mauvaise pratique parmi toutes les langues, voici une implémentation de iterable(obj) -> bool je suis devenu plus aime et utilise souvent:

Pour l'amour de python 2, je vais utiliser un lambda juste pour ce coup de pouce de la performance supplémentaire ...
(En python 3, peu importe ce que vous utilisez pour définir la fonction, def a à peu près la même vitesse que lambda)

iterable = lambda obj: hasattr(obj,'__iter__') or hasattr(obj,'__getitem__')

Notez que cette fonction exécute plus rapidement pour les objets avec __iter__ car il ne teste pas __getitem__.

La plupart des objets itérables doivent compter sur __iter__ où les objets cas spéciaux retombent __getitem__, bien que ce soit est nécessaire pour un objet à itérables.
(Et puisque ce standard, il affecte des objets C ainsi)

La façon la plus simple, le respect du canard Python frappe , est d'attraper l'erreur (Python sait parfaitement ce-t-il attendre d'un objet pour devenir un iterator):

class A(object):
    def __getitem__(self, item):
        return something

class B(object):
    def __iter__(self):
        # Return a compliant iterator. Just an example
        return iter([])

class C(object):
    def __iter__(self):
        # Return crap
        return 1

class D(object): pass

def iterable(obj):
    try:
        iter(obj)
        return True
    except:
        return False

assert iterable(A())
assert iterable(B())
assert iterable(C())
assert not iterable(D())

Remarques :

  1. Il est hors de propos la distinction si l'objet n'est pas itératives, ou un __iter__ buggy a été mis en œuvre, si le type d'exception est le même:. De toute façon, vous ne serez pas en mesure de itérer l'objet
  2. Je pense que je comprends votre préoccupation: Comment fonctionne callable existe comme un chèque si je pouvais également compter sur la saisie de canard pour soulever une AttributeError si __call__ n'est pas défini pour mon objet, mais ce n'est pas le cas pour le contrôle itérables?

    Je ne connais pas la réponse, mais vous pouvez mettre en œuvre la fonction I (et d'autres utilisateurs) donné, ou tout simplement Intercepter l'exception dans votre code (votre mise en œuvre dans cette partie sera comme la fonction que j'ai écrit - il suffit d'assurer vous isoler la création de iterator du reste du code, vous pouvez donc capturer l'exception et le distinguer d'un autre TypeError.

Le func isiterable le code suivant retourne True si l'objet est iterable. si ce n'est pas des retours itératifs False

def isiterable(object_):
    return hasattr(type(object_), "__iter__")

exemple

fruits = ("apple", "banana", "peach")
isiterable(fruits) # returns True

num = 345
isiterable(num) # returns False

isiterable(str) # returns False because str type is type class and it's not iterable.

hello = "hello dude !"
isiterable(hello) # returns True because as you know string objects are iterable

Au lieu de vérifier pour l'attribut __iter__, vous pouvez vérifier l'attribut __len__, qui est mis en œuvre par tous les python builtin itératives, y compris les chaînes.

>>> hasattr(1, "__len__")
False
>>> hasattr(1.3, "__len__")
False
>>> hasattr("a", "__len__")
True
>>> hasattr([1,2,3], "__len__")
True
>>> hasattr({1,2}, "__len__")
True
>>> hasattr({"a":1}, "__len__")
True
>>> hasattr(("a", 1), "__len__")
True

objets Aucun-itérables ne mettre en œuvre cela pour des raisons évidentes. Cependant, il ne se coince pas iterables définis par l'utilisateur qui ne mettent pas en œuvre, ni font les expressions du générateur, qui iter peut traiter. Cependant, cela peut se faire en ligne, et en ajoutant une simple expression de or vérification des générateurs devrait corriger ce problème. (Notez que l'écriture type(my_generator_expression) == generator jetterait un NameError. Reportez-vous à cette répondre à la place.)

  

Vous pouvez utiliser GeneratorType de types:

>>> import types
>>> types.GeneratorType
<class 'generator'>
>>> gen = (i for i in range(10))
>>> isinstance(gen, types.GeneratorType)
True
     

--- réponse acceptée par utdemir

(Ceci le rend utile pour vérifier si vous pouvez appeler len sur l'objet même.)

un peu tard à la fête mais je me suis posé cette question et ai vu ce alors pensé à une réponse. Je ne sais pas si quelqu'un a déjà publié ce billet. Mais essentiellement, je l'ai remarqué que tous les types itérables ont " getitem " dans leur dict. Voici comment vous vérifier si un objet était un itérables sans même essayer. (Jeu de mots)

def is_attr(arg):
    return '__getitem__' in dir(arg)

Pas vraiment "correct" mais peut servir de vérification rapide des types les plus courants comme des chaînes, tuples, flotteurs, etc ...

>>> '__iter__' in dir('sds')
True
>>> '__iter__' in dir(56)
False
>>> '__iter__' in dir([5,6,9,8])
True
>>> '__iter__' in dir({'jh':'ff'})
True
>>> '__iter__' in dir({'jh'})
True
>>> '__iter__' in dir(56.9865)
False

A part essayer régulière et sauf, vous pouvez exécuter l'aide.

temp= [1,2,3,4]
help(temp)

aide donnerait toutes les méthodes qui pourraient être exécutées sur cet objet (il pourrait être un objet et ne peut pas être une liste comme dans l'exemple), qui est temporaire dans ce cas.

Note:. Ce serait quelque chose que vous feriez manuellement

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