En Python, comment puis-je déterminer si un objet est itérables?
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.
La solution
-
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__
. -
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'
-
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'appeleriter(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
-
Vous pouvez obtenir un itérateur de tout
o
objet en appelantiter(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__
. -
Vérification d'une instance de
Iterable
ouSequence
, ou le contrôle de la attribut__iter__
ne suffit pas. -
Si un
o
objet implémente uniquement__getitem__
, mais pas__iter__
,iter(o)
construira un itérateur qui tente d'extraire les articles deo
par l'indice entier, à partir de l'indice 0. L'itérateur va attraper touteIndexError
(mais pas d'autres erreurs) qui est soulevé et soulève alorsStopIteration
lui-même. -
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. -
Si un
o
objet implémente__iter__
, la fonctioniter
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__
. -
__iter__
gagne. Si uno
objet implémente à la fois__iter__
et__getitem__
,iter(o)
appellera__iter__
. -
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 deSequence
.
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'appeleriter(x)
et gérer une exceptionTypeError
si elle est pas. Ceci est plus précis que l'utilisationisinstance(x, abc.Iterable)
, cariter(x)
considère également la méthode__getitem__
héritage, alors que leIterable
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:
- Si vous implémentez
__iter__
, les instances sera considéré comme iterables etisinstance(o, collections.abc.Iterable)
retourneraTrue
. - Si l'objet retourné par
__iter__
n'est pas un itérateur,iter
échouera immédiatement et élever uneTypeError
. - 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).
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
ettuple
) et certains types de non-séquences commedict
etfile
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 str
s 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.
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 sontTrue == 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 sontTrue == 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 :
- 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 -
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 uneAttributeError
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