Duplicate possible:
valeur par défaut du paramètre en tant que résultat de la méthode d'instance
Bien qu'il soit possible de définir des valeurs par défaut pour les paramètres de fonction en python:
def my_function(param_one='default')
...
Il semble ne pas être possible d'accéder à l'instance actuelle (self):
class MyClass(..):
def my_function(self, param_one=self.one_of_the_vars):
...
Mes questions):
C'est écrit comme:
def my_function(self, param_one=None): # Or custom sentinel if None is vaild
if param_one is None:
param_one = self.one_of_the_vars
Et je pense qu'il est prudent de dire que cela n'arrivera jamais dans Python en raison de la nature que self
n'existe pas tant que la fonction n'a pas démarré ... (vous ne pouvez pas référence, dans sa propre définition - comme tout le reste)
Par exemple: vous ne pouvez pas faire d = {'x': 3, 'y': d['x'] * 5}
Il y a beaucoup plus que ce que vous pensez. Considérez les valeurs par défaut comme étant statique (= référence constante pointant vers un objet ) et stockés quelque part dans la définition; évalué au moment de la définition de la méthode; dans le cadre de la classe , pas de l'instance. Comme ils sont constants, ils ne peuvent pas dépendre de self
.
Voici un exemple. C'est contre-intuitif, mais c'est tout à fait logique:
def add(item, s=[]):
s.append(item)
print len(s)
add(1) # 1
add(1) # 2
add(1, []) # 1
add(1, []) # 1
add(1) # 3
Ceci imprimera 1 2 1 1 3
.
Parce que cela fonctionne de la même manière que
default_s=[]
def add(item, s=default_s):
s.append(item)
Évidemment, si vous modifiez default_s
, il conserve ces modifications.
Il existe différentes solutions de contournement, notamment
def add(item, s=None):
if not s: s = []
s.append(item)
ou vous pouvez faire ceci:
def add(self, item, s=None):
if not s: s = self.makeDefaultS()
s.append(item)
Ensuite, la méthode makeDefaultS
aura accès à self
.
Une autre variante:
import types
def add(item, s=lambda self:[]):
if isinstance(s, types.FunctionType): s = s("example")
s.append(item)
ici, la valeur par défaut de s
est un fonction d'usine.
Vous pouvez combiner toutes ces techniques:
class Foo:
import types
def add(self, item, s=Foo.defaultFactory):
if isinstance(s, types.FunctionType): s = s(self)
s.append(item)
def defaultFactory(self):
""" Can be overridden in a subclass, too!"""
return []
Les valeurs par défaut pour les paramètres sont évaluées lors de la "compilation", une fois. Donc, évidemment, vous ne pouvez pas accéder à self
. L'exemple classique est list
comme paramètre par défaut. Si vous y ajoutez des éléments, la valeur par défaut du paramètre change!
La solution de contournement consiste à utiliser un autre paramètre par défaut, généralement None
, puis à vérifier et à mettre à jour la variable.
Vous faites ici de multiples fausses hypothèses. Premièrement, la fonction appartient à une classe et non à une instance, ce qui signifie que la fonction impliquée est la même pour deux instances de la classe. Deuxièmement, les paramètres par défaut sont évalués au moment de la compilation et sont constants (comme dans, une référence d'objet constante - si le paramètre est un objet modifiable, vous pouvez le changer). Ainsi, vous ne pouvez pas accéder à self
avec un paramètre par défaut et vous ne pourrez jamais le faire.