Значения по умолчанию для параметров функции в Python
Возможный дубликат:
значение по умолчанию параметра в качестве результата метода экземпляра
Пока можно задать значения по умолчанию для параметров функции в python:
def my_function(param_one='default')
...
Кажется, что невозможно получить доступ к текущему экземпляру (self):
class MyClass(..):
def my_function(self, param_one=self.one_of_the_vars):
...
Мой вопрос (ы):
- Это правда, что я не могу получить доступ к текущему экземпляру, чтобы установить параметр по умолчанию в функции?
- Если это не возможно: каковы причины и можно ли это представить в будущих версиях python?
Ответы
Ответ 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
в параметре по умолчанию и никогда не сможете.