Comment les @property décorateur de travail?
J'aimerais comprendre comment la fonction intégrée property
œuvres. Ce qui me confond, c'est que property
peut également être utilisé comme un décorateur, mais il suffit d'arguments lorsqu'il est utilisé comme une fonction intégrée et non pas lorsqu'il est utilisé comme un décorateur.
Cet exemple est à partir de la la documentation:
class C(object):
def __init__(self):
self._x = None
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
property
arguments sont getx
, setx
, delx
et un doc chaîne.
Dans le code ci-dessous property
est utilisé en tant que décorateur. L'objet, c'est la x
fonction, mais dans le code ci-dessus il n'y a pas de place pour une fonction de l'objet dans les arguments.
class C(object):
def __init__(self):
self._x = None
@property
def x(self):
"""I'm the 'x' property."""
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
Et, comment sont les x.setter
et x.deleter
décorateurs créé?
Je suis confus.
- Voir aussi: Comment puis-Python propriétés travail?
property
est en fait une classe (pas de fonction), bien qu'il ne fait sans doute appel à la__init__()
méthode lorsque vous effectuez un objet, bien sûr. À l'aide dehelp(property)
depuis le terminal est perspicace.help
est également une classe pour une raison quelconque.- Je pense que ce lien est un bon exemple: [propriété] (journaldev.com/14893/python-property-decorator)
- 2-année-vieux fils, mais encore: Tout est une classe. Même des classes.
- Cela a été déroutant pour moi aussi. J'ai enfin trouvé un article qui a été en mesure de briser pour moi. J'espère que cela aide quelqu'un d'autre. programiz.com/python-programming/property je ne suis pas affilié en aucune façon avec le site.
Vous devez vous connecter pour publier un commentaire.
La
property()
fonction renvoie un spécial descripteur de l'objet:C'est cet objet qui a supplémentaire méthodes:
Ceux-ci agissent comme des décorateurs trop. Ils reviennent une nouvelle propriété de l'objet:
qui est une copie de l'objet ancien, mais avec l'une des fonctions remplacé.
N'oubliez pas que le
@decorator
syntaxe est juste sucre syntaxique; la syntaxe:vraiment signifie la même chose que
donc
foo
la fonction est remplacé parproperty(foo)
, qui nous l'avons vu ci-dessus est un objet spécial. Ensuite, lorsque vous utilisez@foo.setter()
, ce que vous faites, c'est l'appel queproperty().setter
méthode que je vous ai montré ci-dessus, qui renvoie une nouvelle copie de la propriété, mais cette fois avec le setter remplacé par le décoré de la méthode.La séquence suivante crée également un plein sur la propriété, à l'aide de ces décorateur méthodes.
- Nous d'abord de créer des fonctions et une
property
objet avec juste un getter:Ensuite, nous utilisons la
.setter()
méthode pour ajouter un setter:Dernière, nous avons ajouter un deleter avec le
.deleter()
méthode:Dernier mais non le moins, la
property
objet agit comme un descripteur de l'objet, de sorte qu'il a.__obtenez__()
,.__définissez__()
et.__supprimer__()
méthodes de raccordement dans l'instance de l'attribut de l'obtention, de réglage et de suppression:Le Descripteur Howto comprend un pur python exemple de mise en œuvre de la
property()
type:Foo.prop = prop
vous pouvez faireFoo().prop = 5; pront Foo().prop; del Foo().prop
avec le résultat souhaité.property().getter
etproperty().deleter
ont la même adresse, maisproperty().setter
ne l'est pas?type(self)(self.fget, ...)
vsself.__class__(self.fget, ...)
? Pour moi, ce dernier semble plus propre, donc je voudrais l'utiliser dans mon propre projet, et si c'est la même chose.type()
que l'accès à dsous les attributs et les méthodes sont destinés à être utilisés comme points d'extension par le standard de fonctions et d'opérateurs.Property
exemple chaque fois que nous appelonsgetter()
,setter()
oudeleter()
au lieu de simplement modifier l'instance existante (self.fset = fset; return self
)?@human.name.getter
modifié leproperty
objet en place, plutôt que de retourner une nouvelle, lahuman.name
attribut, altération, modification du comportement de la super-classe.@property
de lecture des œuvres de style ancien, les classes trop mais@property.setter
ne l'est pas ?__get__
.getter
méthode?return type(self)(fget, self.fset, self.fdel, self.__doc__)
Im deviner qu'il devrait êtreself.fget
et pas seulementfget
droit? ou il y a une raison particulière pourquoi c'est de cette façon.@existing_property.getter
décorateur travaille.@existing_property.setter
ou@existing_property.deleter
en tant que décorateurs, mais si vous sous-classe quelque chose avec une propriété où vous souhaitez remplacer la lecture, vous pouvez utiliser@ParentClass.existing_property.getter
comme décorateur.getter
méthode, depuisreturn type(self)(fget, self.fset, self.fdel, self.__doc__)
est fondamentalement juste retour de la classe de droit? et le mot clé arguments sont déjà par défaut dansfset
etfdel
. peut legetter
de la méthode de ré-écrit à justereturn type(self)(fget)
? les deuxfset
etfdel
sont déjà avoir un défaut denone
fget
argument. Vous obtenez un nouveauproperty
instance configuré pour faire la même chose que l'ancien, à l'exception de lafget
attribut a été remplacé.type(self(fget))
, car alors le setter et le deleter et docstring seraient tous perdus.La Documentation dit c'est juste un raccourci pour créer propriétés readonly. Donc
est équivalent à
@property
comme décorateur dans leur classe.Voici un exemple minimal de la façon dont
@property
peuvent être mises en œuvre:Sinon
word
reste une méthode au lieu d'une propriété.self.word = my_word
-- qui serait alors de travailler de la même façonprint( Thing('ok').word ) = 'ok'
La première partie est simple:
est le même que
property
avec juste un getter.La prochaine étape serait d'étendre cette propriété avec un setter et un deleter. Et ce qui se passe avec les méthodes appropriées:
renvoie une nouvelle propriété qui hérite de tout, de la vieille
x
plus le setter.x.deleter
fonctionne de la même manière.Ce qui suit:
Est la même chose que:
Est la même chose que:
Est la même chose que:
Qui est le même que :
Ci-dessous est un autre exemple sur la façon
@property
peut aider quand on a de refactoriser le code qui est prise à partir ici (je ne les résumer ci-dessous):Imaginez que vous avez créé une classe
Money
comme ceci:et un utilisateur crée une bibliothèque en fonction de cette classe où il/elle utilise par exemple
Maintenant, supposons que vous décidez de changer votre
Money
de la classe et de se débarrasser de ladollars
etcents
attributs, mais au lieu de décider de piste uniquement, le montant total des centimes:Si le mentionnés ci-dessus, l'utilisateur tente d'exécuter son/sa bibliothèque comme avant
il en résultera une erreur
Qui signifie que maintenant tout le monde qui s'appuie sur l'original de votre
Money
classe aurait à changer toutes les lignes de code oùdollars
etcents
sont utilisées, ce qui peut être très douloureux... Alors, comment cela pourrait-il être évité? En utilisant@property
!C'est comment:
lorsque nous appelons aujourd'hui à partir de notre bibliothèque
il fonctionnera comme prévu et nous n'avons pas eu à changer une seule ligne de code dans notre bibliothèque! En fait, nous n'aurions même pas de savoir que la bibliothèque nous dépendons changé.
Également la
setter
fonctionne très bien:self.dollar = dollars
? nous avons fait beaucoup avec @bien, mais il semble qu'aucun extrait de fonctionnalité est ajoutée.J'ai lu tous les posts ici et réalisé que nous avons peut-être besoin d'un exemple réel, Pourquoi, en fait, nous avons @property?
Donc, envisager un Flacon d'application lorsque vous utilisez le système d'authentification.
Vous déclarez un modèle de l'Utilisateur dans
models.py
:Dans ce code, nous avons un attribut "caché"
password
en utilisant@property
qui déclencheAttributeError
assertion lorsque vous essayez d'y accéder directement, tandis que nous avons utilisé @property.setter pour définir la véritable variable d'instancepassword_hash
.Maintenant dans
auth/views.py
nous pouvons instancier un Utilisateur avec:Avis attribut
password
qui vient d'un formulaire d'inscription lorsqu'un utilisateur remplit le formulaire. Confirmation du mot de passe qui se passe sur le front-end avecEqualTo('password', message='Passwords must match')
(dans le cas où si vous vous demandez, mais c'est un autre sujet lié Flacon de formes).J'espère que cet exemple sera utile
Ce point est été compensé par beaucoup de gens là-haut, mais ici, c'est un direct point que je cherchais.
C'est ce que je ressens est important de commencer avec les @property décorateur.
par exemple:-
L'appel de la fonction "get_config()" fonctionne comme ceci.
Si vous remarquez que je n'ai pas utilisé "()" entre parenthèses pour l'appel de la fonction. C'est la chose que j'ai été à la recherche pour les @property décorateur. De sorte que vous pouvez utiliser votre fonction comme une variable.
Nous allons commencer avec Python décorateurs.
Un Python décorateur est une fonction qui permet d'ajouter des fonctionnalités supplémentaires à un cadre déjà défini la fonction.
En Python, tout est objet En Python, tout est objet. Les fonctions en Python sont des objets de première classe qui signifie qu'ils peuvent être référencé par une variable, ajoutés dans les listes, passées en argument à une autre fonction, etc.
Envisager l'extrait de code suivant.
Ici, nous pouvons dire que la fonction décorateur modifié notre dit_bonjour fonction et l'ajout de quelques lignes de code supplémentaires en elle.
La syntaxe de Python pour décorateur
Nous allons Conclure de tout ce que avec un scénario, mais avant cela, parlons un peu de la oups principes.
Getters et les setters sont utilisés dans de nombreux langages de programmation orientée objet afin de garantir le principe d'encapsulation des données(est considéré comme le regroupement de données avec les méthodes qui fonctionnent sur ces données.)
Ces méthodes sont bien sûr de la lecture pour la récupération des données et la définition pour changer les données.
Selon ce principe, les attributs d'une classe sont privés de cacher et de protéger de l'autre code.
Yup, @property est fondamentalement un pythonic façon d'utiliser les accesseurs et mutateurs.
Python est un grand concept de propriété qui rend la vie d'un objet-orienté programmeur beaucoup plus simple.
Supposons que vous décidez de faire une classe qui peut stocker la température en degré Celsius.
Refonte du Code, Voici comment nous avons pu obtenir cela avec la propriété.
En Python, la propriété() est une fonction intégrée qui crée et retourne un objet de propriété.
Un objet de propriété a trois méthodes getter(), setter () et delete().
Ici,
pourrait avoir été ventilés comme,
Point À Noter:
Vous pouvez maintenant accéder à la valeur de la température par écrit.
Nous pouvons aller plus loin et de ne pas définir des noms get_temperature et set_temperature comme elles sont inutiles, et de polluer l'espace de noms de la classe.
La pythonic façon pour traiter le problème ci-dessus est d'utiliser @property.
Points à Noter -
Comme vous pouvez le voir, le code est nettement moins élégant.
Maintenant,nous allons parler de la vie réelle pratique scenerio.
Disons que vous avez conçu une classe comme suit:
Maintenant, laissez-nous supposons que nos élèves se sont populaires parmi les clients et ils ont commencé à l'utiliser dans leurs programmes, Ils ont fait toutes sortes de missions à l'objet.
Et Un jour fatidique, un fidèle client est venu vers nous et a suggéré que "x" doit être une valeur comprise entre 0 et 1000, c'est vraiment une horrible scénario!
En raison de ces propriétés, il est facile: Nous créons une propriété de la version de "x".
C'est formidable, n'est-ce pas: Vous pouvez commencer par les plus simples de mise en œuvre possibles et imaginables et vous êtes libre de migrer plus tard à une propriété de la version sans avoir à changer l'interface! Ainsi les propriétés ne sont pas juste un remplacement pour les méthodes de lecture et de définition!
Vous pouvez le vérifier la mise en Œuvre ici
property
est une classe derrière@property
décorateur.Vous pouvez toujours vérifier ceci:
J'ai réécrit l'exemple de
help(property)
pour montrer que la@property
syntaxeest fonctionnellement identique à
property()
syntaxe:Il n'y a pas de différence à la façon dont nous utilisons la propriété comme vous pouvez le voir.
Pour répondre à la question
@property
décorateur est mis en œuvre parproperty
classe.Donc, la question est d'expliquer la
property
classe un peu.Cette ligne:
A l'initialisation. On peut réécrire comme ceci:
Le sens de
fget
,fset
etfdel
:L'image suivante montre les triplets nous avons, à partir de la classe
property
:__get__
,__set__
, et__delete__
sont là pour être remplacé. C'est la mise en œuvre du descripteur de modèle en Python.On peut aussi utiliser la propriété
setter
,getter
etdeleter
méthodes pour lier la fonction à la propriété. Vérifiez l'exemple suivant. La méthodes2
de la classeC
va définir la propriété doublé.Une propriété peut être déclarée dans deux façons.
Vous pouvez jeter un oeil à quelques exemples que j'ai écrit au sujet de propriétés en python.
Voici un autre exemple:
Essentiellement le même que le C( objet ) exemple sauf que je suis en utilisant x à la place... je n'ai pas l'initialiser dans __init - ... et bien.. je ne, mais il peut être retiré parce que __x est défini comme faisant partie de la classe....
La sortie est:
et si j'ai fait un commentaire de l'auto.x = 1234 dans init alors la sortie est:
et si j'ai mis le _default = None pour _default = 0 dans la fonction get ( comme tous les getters doit avoir une valeur par défaut, mais il n'est pas passé par la propriété de valeurs à partir de ce que j'ai vu ainsi, vous pouvez définir ici, et en fait il n'est pas mauvais parce que vous pouvez définir la valeur par défaut une fois et l'utiliser partout ) c'est à dire: def x( self, _default = 0 ):
Remarque: La lecture de la logique est là juste pour avoir de la valeur, être manipulé par elle pour s'assurer qu'il est manipulé par elle - même pour l'impression des déclarations...
Remarque: j'ai l'habitude de Lua et d'être en mesure de créer dynamiquement 10+ aides lorsque j'appelle une fonction unique et j'ai fait quelque chose de similaire pour Python sans l'aide de ces propriétés et il fonctionne à un degré, mais, même si les fonctions sont en cours de création avant d'être utilisé, il y a toujours des problèmes à la fois avec eux d'être appelé avant d'être créé, ce qui est étrange, car il n'est pas codé de cette façon... je préfère la souplesse de Lua méta-tables et le fait que je peux utiliser réelle setters /getters à la place de essentiellement accéder directement à une variable... j'aime la manière dont rapidement certaines choses peuvent être construits avec Python bien que - par exemple des programmes graphiques. bien que celui que je suis en train de concevoir peut ne pas être possible sans beaucoup de bibliothèques supplémentaires - si je code en AutoHotkey je peux directement accéder à la dll appels dont j'ai besoin, et la même chose peut être fait en Java, C#, C++, et plus peut-être que je n'ai pas trouvé la bonne chose, mais encore pour ce projet j'ai peut passer de Python..
Remarque: Le code de sortie dans ce forum est cassé, j'ai dû ajouter des espaces pour la première partie du code pour qu'il fonctionne - lors de la copie /coller de vous assurer de convertir tous les espaces en tabulations.... J'utilise des onglets pour Python car dans un fichier de 10 000 lignes de la taille du fichier peut être de 512 ko à 1 mo avec des espaces et de 100 à 200 KO, avec des onglets, ce qui équivaut à une différence énorme pour la taille du fichier, et la réduction du temps de traitement...
Onglets peuvent également être réglés par l'utilisateur, donc si vous préférez 2 espaces de largeur, 4, 8 ou ce que vous pouvez faire, c'est à dire réfléchie pour les développeurs avec vue déficits.
Remarque: Toutes les fonctions définies dans la classe ne sont pas indenté correctement en raison d'un bogue dans le forum logiciel - de vous assurer de l'indenter si vous copiez /collez
Une remarque:
pour moi, pour Python 2.x,
@property
ne fonctionne pas comme annoncé quand je n'ai pas hériter deobject
:mais sur le lieu de travail:
pour Python 3, travaillait toujours.
object
est un vieux de la classe de style, et vieux style de classes ne prennent pas en charge le descripteur de protocole (qui est ce queproperty
met en œuvre pour travailler à la manière dont il le fait). En Python 3, de style ancien des classes n'existe plus; tous classes sont ce que nous avons appelé le nouveau style de classes en Python 2.