当参数在 Python 中指定为 None 时,让函数使用其参数默认值的好方法是什么?
What is a good way to get a function to use its default value for an argument when the argument is specified as None in Python?
假设我有一个函数(称为 function
),它接受一个默认值为 True
的布尔参数,例如 def function(argument1 = True)
.
现在假设我想使用此函数,使用另一个函数 (resolveArg
) 的输出指定其参数,该函数检查现有基础结构中的参数。这种 resolveArg
方法被普遍使用,如果它可以找到指定给定函数的参数值(例如 function
),则将函数参数设置为它,否则将参数设置为 None
.
如果另一个函数 (resolveArg
) 将其参数设置为 None
,我如何让 function
使用其参数的默认值?
def resolveArg(argName = None):
if argName in self.conf._argdict:
return(self.conf._argdict[argName].value)
else:
return(None)
def function(argument1 = True)
if argument1 is True:
return(True)
elif argument1 is False:
return(False)
else:
raise(Exception)
function(argument1 = resolveArg("red"))
如果参数是 True
或 None
.
,一种方法是为您的function
提供相同的行为
def function(arg=True):
if arg in [True, None]:
do_stuff()
else:
do_something_else()
我以前没见过这种问题,所以可能有办法改进你的逻辑并省略这个功能。
不过,有一种方法可以使用模块 "inspect" 对 Python 中的代码进行内省。
示例用法是:
>>> def a(q=5):
... if q is None:
... return dict(inspect.getmembers(a))['func_defaults'][0]
... return q
...
>>> a()
5
>>> a(None)
5
这个问题是 "func_defaults" returns 一个列表,如果你有多个参数函数,它是不方便的,并且作为一个整体会使过程容易出错。
警告
您要求 "good way to get a function to use its default value for an argument when the argument is specified as None in Python?"
我认为没有 好的 方法,因为这不是一件好事。这是一件有风险的事情 - 它可以掩盖令人讨厌的错误情况,在这种情况下您可能有理由希望检测到 None
被传递到您期望值的地方这一事实。在广泛使用此技术的地方进行调试可能会很糟糕。 谨慎使用。
可能的方法
我猜您想要一个通用的解决方案,它比您提供的示例具有更多的功能。在示例中 - 您最简单的方法是在参数值中测试 None
并在必要时替换它。
您可以编写一个装饰器来处理一般情况,它将使用检查工具箱计算具有默认值的参数列表中的参数值,如果它们是 None
则替换它们。
下面的代码通过一些简单的测试用例演示了这个想法 - 这将起作用,但仅适用于当前构造的具有简单参数(不是 *args, **kwargs
)的函数。它可以得到加强以涵盖这些情况。它像往常一样安全地处理没有默认值的参数。
import inspect
def none2defaultdecorator(thisfunc):
(specargs, _, _, defaults) = inspect.getargspec(thisfunc)
def wrappedfunc(*instargs):
callargs = inspect.getcallargs(thisfunc, *instargs)
if len(specargs) != len(callargs):
print "Strange - different argument count in this call to those in spec"
print specargs
print callargs
for i,argname in enumerate(specargs[-len(defaults):]):
try:
if callargs[argname] == None:
callargs[argname] = defaults[i]
except KeyError:
# no local value for this argument - it will get the default anyway
pass
return thisfunc(**callargs)
return wrappedfunc
#Decorate the funtion with the "None replacer". Comment this out to see difference
@none2defaultdecorator
def test(binarg = True, myint = 5):
if binarg == True:
print "Got binarg == true"
elif binarg == False:
print "Got binarg == false"
else:
print "Didn't understand this argument - binarg == ", binarg
print "Argument values - binarg:",binarg,"; myint:",myint
test()
test(False)
test(True)
test(None)
test(None, None)
您可能想按以下方式稍微修改 function
的实现:
def function(argument1 = None)
if argument1 is None:
argument1 = True
return argument1
如果你想了解更多关于默认函数参数None,你可能想参考我的另一个SO answer
假设我有一个函数(称为 function
),它接受一个默认值为 True
的布尔参数,例如 def function(argument1 = True)
.
现在假设我想使用此函数,使用另一个函数 (resolveArg
) 的输出指定其参数,该函数检查现有基础结构中的参数。这种 resolveArg
方法被普遍使用,如果它可以找到指定给定函数的参数值(例如 function
),则将函数参数设置为它,否则将参数设置为 None
.
如果另一个函数 (resolveArg
) 将其参数设置为 None
,我如何让 function
使用其参数的默认值?
def resolveArg(argName = None):
if argName in self.conf._argdict:
return(self.conf._argdict[argName].value)
else:
return(None)
def function(argument1 = True)
if argument1 is True:
return(True)
elif argument1 is False:
return(False)
else:
raise(Exception)
function(argument1 = resolveArg("red"))
如果参数是 True
或 None
.
function
提供相同的行为
def function(arg=True):
if arg in [True, None]:
do_stuff()
else:
do_something_else()
我以前没见过这种问题,所以可能有办法改进你的逻辑并省略这个功能。
不过,有一种方法可以使用模块 "inspect" 对 Python 中的代码进行内省。
示例用法是:
>>> def a(q=5):
... if q is None:
... return dict(inspect.getmembers(a))['func_defaults'][0]
... return q
...
>>> a()
5
>>> a(None)
5
这个问题是 "func_defaults" returns 一个列表,如果你有多个参数函数,它是不方便的,并且作为一个整体会使过程容易出错。
警告
您要求 "good way to get a function to use its default value for an argument when the argument is specified as None in Python?"
我认为没有 好的 方法,因为这不是一件好事。这是一件有风险的事情 - 它可以掩盖令人讨厌的错误情况,在这种情况下您可能有理由希望检测到 None
被传递到您期望值的地方这一事实。在广泛使用此技术的地方进行调试可能会很糟糕。 谨慎使用。
可能的方法
我猜您想要一个通用的解决方案,它比您提供的示例具有更多的功能。在示例中 - 您最简单的方法是在参数值中测试 None
并在必要时替换它。
您可以编写一个装饰器来处理一般情况,它将使用检查工具箱计算具有默认值的参数列表中的参数值,如果它们是 None
则替换它们。
下面的代码通过一些简单的测试用例演示了这个想法 - 这将起作用,但仅适用于当前构造的具有简单参数(不是 *args, **kwargs
)的函数。它可以得到加强以涵盖这些情况。它像往常一样安全地处理没有默认值的参数。
import inspect
def none2defaultdecorator(thisfunc):
(specargs, _, _, defaults) = inspect.getargspec(thisfunc)
def wrappedfunc(*instargs):
callargs = inspect.getcallargs(thisfunc, *instargs)
if len(specargs) != len(callargs):
print "Strange - different argument count in this call to those in spec"
print specargs
print callargs
for i,argname in enumerate(specargs[-len(defaults):]):
try:
if callargs[argname] == None:
callargs[argname] = defaults[i]
except KeyError:
# no local value for this argument - it will get the default anyway
pass
return thisfunc(**callargs)
return wrappedfunc
#Decorate the funtion with the "None replacer". Comment this out to see difference
@none2defaultdecorator
def test(binarg = True, myint = 5):
if binarg == True:
print "Got binarg == true"
elif binarg == False:
print "Got binarg == false"
else:
print "Didn't understand this argument - binarg == ", binarg
print "Argument values - binarg:",binarg,"; myint:",myint
test()
test(False)
test(True)
test(None)
test(None, None)
您可能想按以下方式稍微修改 function
的实现:
def function(argument1 = None)
if argument1 is None:
argument1 = True
return argument1
如果你想了解更多关于默认函数参数None,你可能想参考我的另一个SO answer