Нестандартные необязательные аргументы по умолчанию
У меня есть две функции:
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 ответов
def f(a,b,c=None):
if c is None:
c = g(b)
Если None
может быть допустимым значением для c
тогда вы делаете это:
sentinel = object()
def f(a,b,c=sentinel):
if c is sentinel:
c = g(b)
Вы не можете сделать это таким образом.
Внутри функции проверьте, указан ли c. Если нет, сделайте расчет.
def f(a,b,c=None):
if c == None:
c = g(b)
blabla
Ценность 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.
Проблема с
sentinel = object()
def f(a, b, c=sentinel):
if c is sentinel:
c = g(b)
в том, что sentinel
является глобальным / общедоступным, если этот код не является частью функции / метода. Так что кто-то еще может позвонить f(23, 42, sentinel)
, Однако если f
является глобальным / публичным, вы можете использовать закрытие, чтобы сделать sentinel
local / private, чтобы вызывающая сторона не могла его использовать:
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)
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
соответственно.