Je le fais comme:
def set_property(property,value):
def get_property(property):
ou
object.property = value
value = object.property
Je suis nouveau sur Python, donc j'explore toujours la syntaxe, et j'aimerais avoir des conseils pour le faire.
python
getter-setter
Jorge Guberte
la source
la source
._x
(qui n'est pas une propriété, juste un attribut ordinaire) contournent leproperty
wrapping. Seules les références pour.x
passer par leproperty
.La manière "Pythonique" n'est pas d'utiliser des "getters" et des "setters", mais d'utiliser des attributs simples, comme le montre la question, et
del
pour les supprimer (mais les noms sont modifiés pour protéger les innocents ... intégrés):Si plus tard, vous souhaitez modifier le paramètre et obtenir, vous pouvez le faire sans avoir à modifier le code utilisateur, en utilisant le
property
décorateur:(Chaque décorateur utilise des copies et met à jour l'objet de propriété précédent, alors notez que vous devez utiliser le même nom pour chaque fonction / méthode définie, récupérée et supprimée.
Après avoir défini ce qui précède, le paramètre d'origine, l'obtention et la suppression du code sont les mêmes:
Vous devez éviter cela:
Premièrement, ce qui précède ne fonctionne pas, car vous ne fournissez pas d'argument pour l'instance que la propriété serait définie sur (généralement
self
), ce qui serait:Deuxièmement, cela fait double emploi avec l'objectif de deux méthodes spéciales,
__setattr__
et__getattr__
.Troisièmement, nous avons également les fonctions
setattr
etgetattr
intégrées.Le
@property
décorateur sert à créer des getters et des setters.Par exemple, nous pouvons modifier le comportement du paramètre pour placer des restrictions sur la valeur définie:
En général, nous voulons éviter d'utiliser
property
et simplement utiliser des attributs directs.C'est ce à quoi s'attendent les utilisateurs de Python. En suivant la règle de la moindre surprise, vous devriez essayer de donner à vos utilisateurs ce qu'ils attendent, sauf si vous avez une raison très convaincante du contraire.
Manifestation
Par exemple, supposons que nous voulions que l'attribut protégé de notre objet soit un entier compris entre 0 et 100 inclus, et empêcher sa suppression, avec des messages appropriés pour informer l'utilisateur de sa bonne utilisation:
(Notez que
__init__
fait référence àself.protected_value
mais les méthodes de propriété font référenceself._protected_value
. C'est ainsi qui__init__
utilise la propriété via l'API publique, garantissant qu'elle est "protégée".)Et l'utilisation:
Les noms importent-ils?
Oui, ils le font .
.setter
et.deleter
faire des copies de la propriété d'origine. Cela permet aux sous-classes de modifier correctement le comportement sans altérer le comportement du parent.Maintenant, pour que cela fonctionne, vous devez utiliser les noms respectifs:
Je ne sais pas où cela serait utile, mais le cas d'utilisation est si vous voulez une propriété get, set et / ou delete-only. Il vaut probablement mieux s'en tenir à la même propriété sémantiquement portant le même nom.
Conclusion
Commencez avec des attributs simples.
Si vous avez besoin ultérieurement de fonctionnalités pour définir, obtenir et supprimer, vous pouvez l'ajouter avec le décorateur de propriétés.
Évitez les fonctions nommées
set_...
etget_...
- c'est à cela que servent les propriétés.la source
__init__
méthode fait référenceself.protected_value
mais le getter et les setters font référenceself._protected_value
. Pourriez-vous expliquer comment cela fonctionne? J'ai testé votre code et il fonctionne tel quel - ce n'est donc pas une faute de frappe.__init__
cas?self.protected_value = start_protected_value
fait la fonction setter; Je pensais que c'était une mission.la source
Utiliser
@property
et@attribute.setter
vous aide non seulement à utiliser la méthode "pythonique" mais aussi à vérifier la validité des attributs à la fois lors de la création de l'objet et lors de sa modification.Par cela, vous «cachez» réellement l'
_name
attribut des développeurs clients et effectuez également des vérifications sur le type de propriété de nom. Notez qu'en suivant cette approche même pendant l'initiation, le passeur est appelé. Alors:Mènera à:
Mais:
la source
Découvrez le
@property
décorateur .la source
Vous pouvez utiliser des accesseurs / mutateurs (ie
@attr.setter
et@property
) ou non, mais le plus important est d'être cohérent!Si vous utilisez
@property
pour accéder simplement à un attribut, par exempleutilisez-le pour accéder à chaque * attribut! Ce serait une mauvaise pratique d’accéder à certains attributs en utilisant
@property
et de laisser d’autres propriétés publiques (c.-à-d. Nom sans trait de soulignement) sans accesseur, par exemple ne pas faireNotez qu'il
self.b
n'a pas d'accesseur explicite ici même s'il est public.De même avec les setters (ou mutateurs ), n'hésitez pas à utiliser
@attribute.setter
mais soyez cohérent! Quand vous faites par exempleJ'ai du mal à deviner votre intention. D'une part, vous dites que les deux
a
etb
sont publics (pas de soulignement principal dans leurs noms), donc je devrais théoriquement être autorisé à accéder / muter (obtenir / définir) les deux. Mais ensuite, vous spécifiez un mutateur explicite uniquement poura
, ce qui me dit que je ne devrais peut-être pas pouvoir définirb
. Puisque vous avez fourni un mutateur explicite, je ne sais pas si le manque d'accesseur explicite (@property
) signifie que je ne devrais pas être en mesure d'accéder à l'une de ces variables ou si vous étiez simplement économe en utilisant@property
.* L'exception est lorsque vous souhaitez explicitement rendre certaines variables accessibles ou modifiables mais pas les deux ou que vous souhaitez effectuer une logique supplémentaire lors de l'accès ou de la mutation d'un attribut. C'est à ce moment que j'utilise personnellement
@property
et@attribute.setter
(sinon pas d'acesseurs / mutateurs explicites pour les attributs publics).Enfin, les suggestions PEP8 et Google Style Guide:
PEP8, Designing for Inheritance dit:
D'autre part, selon les règles / propriétés du langage Python du Guide de style Google, la recommandation est de:
Les avantages de cette approche:
et contre:
la source
@property
, utiliser le reste@property
semble être une mauvaise décision.@property
(par exemple, exécuter une logique spéciale avant de retourner un attribut). Sinon, pourquoi décoreriez-vous un attribut@propery
et pas d'autres?@property
pour commencer, non? Si votre getter l'estreturn this._x
et que votre setter l'estthis._x = new_x
, alors utiliser@property
est un peu idiot.@property
est la cohérence".Vous pouvez utiliser les méthodes magiques
__getattribute__
et__setattr__
.Sachez que
__getattr__
et__getattribute__
ne sont pas les mêmes.__getattr__
n'est invoqué que lorsque l'attribut est introuvable.la source