Les éléments issus du parsing de fichier XML sont-ils (vraiment) itérables ?

On peut itérer avec for mais isinstance(Iterable) n'est pas de cet avis...

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Je suis actuellement le cours de Python du site. En faisant des tests, je tombe sur quelque chose de curieux compte tenu de ce qui est avancé dans le cours.

Voici le petit code sur lequel je m’appuie :

import xml.etree.ElementTree as ET

tree = ET.parse("fichier.xml")
root = tree.getroot()

for elt in root:
    print(elt)  #ça marche donc root est itérable ?

from collections.abc import Iterable

print(isinstance(root, Iterable))   #renvoie False !!

Alors voilà donc le problème : il me semble que si on peut itérer dessus avec un for, isinstance(..., Iterable) devrait renvoyer True ?

Pour tester ce code, il faut un fichier xml de test sous la main donc je vous donne le mien ^^

<joueur>
	<taille>
		<assis> 120cm </assis>
		<debout> 175cm </debout>
	</taille>
	<age> 50 </age>
</joueur>

Merci pour l’aide !!

Depuis la documentation de collections.abc.Iterable:

class collections.abc.Iterable

ABC for classes that provide the __iter__() method.

Checking isinstance(obj, Iterable) detects classes that are registered as Iterable or that have an __iter__() method, but it does not detect classes that iterate with the __getitem__() method. The only reliable way to determine whether an object is iterable is to call iter(obj).

Donc je suppose que iter(root) devrait mieux marcher.

+1 -0

Je pense que tu fais référence à cette section où je présente isinstance et les interfaces de la lib standard telles que Iterable.
Ce n’est pas présenté comme étant « le moyen de savoir si itérable ou non » contrairement à ce que tu dis, mais comme un moyen d’utiliser isinstance pour autre chose qu’une vérification stricte du type. Il y est dit qu’on peut l’utiliser pour vérifier qu’un objet est itérable, et c’est vrai : tout objet pour lequel isinstance(obj, Iterable) est vrai est un itérable.

Le __iter__ est la manière habituelle d’identifier un itérable, mais il existe un second protocole qui fait que l’on peut itérer sur un objet : le cas des objets indexables détaillé ici.

Il y est dit qu’on peut l’utiliser pour vérifier qu’un objet est itérable, et c’est vrai : tout objet pour lequel isinstance(obj, Iterable) est vrai est un itérable.

Hmm… En fait, même dire ça est un peu trompeur. isinstance(obj, Iterable) vérifie juste que le protocole Iterable est implémenté dans le sens où une méthode __iter__ est implémentée. Il ne vérifie pas qu’il est implémenté correctement (i.e. que __iter__() renvoie un Iterator bien formé). Le fait que isintance(obj, Iterable) soit vrai ne garantie rien sur le fait que iter(obj) ou for item in obj vont se comporter comme attendu, ou autrement dit être Iterable n’implique pas le fait d’être effectivement itérable).

La philosophie "on est entre adultes consentants" de Python ressort ici en disant qu’il est de la responsabilité des développeurs de respecter les conventions, et donc d’implémenter (correctement) __iter__ pour que l’implication Iterable ⇒ itérable soit vraie en pratique. Ceci veut notamment dire qu’il est en fait très rarement utile de faire des vérifications avec isinstance, en rejoignant aussi la philosophie "il vaut mieux demander pardon que la permission". Si tu as une fonction qui prend un itérable comme argument, plutôt que de vérifier que c’est une instance de Iterable au runtime, tu as autant de directement itérer dessus et laisser le système d’exceptions faire son travail pour remonter les problèmes. Il est de la responsabilité des utilisateurs de ta librairie de fournir un itérable lorsqu’ils appellent ta fonction.

Évidemment, la philosophie "on est entre adultes consentants" peut se casser la figure assez magistralement lorsque des erreurs de typage passent silencieusement à travers les mailles du filets. Des outils d’analyse statiques comme mypy aident grandement à limiter ces problèmes.

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte