Comment passer un argument par défaut de la valeur d'un membre de l'instance à une méthode?
Je veux passer un argument par défaut à une méthode d'instance à l'aide de la valeur d'un attribut de l'instance:
class C:
def __init__(self, format):
self.format = format
def process(self, formatting=self.format):
print(formatting)
En essayant ça, j'obtiens le message d'erreur suivant:
NameError: name 'self' is not defined
Je veux la méthode pour se comporter comme ceci:
C("abc").process() # prints "abc"
C("abc").process("xyz") # prints "xyz"
Quel est le problème ici, pourquoi n'est-ce pas le travail? Et comment pourrais-je faire ce travail?
- ne pas utiliser le format de nom de variable, car il est intégré dans la fonction en python.
- L'édition de l'erreur de
self
dansprocess method
Vous devez vous connecter pour publier un commentaire.
On ne peut pas vraiment définir ce que la valeur par défaut, puisque la valeur par défaut est évaluée lorsque la méthode est définie, qui est avant tout des instances existent. Le schéma habituel est de faire quelque chose comme ceci à la place:
self.format
ne sera utilisé que siformatting
estNone
.Pour démontrer le point de la façon dont les valeurs par défaut de travail, voir cet exemple:
Et la sortie de ici:
Avis comment
mk_default
a été appelé qu'une seule fois, et c'est arrivé avant que la fonction n'a jamais été appelé!mk_default
a été appelé avant les fonctions ont été appelés depuisfoo=mk_default()
a appelé, en raison de la parenthèse. Ne devrait-elle pas êtrefoo=mk_default
? Ensuite, votre exemple pourrait changer àmyfun("testing")
suivie parmyfun()
.formatting = formatting or self.format
sera misformatting
àself.format
siformatting
est un falsey valeur, tels que des 0. - Ce juste de me mordre. Un moyen plus sûr est de typeformatting = formatting if formatting is not None else self.format
ou l'équivalent.En Python, le nom
self
est pas spécial. C'est juste une convention pour le nom du paramètre, qui est pourquoi il estself
paramètre dans__init__
. (En fait,__init__
n'est pas très spécial, et en particulier, il ne pas réellement créer l'objet... c'est une longue histoire)C("abc").process()
crée unC
exemple, regarde leprocess
méthode dans leC
classe, et les appels de la méthode, laC
instance en tant que premier paramètre. Donc, il finira dans laself
paramètre si vous les avez fournies.Même si vous avez eu ce paramètre, bien que, vous ne serait pas autorisé à écrire quelque chose comme
def process(self, formatting = self.formatting)
, parce queself
n'est pas dans le champ d'application encore au point où vous définissez la valeur par défaut. En Python, la valeur par défaut pour un paramètre est calculé lorsque la fonction est compilé, et "collé" à la fonction. (C'est la même raison pourquoi, si vous utilisez un défaut comme[]
, cette liste permettra de mémoriser les modifications entre les appels à la fonction.)La méthode traditionnelle consiste à utiliser
None
comme un défaut, et vérifier que la valeur et de la remplacer à l'intérieur de la fonction. Vous pouvez trouver qu'il est un peu plus sûr de faire une valeur spéciale pour la fin (uneobject
exemple est tout ce dont vous avez besoin, aussi longtemps que vous le cacher, de sorte que le code appelant ne pas utiliser le même exemple) au lieu deNone
. De toute façon, vous devriez vérifier cette valeur avecis
, pas==
.None
est une valeur valide pourformatting
, alors vous aurez à choisir autre chose, comme je l'ai expliqué.Puisque vous souhaitez utiliser
self.format
comme un argument par défaut ce qui implique que la méthode doit être l'instance spécifique (à savoir qu'il n'est pas possible de définir ce au niveau de la classe). Au lieu de cela, vous pouvez définir la méthode spécifique au cours de la classe de__init__
par exemple. C'est là que vous avez accès à l'instance des attributs particuliers.Une approche consiste à utiliser
functools.partielle
afin d'obtenir une mise à jour (spécifique) de la version de la méthode:À noter qu'avec cette approche, vous pouvez seulement passer l'argument correspondant par mot-clé, puisque si vous les avez fournies par la position, ce serait de créer un conflit dans
partial
.Une autre approche est de définir et d'appliquer la méthode dans
__init__
:Cela permet également de passage de l'argument par la position, cependant, la méthode de résolution de l'ordonnance devient moins apparente (ce qui peut affecter l'IDE d'inspection par exemple, mais je suppose qu'il y IDE les solutions spécifiques pour que).
Une autre approche serait de créer un type personnalisé pour ce genre de "instance d'attribut par défaut" en combinaison avec un décorateur qui effectue le correspondant
getattr
argument de remplissage:"auto" besoin d'être passer comme premier argument à toutes les fonctions de classe si vous voulez qu'ils se comportent comme des non-méthodes statiques.
il se réfère à l'objet lui-même. Vous ne pouvait pas passer "auto" comme argument par défaut comme il est de fixer comme premier argument.
Dans votre cas, au lieu de "mise en forme=auto.format" utiliser "formatage=None" et puis d'attribuer de la valeur à partir de code comme ci-dessous:
[MODIFIER]
Remarque : n'utilisez pas de "format", comme nom de variable, car il est intégré dans la fonction en python
self
problème. Mais votre réponse n'a pas satisfait à la sortie souhaitée.Vous ne pouvez pas accéder à l'autonomie dans la définition de la méthode. Ma solution est-ce -
Au lieu de créer une liste de si-arrêtera que la durée par défaut de vos arguments, on peut utiliser un "valeurs par défaut" du dictionnaire et de créer de nouvelles instances d'une classe à l'aide de la fonction eval():
Je jette ce au début de chaque classe qui instancie une autre classe comme un argument par défaut. Il évite python évaluation de la valeur par défaut lors de la compilation... j'aimerais un nettoyeur de pythonic approche, mais lo'.