代码之家  ›  专栏  ›  技术社区  ›  tomeedee

以编程方式确定函数所需的参数量-python[duplicate]

  •  31
  • tomeedee  · 技术社区  · 17 年前

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

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

    6 回复  |  直到 9 年前
        1
  •  40
  •   gimel    17 年前

    inspect.getargspec() :

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

        2
  •  15
  •   Stephan202 Alex Martelli    9 年前

    你想要的通常是不可能的,因为使用了varargs和kwargs,但是 inspect.getargspec (python 2.x)和 inspect.getfullargspec (蟒蛇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
      
        3
  •  3
  •   Jean-François Fabre    9 年前

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

    (自 someMethod.func_code.co_argcount 不再工作)

        4
  •  2
  •   Josep Valls    9 年前

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

        5
  •  1
  •   Ber    17 年前

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

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

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

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

        6
  •  0
  •   cfi    13 年前

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

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

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

    这个 typical_argument 参数是一个组合:如果 检查 无法工作,例如在前面提到的内置函数上,然后我们只尝试用一个参数调用函数,然后看看会发生什么。

    这种方法的问题在于 提高类型错误 :使用的参数数目错误,或者使用的参数类型错误。通过允许用户提供 典型的论点 我想回避这个问题。

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