关于以编程方式确定函数所需的参数量:以编程方式确定函数所需的参数量 – Python

Programmatically determining amount of parameters a function requires - Python

本问题已经有最佳答案,请猛点这里访问。

我正在创建一个简单的命令行实用程序,并使用字典作为一种case语句,关键字链接到它们的相应函数。这些函数都有不同数量的参数,因此当前需要检查用户是否输入了每个函数所需的正确数量的参数。我将所需数量放入字典大小写语句中,格式为{Keyword:(FunctionName, AmountofArguments)}

这个当前的设置工作得非常好,但是我只是想知道是否有一种方法可以确定函数中所需的参数个数,我的google尝试到目前为止没有返回任何值,但是我看到args和kwargs是如何通过无限的参数来破坏这样的命令的。允许。


检查.getargspec():

Get the names and default values of a function’s arguments. A tuple of four things is returned: (args, varargs, varkw, defaults). args is a list of the argument names (it may contain nested lists). varargs and varkw are the names of the * and ** arguments or None. defaults is a tuple of default argument values or None if there are no default arguments; if this tuple has n elements, they correspond to the last n elements listed in args.


一般来说,由于使用varargs和kwargs,您想要的是不可能的,但是EDOCX1(python 2.x)和EDOCX1(python 3.x)接近了。

  • python 2.x版本:

    1
    2
    3
    4
    5
    6
    7
    8
    >>> import inspect
    >>> def add(a, b=0):
    ...     return a + b
    ...
    >>> inspect.getargspec(add)
    (['a', 'b'], None, None, (0,))
    >>> len(inspect.getargspec(add)[0])
    2
  • python 3.x版本:

    1
    2
    3
    4
    5
    6
    7
    8
    >>> import inspect
    >>> def add(a, b=0):
    ...     return a + b
    ...
    >>> inspect.getfullargspec(add)
    FullArgSpec(args=['a', 'b'], varargs=None, varkw=None, defaults=(0,), kwonlyargs=[], kwonlydefaults=None, annotations={})
    >>> len(inspect.getfullargspec(add).args)
    2


在python 3中,使用someMethod.__code__.co_argcount

(因为someMethod.func_code.co_argcount不再工作)


已经回答了这个问题,但如果没有检查模块,您也可以使用someMethod.func_code.co_argcount


使每个命令都成为一个类,从定义命令的一般结构的抽象基派生而来。尽可能将命令属性的定义放入类变量中,方法在处理该数据的基类中定义。

用工厂类注册每个子类。这个工厂类通过实例化适当的命令子类来获取参数列表,并决定要执行哪个命令。

参数检查由命令子类本身处理,使用正确定义的常规方法构成命令基类。

这样,您就不需要重复地编写相同的代码,也不需要模拟switch语句。它还使得扩展和添加命令变得非常容易,因为您可以简单地添加和注册一个新类。没有其他可以改变的。


好问题。我刚遇到一个问题,我想写一个接受回调参数的函数。根据该回调的参数数量,需要以不同的方式调用它。

我从Gimel的回答开始,然后扩展到能够处理与inspect模块(raise TypeError反应不好的内置设备。

下面是检查函数是否只需要一个参数的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
def func_has_one_arg_only(func, typical_argument=None, ignore_varargs=False):
   """True if given func expects only one argument

    Example (testbench):
    assert not func_has_one_arg_only(dict.__getitem__), 'builtin 2 args'
    assert func_has_one_arg_only(lambda k: k), 'lambda 1 arg'
    assert not func_has_one_arg_only(lambda k,x: k), 'lambda 2 args'
    assert not func_has_one_arg_only(lambda *a: k), 'lambda *a'
    assert not func_has_one_arg_only(lambda **a: k), 'lambda **a'
    assert not func_has_one_arg_only(lambda k,**a: k), 'lambda k,**a'
    assert not func_has_one_arg_only(lambda k,*a: k), 'lambda k,*a'

    assert func_has_one_arg_only(lambda k: k, ignore_varargs=True), 'lambda 1 arg'
    assert not func_has_one_arg_only(lambda k,x: k, ignore_varargs=True), 'lambda 2 args'
    assert not func_has_one_arg_only(lambda *a: k, ignore_varargs=True), 'lambda *a'
    assert not func_has_one_arg_only(lambda **a: k, ignore_varargs=True), 'lambda **a'
    assert func_has_one_arg_only(lambda k,**a: k, ignore_varargs=True), 'lambda k,**a'
    assert func_has_one_arg_only(lambda k,*a: k, ignore_varargs=True), 'lambda k,*a'
   """


    try:
        import inspect
        argspec = inspect.getargspec(func)
    except TypeError:                   # built-in c-code (e.g. dict.__getitem__)
        try:
            func(typical_argument)
        except TypeError:
            return False
        else:
            return True
    else:
        if not ignore_varargs:
            if argspec.varargs or argspec.keywords:
                return False
        if 1 == len(argspec.args):
            return True
        return False
    raise RuntimeError('This line should not be reached')

您可以使用ignore_varargs参数控制与varargs参数*args**kwargs相关的行为。

typical_argument参数是一个组合:如果inspect不能工作,例如在前面提到的内置函数上,那么我们只需要用一个参数调用函数,看看会发生什么。

这种方法的问题在于,raise TypeError有多种原因:要么使用了错误数量的参数,要么使用了错误类型的参数。通过允许用户提供typical_argument,我试图绕过这个问题。

这不太好。但这可能有助于有相同问题的人,同时也会遇到这样一个事实:inspect无法检查C代码函数实现。也许大家有更好的建议?