我试图了解以下有关处理函数及其参数的信息:
def print_my_arg(func, *args, **kwargs):
func(*args, **kwargs)
if 'my_arg' in kwargs:
print(' my_arg = {}'.format(kwargs['my_arg']))
def foo(call_no, my_arg='Default Value'):
print('call_no = {}'.format(call_no) )
print_my_arg(foo, 0, my_arg='My Value 1')
print_my_arg(foo, 1, 'My Value 2')
print_my_arg(foo, 2)
输出:
call_no = 0
my_arg = My Value 1
call_no = 1 # I'd like to see 'My Value 2' here
call_no = 2 # I'd like to see 'Default Value' here
显然,人们可以按照上面显示的任何一种方式自由调用函数,这使我感到奇怪:为什么my_arg
仍然不去kwargs
?是否没有统一的方法来按名称(而不是按位置)访问参数,而这并不取决于调用函数的方式?
请注意:
我对此不感兴趣print_my_args(func, call_no, my_arg)
,因为我正在谈论的情况是我func
事先不知道的签名,但是我想知道是否存在一个特定的参数(按名称)。
显然,这与装饰器有关,但是我以更简单的方式编写了示例(或者我希望如此)。
编辑
非常感谢您提供有关inspect.signature的答案。使用它,我的新版本print_my_arg()
是:
from inspect import signature
def print_my_arg ( func, *args, **kwargs ):
func ( *args, **kwargs )
sig = signature ( func )
if 'my_arg' not in sig.parameters: return
binding = sig.bind ( *args, **kwargs )
binding.apply_defaults ()
print ( " my_arg = {}".format ( binding.arguments [ 'my_arg' ] ) )
是否没有统一的方法来按名称(而不是按位置)访问参数,而这并不取决于调用函数的方式?
是的,请inspect
通过以下命令signature
:
>>> import inspect
>>> sig = inspect.signature(foo)
>>> print(sig)
(call_no, my_arg='Default Value')
>>> args = sig.bind(1, "my_value")
>>> args.arguments["my_arg"]
'my_value'
请注意,尝试将签名绑定到无效调用将引发类似/相同的TypeError,与使用无效参数调用函数时会引发类似的TypeError。args.arguments
除非您调用,否则使用默认值的参数也不会出现args.apply_defaults()
另请注意,仅关键字参数将在args.kwargs
字典中而不是args.arguments
:
import inspect
def bar(a,*, b=None):
pass
sig = inspect.signature(bar)
binding = sig.bind(1, b=5)
assert "a" in binding.arguments
assert "b" in binding.kwargs
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句