Valeurs par défaut pour les paramètres de fonction en Python [dupliquer]
possible Duplicate:
valeur par défaut du paramètre résultant de la méthode d'instance
alors qu'il est 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 impossible d'accéder à l'instance actuelle (self):
class MyClass(..):
def my_function(self, param_one=self.one_of_the_vars):
...
ma question (s):
- est-ce vrai que je ne peux pas accéder à l'instance courante pour définir le paramètre par défaut dans les fonctions?
- Si elle n'est pas possble: quelles sont les raisons et est-il imaginable que ce sera possible dans les futures versions de python?
4 réponses
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 sûr de dire que cela n'arrivera jamais en Python en raison de la nature que self
n'existe pas vraiment jusqu'à ce que la fonction commence... (vous ne pouvez pas y faire 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 vous le pensez. Considérons que les valeurs par défaut sont statique (=référence constante pointant vers un objet) et stockées quelque part dans la définition; évaluées au moment de la définition de la méthode; dans le cadre de la classe , pas l'instance. Comme ils sont constants, ils ne peuvent pas dépendre de self
.
voici un exemple. C'est contre-intuitif, mais rend en fait parfait sens:
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
ce sera imprimé 1 2 1 1 3
.
parce qu'il 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 y a plusieurs solutions de rechange, y compris
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)
alors 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 une 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 []
valeur par défaut pour les paramètres sont évalués à "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 ajoutez des éléments, la valeur par défaut pour le paramètre change!
la solution est d'utiliser un autre paramètre par défaut, typiquement None
, puis de vérifier et mettre à jour la variable.
il y a plusieurs fausses hypothèses que vous faites ici - D'abord, la fonction appartient à une classe et non à une instance, ce qui signifie que la fonction réelle impliquée est la même pour deux instances d'une 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 constant - si le paramètre est un objet mutable, vous pouvez le modifier). Ainsi, vous ne pouvez pas accéder à self
dans un paramètre par défaut et ne pourrez jamais le faire.