以编程方式确定函数所需的参数量 - Python

时间:2009-04-12 15:43:35

标签: python parameters function

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

这个当前的设置工作得非常好,但我只是想知道自我改进的利益,如果有一种方法来确定一个函数中所需的参数数量,我的谷歌尝试返回到目前为止没有任何价值,但我看到如何由于他们允许的论据数量无限,args和kwargs可以搞砸这样的命令。

6 个答案:

答案 0 :(得分:40)

inspect.getargspec()

  

获取函数参数的名称和默认值。返回四个元组的元组:(args,varargs,varkw,defaults)。 args是参数名称的列表(它可能包含嵌套列表)。 varargs和varkw是*和**参数的名称或None。 defaults是默认参数值的元组,如果没有默认参数,则为None;如果这个元组有n个元素,它们对应于args中列出的最后n个元素。

答案 1 :(得分:15)

你想要的通常是不可能的,因为使用了varargs和kwargs,但inspect.getargspec(Python 2.x)和inspect.getfullargspec(Python 3.x)接近。

  • Python 2.x:

    >>> 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:

    >>> 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
    

答案 2 :(得分:4)

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

(因为someMethod.func_code.co_argcount不再有效)

答案 3 :(得分:2)

这已经得到解答,但如果没有检查模块,您也可以使用someMethod.func_code.co_argcount

答案 4 :(得分:1)

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

使用工厂类注册每个子类。 此工厂类获取参数列表,通过实例化相应的命令子类来决定执行哪个命令。

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

这样,您永远不需要重复编码相同的东西,并且实际上不需要模拟switch语句。它还可以非常轻松地扩展和添加命令,因为您可以简单地添加和注册新类。没有什么可以改变的。

答案 5 :(得分:0)

很好的问题。我只是遇到了一个问题,我想编写一个带回调参数的函数。根据该回调的参数数量,需要以不同方式调用它。

我从gimel的回答开始,然后扩展为能够处理与inspect模块(raise TypeError)反应不佳的内置函数。

所以这里是检查函数是否只需要一个参数的代码:

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')

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

typical_argument参数是一个kludge:如果inspect无效,例如在上述内置函数中,我们只是尝试用一个参数调用函数,看看会发生什么。

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

这不太好。但它可能会帮助人们有同样的问题,并且还会遇到inspect无法检查C编码函数实现的事实。也许人们有更好的建议?