我如何才能找到一个Python函数的参数的数量?我需要知道它有多少普通参数和多少命名参数。

例子:

def someMethod(self, arg1, kwarg1=None):
    pass

这个方法有2个参数和1个命名参数。


当前回答

你可以通过(将"function"替换为你的函数名)获得参数的数量:

function.__code__.co_argcount ## 2

参数的名称为:

function.__code__.co_varnames ## ('a', 'b')

其他回答

对于那些想要在Python 2和Python 3.6+之间以可移植的方式做到这一点的人来说,有一个好消息:使用inspect.getfullargspec()方法。它在Python 2中都可以工作。X和3.6+

正如吉姆·法萨拉基斯·希利亚德(Jim Fasarakis Hilliard)等人指出的,过去是这样的: 1. 在Python 2中。X:使用inspect.getargspec() 2. 在Python 3中。X:使用签名,因为getargespec()和getfulllargspec()已弃用。

然而,从Python 3.6开始(根据流行需求?),事情已经朝着更好的方向变化:

从Python 3文档页:

inspect.getfullargspec(函数) 在3.6版更改:此方法以前在Python 3.5中被记录为不赞成signature(),但为了恢复从遗留的getargspec() API迁移的单源Python 2/3代码明确支持的标准接口,该决定已被撤销。

正如其他答案所暗示的那样,只要查询的东西实际上是一个函数,getargespec就能很好地工作。它不适用于内置函数,如open, len等,并会在这些情况下抛出异常:

TypeError: <built-in function open> is not a Python function

下面的函数(受到这个答案的启发)演示了一种变通方法。它返回f期望的参数数:

from inspect import isfunction, getargspec
def num_args(f):
  if isfunction(f):
    return len(getargspec(f).args)
  else:
    spec = f.__doc__.split('\n')[0]
    args = spec[spec.find('(')+1:spec.find(')')]
    return args.count(',')+1 if args else 0

其思想是从__doc__字符串中解析出函数规范。显然,这依赖于所述字符串的格式,因此几乎不是健壮的!

假设您可能正在处理基于类的方法或简单的函数,您可以像下面这样做。

如果输入是类方法(因此包括self),这将自动减去一个输入。

import types
def get_arg_count(fn):
    extra_method_input_count=1 if isinstance(fn, types.MethodType) else 0
    return fn.__code__.co_argcount-extra_method_input_count

然后你可以根据需要应用到函数或方法:

def fn1(a, b, c):
    return None

class cl1:
    def fn2(self, a, b, c):
        return None

print(get_arg_count(fn1)) #=> 3
print(get_arg_count(cl1().fn2)) #=> 3

你可以通过(将"function"替换为你的函数名)获得参数的数量:

function.__code__.co_argcount ## 2

参数的名称为:

function.__code__.co_varnames ## ('a', 'b')

之前接受的答案从Python 3.0开始已弃用。而不是使用inspect。gettarget spec您现在应该选择取代它的Signature类。

通过Signature函数为函数创建一个签名很容易:

from inspect import signature

def someMethod(self, arg1, kwarg1=None):
    pass

sig = signature(someMethod)

现在,你可以通过字符串快速查看它的参数:

str(sig)  # returns: '(self, arg1, kwarg1=None)'

或者你也可以通过sig.parameters获取属性名到参数对象的映射。

params = sig.parameters 
print(params['kwarg1']) # prints: kwarg1=20

此外,你可以在sig.parameters上调用len来查看这个函数需要的参数数量:

print(len(params))  # 3

params映射中的每个条目实际上都是一个Parameter对象,它具有进一步的属性,使您的工作更加轻松。例如,抓取一个参数并查看它的默认值现在很容易执行:

kwarg1 = params['kwarg1']
kwarg1.default # returns: None

参数中包含的其他对象也是如此。


至于Python 2。X用户,同时检查。Getargspec没有被弃用,该语言将很快被:-)。Signature类在2中不可用。X系列,不会。所以你仍然需要使用inspect.getargspec。

至于在Python 2和3之间的转换,如果你的代码依赖于Python 2中的getargspec接口,而在3中切换到signature太困难了,你可以使用inspect.getfullargspec这个有价值的选项。它提供了一个类似于getargspec(单个可调用参数)的接口,以便获取函数的参数,同时还处理一些getargspec无法处理的附加情况:

from inspect import getfullargspec

def someMethod(self, arg1, kwarg1=None):
    pass

args = getfullargspec(someMethod)

与getargespec一样,getfullargspec返回一个包含参数的NamedTuple。

print(args)
FullArgSpec(args=['self', 'arg1', 'kwarg1'], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={})