Подтвердить что ты не робот

Значения по умолчанию для параметров функции в Python

Возможный дубликат:
значение по умолчанию параметра в качестве результата метода экземпляра

Пока можно задать значения по умолчанию для параметров функции в python:

def my_function(param_one='default')
    ...

Кажется, что невозможно получить доступ к текущему экземпляру (self):

class MyClass(..):

    def my_function(self, param_one=self.one_of_the_vars):
        ...

Мой вопрос (ы):

  • Это правда, что я не могу получить доступ к текущему экземпляру, чтобы установить параметр по умолчанию в функции?
  • Если это не возможно: каковы причины и можно ли это представить в будущих версиях python?
4b9b3361

Ответ 1

Он записывается как:

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

И я думаю, что можно с уверенностью сказать, что никогда не произойдет в Python из-за того, что self действительно не существует до тех пор, пока функция не начнет... (вы не можете ссылаться на нее, в своем собственном определении - например все остальное)

Например: вы не можете сделать d = {'x': 3, 'y': d['x'] * 5}

Ответ 2

Это гораздо больше, чем вы думаете. Рассмотрите статические значения по умолчанию (= постоянная ссылка, указывающая на один объект) и хранящиеся где-нибудь в определении; оценивается по времени определения метода; как часть класса, а не экземпляр. Поскольку они постоянны, они не могут зависеть от self.

Вот пример. Это противоречиво, но на самом деле имеет смысл:

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

Откроется 1 2 1 1 3.

Поскольку он работает так же, как

default_s=[]
def add(item, s=default_s):
    s.append(item)

Очевидно, что если вы изменяете default_s, он сохраняет эти изменения.

Существуют различные обходные пути, включая

def add(item, s=None):
    if not s: s = []
    s.append(item)

или вы можете сделать это:

def add(self, item, s=None):
    if not s: s = self.makeDefaultS()
    s.append(item)

Тогда метод makeDefaultS будет иметь доступ к self.

Другая вариация:

import types
def add(item, s=lambda self:[]):
    if isinstance(s, types.FunctionType): s = s("example")
    s.append(item)

здесь значение по умолчанию s является factory функцией.

Вы можете объединить все эти методы:

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 []

Ответ 3

Значение по умолчанию для параметров оценивается в "компиляции" один раз. Очевидно, что вы не можете получить доступ к self. Классическим примером является list как параметр по умолчанию. Если вы добавите в него элементы, значение по умолчанию для параметра изменится!

Обходной путь - использовать другой параметр по умолчанию, обычно None, а затем проверить и обновить переменную.

Ответ 4

Существует несколько ложных предположений, которые вы здесь делаете. Во-первых, функция принадлежит классу, а не экземпляру, что означает, что задействованная фактическая функция одинакова для любых двух экземпляров класса. Во-вторых, параметры по умолчанию оцениваются во время компиляции и являются постоянными (как в случае с константной ссылкой на объект - если параметр является изменяемым объектом, вы можете его изменить). Таким образом, вы не можете получить доступ к self в параметре по умолчанию и никогда не сможете.