2015-04-10 1 views
6

En utilisant le décorateur @property, Python a complètement éliminé le besoin de getters et setters sur les propriétés de l'objet (certains pourraient dire 'attributs'). Cela rend le code beaucoup plus simple, tout en conservant l'extensibilité lorsque les choses doivent être plus complexes.Python: méthodes de prédicat en tant que propriétés?

Je me demandais ce que l'approche de Pythonic pour le type de méthode suivant est, cependant. Dire que j'ai la classe suivante:

class A(object): 
    def is_winner(self): 
     return True # typically a more arcane method to determine the answer 

Ces méthodes prennent généralement pas d'arguments, et sans effets secondaires. On pourrait appeler ces prédicats. Et compte tenu de leur nom, ils ressemblent souvent à quelque chose que l'on aurait aussi stocké comme une propriété.

Je suis enclin à ajouter un décorateur @property à ce qui précède, afin de pouvoir l'appeler comme une propriété d'objet (à savoir foo.is_winner), mais je me demandais si cela est la chose à faire la norme. À première vue, je n'ai trouvé aucune documentation sur ce sujet. Existe-t-il une norme commune pour cette situation?

+3

Si cela rend votre API * plus facile et plus propre à utiliser *, alors par tous les moyens, optez pour la propriété @! Vous n'avez pas besoin d'un guide de style pour vous le dire. –

+1

Eh bien, le premier changement évident qui doit être fait afin de rendre Pythonic est d'arrêter de camelcasing noms de méthodes. – rightfold

+2

Vous pouvez éviter d'utiliser des méthodes coûteuses (calcul ou E/S) dans les propriétés, du moins si vous ne les notez pas. –

Répondre

2

Il semble que le consensus général est que les attributs sont généralement considérés comme étant instantanés et prochain-à-utiliser, donc si le calcul étant décoré comme @ propriété est cher, il est probablement préférable de mettre en cache le résultat pour utilisation répétée (@Martijn Pieters) ou de le laisser comme une méthode, car on s'attend généralement à ce que les méthodes prennent plus de temps que les recherches d'attributs. PEP 8 notes spécifiquement:

  • Note 2: Essayez de garder le comportement fonctionnel sans effets secondaires, bien que les effets secondaires tels que la mise en cache sont généralement bien.

  • Note 3: Évitez d'utiliser des propriétés pour des opérations coûteuses en calcul; la notation d'attribut fait croire à l'appelant que l'accès est (relativement) bon marché.


Un cas d'utilisation particulière du décorateur @property est d'ajouter un comportement à une classe sans exiger que les utilisateurs du changement de classe de foo.bar références à foo.bar() appels -, si vous voulez par exemple comptez le nombre de fois qu'un attribut a été référencé, vous pouvez convertir l'attribut en @property où la méthode décorée manipule un état avant de renvoyer les données demandées.

Voici un exemple de la classe d'origine:

class Cat(object): 
    def __init__(self, name): 
     self.name = name 

# In user code 
baxter = Cat('Baxter') 
print(baxter.name) # => Baxter 

Avec le décorateur @property, nous pouvons maintenant ajouter certaines machines sous le capot sans affecter le code utilisateur:

class Cat(object): 
    def __init__(self, name): 
     self._name = name 
     self._name_access_count = 0 

    @property 
    def name(self): 
     self._name_access_count += 1 
     return self._name 

# User code remains unchanged 
baxter = Cat('Baxter') 
print(baxter.name) # => Baxter 

# Also have information available about the number of times baxter's name was accessed 
print(baxter._name_access_count) # => 1 
baxter.name      # => 'Baxter' 
print(baxter._name_access_count) # => 2 

Ce traitement du décorateur @property a été mentionné dans certains articles de blog (1, 2) comme l'un des principaux cas d'utilisation - nous permettant d'écrire d'abord le code le plus simple possible, puis plus tard passer à @ propery-décoré rencontré hods quand nous avons besoin de la fonctionnalité.