Нестандартные необязательные аргументы по умолчанию - PullRequest
4 голосов
/ 13 июля 2009

У меня есть две функции:

def f(a,b,c=g(b)):
    blabla

def g(n):
    blabla

c - необязательный аргумент в функции f. Если пользователь не указывает его значение, программа должна вычислить g (b), и это будет значение c. Но код не компилируется - он говорит, что имя 'b' не определено. Как это исправить?

Кто-то предложил:

def g(b):
    blabla

def f(a,b,c=None):
    if c is None:
        c = g(b)
    blabla

Но это не работает. Возможно, пользователь предполагал, что c будет None, и тогда c будет иметь другое значение.

Ответы [ 5 ]

26 голосов
/ 13 июля 2009
def f(a,b,c=None):
    if c is None:
        c = g(b)

Если c может быть допустимым значением для *1003*, то вы делаете это:

sentinel = object()
def f(a,b,c=sentinel):
    if c is sentinel:
        c = g(b)
2 голосов
/ 13 июля 2009

Вы не можете сделать это таким образом.

Внутри функции проверьте, указан ли c. Если нет, сделайте расчет.

def f(a,b,c=None):
    if c == None:
        c = g(b)
    blabla
2 голосов
/ 13 июля 2009

значение c будет оценено (g(b)) во время компиляции. Вам нужно g, определенное до f. И, конечно же, вам нужно определить глобальную переменную b на этом этапе.

b = 4

def g(a):
    return a+1

def test(a, c=g(b)):
    print(c)

test(b)

отпечатков 5.

1 голос
/ 24 мая 2010

проблема с

sentinel = object()
def f(a, b, c=sentinel):
  if c is sentinel:
    c = g(b)

означает, что sentinel является глобальным / общедоступным, если этот код не является частью функции / метода. Так что кто-то еще может позвонить f(23, 42, sentinel). Однако, если f является глобальным / общедоступным, вы можете использовать закрытие, чтобы сделать sentinel локальным / частным, чтобы вызывающий не мог его использовать:

def f():
  sentinel = object()
  def tmp(a, b, c=sentinel):
    if c is sentinel:
      c = g(b)
  return tmp
f = f()

Если вы обеспокоены тем, что статические анализаторы кода могут получить неверное представление о f, вы можете использовать те же параметры для фабрики:

def f(a, b, c=object()): #@UnusedVariable
  sentinel = object()
  def tmp(a, b, c=sentinel):
    if c is sentinel:
      c = g(b)
  return tmp
f = f(23, 42)
0 голосов
/ 13 июля 2009
def f(a,b,*args):
    if len(args) == 1:
        c = args[0]
    elif len(args) == 0:
        c = g(b)
    else:
        raise Exception('Function takes 2 or 3 parameters only.')
    blabla

def g(n):
    blabla

Возможно, вы можете структурировать это лучше, но это основная идея. В качестве альтернативы вы можете использовать **kwargs и использовать такую ​​функцию, как f(a,b,c=Something), вам просто нужно изменить f соответственно.

Документация

...