2009-04-11 2 views
14

Étant donné une classe qui tient un registre de ses objets:Enumérer les instances d'objets d'une classe donnée en Python

class Person(object): 
    __registry = [] 

    def __init__(self, name): 
     self.__registry.append(self) 
     self.name = name 

Comment puis-je faire fonctionner le code suivant (sans utiliser Personne .__ Registre):

for personobject in Person: 
    print personobject 

En recherchant j'ai trouvé un indice que l'on pourrait aller pour un __metaclass__ avec __getitem__ -method. Des idées à quoi cela ressemblerait?

+0

ehh ne fait pas un hack laid look jolie. –

Répondre

20

Vous pouvez rendre votre objet de classe itérable avec une simple métaclasse.

class IterRegistry(type): 
    def __iter__(cls): 
     return iter(cls._registry) 

class Person(object): 
    __metaclass__ = IterRegistry 
    _registry = [] 

    def __init__(self, name): 
     self._registry.append(self) 
     self.name = name 

(j'ai également changé __registry à _registry pour faciliter l'accès de la métaclasse). Ensuite,

>>> p = Person('John') 
>>> p2 = Person('Mary') 
>>> for personobject in Person: 
...  print personobject 
... 
<person.Person object at 0x70410> 
<person.Person object at 0x70250> 
+0

merci beaucoup ... c'était exactement ce que je cherchais;) – Titusz

+0

Très bon conseil: je ne connaissais pas celui-ci :) – jkp

+0

Pourquoi cela ne fonctionne-t-il pas simplement en mettant le def __iter__ dans la classe Person? Je me demandais juste. –

2

vous pouvez le faire avec:

for item in Person.__registry: 
    print(item) 
+0

c'est évident ... mais je voudrais le faire fonctionner comme: pour l'objet dans Classname ... (juste pour la beauté de celui-ci ...) – Titusz

+0

vous devez faire votre classe itérable alors, je suppose – SilentGhost

+0

et ce n'est pas btw bel, – SilentGhost

10

Tout d'abord, ne pas utiliser le double __ noms. Ils sont réservés à Python. Si vous voulez "privé" utiliser unique _. Deuxièmement, gardez ce genre de chose aussi simple que possible. Ne perdez pas beaucoup de temps et d'énergie sur quelque chose de complexe. C'est un problème simple, gardez le code aussi simple que possible pour faire le travail.

class Person(object): 
    _registry = [] 

    def __init__(self, name): 
     self._registry.append(self) 
     self.name = name 

for p in Person._registry: 
    print p 
+0

Le point est que la solution _registry * est * le moyen le plus simple possible de le faire. Tout le reste essaie juste de "mettre du rouge à lèvres sur un cochon". –