我想知道是否可以在调用 Python 函数之前列出 Python 函数预期的变量,以便从包含大量变量的更大字典中传递预期变量。
我已经搜索了网络,但找不到任何东西。但是,python 解释器可以显示预期变量的列表,所以肯定有某种方法可以在脚本中做到这一点?
我想知道是否可以在调用 Python 函数之前列出 Python 函数预期的变量,以便从包含大量变量的更大字典中传递预期变量。
我已经搜索了网络,但找不到任何东西。但是,python 解释器可以显示预期变量的列表,所以肯定有某种方法可以在脚本中做到这一点?
您可以使用inspect.signature()
或inspect.getfullargspec()
函数:
import inspect
argspec = inspect.getfullargspec(somefunction)
signature = inspect.signature(somefunction)
inspect.fullargspec
返回一个包含 7 个元素的命名元组:
*args
参数的名称,如果已定义(None
否则)**kwargs
参数的名称,如果已定义(None
否则)有了inspect.signature()
一个Signature
object,一个丰富的对象,它不仅将上述数据建模为一组更结构化的对象,而且还允许您将值绑定到参数,就像调用函数一样。
哪个更好将取决于您的用例。
演示:
>>> import inspect
>>> def foo(bar, baz, spam='eggs', *monty, python: "kwonly", spanish=42, **inquisition) -> "return annotation":
... pass
...
>>> inspect.getfullargspec(foo)
FullArgSpec(args=['bar', 'baz', 'spam'], varargs='monty', varkw='inquisition', defaults=('eggs',), kwonlyargs=['python', 'spanish'], kwonlydefaults={'spanish': 42}, annotations={'return': 'return annotation', 'python': 'kwonly'})
>>> signature = inspect.signature(foo)
>>> signature
<Signature (bar, baz, spam='eggs', *monty, python: 'kwonly', spanish=42, **inquisition) -> 'return annotation'>
>>> signature.parameters['python'].kind.description
'keyword-only'
>>> signature.bind('Eric', 'Idle', 'John', python='Cleese')
<BoundArguments (bar='Eric', baz='Idle', spam='John', python='Cleese')>
如果您有一个以values
可能的参数值命名的字典,我将使用inspect.signature()
并使用Signature.parameters
映射来匹配名称:
posargs = [
values[param.name]
for param in signature.parameters.values()
if param.kind is Parameter.POSITIONAL_ONLY
]
skip_kinds = {Parameter.POSITIONAL_ONLY, Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD}
kwargs = {
param.name: values[param.name]
for param in signature.parameters.values()
if param.name in values and param.kind not in skip_kinds
}
上面为您提供了仅位置参数的值列表,以及其余参数的字典(任何*args
或**kwargs
参数除外)。
作为一个侧面答案,我现在使用另一种方法将它们期望的变量传递给函数:我将它们全部传递。
我的意思是我在我的根对象(它是所有其他对象的父对象)中维护一种全局/共享变量字典,例如:
shareddict = {'A': 0, 'B':'somestring'}
然后我只需将此 dict 传递给要调用的任何其他对象的任何方法,就像这样:
shareddict.update(call_to_func(**shareddict))
如您所见,我们将 shareddict 中的所有键/值解包为 call_to_func() 的关键字参数。我们还使用返回的结果更新 shareddict,我们将在下面看到原因。
现在有了这个技术,如果我需要这个字典中的一个或多个变量,我可以在我的函数/方法中简单而清晰地定义:
my_method1(A=None, *args, **kwargs):
''' This method only computes on A '''
new_A = Do_some_stuff(A)
return {'A': new_A} # Return the new A in a dictionary to update the shared value of A in the shareddict
my_method2(B=None, *args, **kwargs):
''' This method only computes on B '''
new_B = Do_some_stuff(B)
return {'B': new_B} # Return the new B in a dictionary to update the shareddict
my_method3(A=None, B=None, *args, **kwargs):
''' This method swaps A and B, and then create a new variable C '''
return {'A': B, 'B': A, 'C': 'a_new_variable'} # Here we will update both A and B and create the new variable C
如您所见,上述所有方法都返回一个变量字典,它将更新共享字典,并将其传递给其他函数。
这种技术有几个优点:
json.dumps(finaldict, sort_keys=True)
.好,易于:
import inspect #library to import
def foo(bar, baz, spam='eggs', *monty, **python): pass #example function
argspec = inspect.signature(foo)
print(argspec) #print your output
prints: (bar, baz, spam='eggs', *monty, **python)
它也适用于类内部的方法(非常有用!):
class Complex: #example Class
def __init__(self, realpart, imagpart): #method inside Class
... self.r = realpart
... self.i = imagpart
argspec = inspect.signature(Complex)
print(argspec)
打印:(真实部分,想象部分)