2009-08-03 6 views
5

J'ai quelque chose comme ceci:Créer des propriétés en utilisant getter lambda et régleurs

class X(): 
    def __init__(self): 
     self.__name = None 

    def _process_value(self, value): 
     # do something 
     pass 

    def get_name(self): 
     return self.__name 

    def set_name(self, value): 
     self.__name = self._process_value(value) 

    name = property(get_name, set_name) 

Puis-je remplacer get_name et set_name en utilisant les fonctions lambda?

J'ai essayé ceci:

name = property(lambda self: self.__name, lambda self, value: self.__name = self.process_value(value)) 

mais compilateur n'aime pas ma fonction setter.

+0

Qu'est-ce que "lissée"? –

+0

Probablement «quelque chose». – hughdbrown

+0

Il semble que vous essayez de rendre les définitions de propriété plus obscures. Quel est le point de remplacer les fonctions simples avec lambdas? –

Répondre

19

Votre problème est que le corps de lambda doit être une expression et l'affectation est une déclaration (une distinction forte et profonde en Python). Si vous insistez sur perpétrant lambda s vous rencontrerez de nombreux cas et d'apprendre les solutions de contournement (il y a en général un, mais pas toujours), comme dans ce cas:

name = property(lambda self: self.__name, 
       lambda self, value: setattr(self, 
              '_X__name', 
              self.process_value(value))) 

-à-dire utiliser le haut-setattr (qui est une fonction et donc acceptable dans le corps de lambda) plutôt que d'affectation (qui est une déclaration et donc inacceptable dans le corps de lambda).

Modifier: Vous devez également effectuer le nom mutiler pour l'attribut double underscore manuellement (changement __name à _X__name que vous êtes en classe X) où le nom d'attribut est présenté comme une chaîne entre guillemets, comme doit être dans setattr, car le compilateur Pyhon fait seulement le nom mangling en question pour les identifiants appropriés, pas pour les littéraux de chaîne.

+0

Super! Merci, Alex. – zinovii

+0

J'ai un autre problème ici. setattr ne fonctionne que pour "_name" et non "__name". – zinovii

+0

Ah oui, vous devez effectuer manuellement le mangling car il s'agit d'une chaîne entre guillemets - laissez-moi éditer en conséquence! –

1

Si vous étendez un list, vous pouvez également utiliser __setitem__, comme ceci:

class Position(list): 
    def __init__(self,x=0, y=0, z=0): 
     super(Position, self).__init__((x,y,z)) 

    x = property(lambda self: self[0], 
       lambda self,value: self.__setitem__(0, value)) 
    y = property(lambda self: self[1], 
       lambda self,value: self.__setitem__(1, value)) 
    z = property(lambda self: self[2], 
       lambda self,value: self.__setitem__(2, value)) 
Questions connexes