Question

Si je comprends bien, je peux utiliser la construction de la boucle de for sur un objet avec une méthode de __iter__ qui retourne un itérateur. Je un objet pour lequel je mettre en œuvre le procédé de __getattribute__ de suivant:

def __getattribute__(self,name):
    if name in ["read","readlines","readline","seek","__iter__","closed","fileno","flush","mode","tell","truncate","write","writelines","xreadlines"]:
        return getattr(self.file,name)
    return object.__getattribute__(self,name)

J'ai un objet de cette classe, a pour laquelle les éléments suivants se produit:

>>> hasattr(a,"__iter__")
True
>>> for l in a: print l
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'TmpFile' object is not iterable
>>> for l in a.file: print l
...
>>>

python Ainsi voit que a a une méthode de __iter__, mais ne pense pas que ce soit itérables. Qu'est ce que j'ai mal fait? C'est avec python 2.6.4.

Était-ce utile?

La solution

Il y a un détail de mise en œuvre subtile obtenir de votre manière: __iter__ n'est pas réellement une méthode d'instance, mais une méthode de classe. Autrement dit, obj.__class__.__iter__(obj) est appelé, plutôt que obj.__iter__().

Ceci est dû à des optimisations de machines à sous sous le capot, ce qui permet l'exécution Python de mettre en place plus rapidement itérateurs. Cela est nécessaire car il est très important que itérateurs être aussi rapide que possible.

Il est impossible de définir __getattribute__ pour le type de class sous-jacente, il est donc impossible de retourner cette méthode dynamique. Cela vaut pour la plupart __metamethods__; vous aurez besoin d'écrire une enveloppe réelle.

Autres conseils

Certaines des méthodes spéciales sont optimisées quand une classe est créée et ne peut être ajouté ultérieurement ou annulé par la cession. Consultez la documentation pour __getattribute__ qui dit:

Cette méthode peut encore être contournée lorsque à la recherche des méthodes spéciales comme la résultat d'invocation implicite par syntaxe du langage ou des fonctions intégrées.

Ce que vous devez faire dans ce cas fournir une mise en œuvre directe de __iter__ qui transmet l'appel:

def __iter__(self):
    return self.file.__iter__()
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top