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?
46
demandé sur Community 2012-11-02 17:16:59

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}

53
répondu Jon Clements 2012-11-02 13:18:48

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 []
14
répondu Anony-Mousse 2012-11-02 13:33:22

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.

3
répondu Karoly Horvath 2012-11-02 13:20:47

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.

2
répondu l4mpi 2012-11-02 13:24:07