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

例子:

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

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


当前回答

正如其他答案所暗示的那样,只要查询的东西实际上是一个函数,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__字符串中解析出函数规范。显然,这依赖于所述字符串的格式,因此几乎不是健壮的!

其他回答

Dimitris Fasarakis Hilliard的公认答案建议以字符串格式获取参数,但我认为在解析这个字符串时可能会犯错误,因此我直接使用inspect模块创建了一个参数列表

import inspect
def my_function(a,b,c):
    #some code
    pass

result=list(inspect.signature(my_function).parameters.keys())
print(result)
['a','b','c']

In:

import inspect 

class X:
    def xyz(self, a, b, c): 
        return 

print(len(inspect.getfullargspec(X.xyz).args))

Out:

4


注意:如果xyz不在类X中,并且没有“self”,只有“a, b, c”,那么它将打印3。

对于3.5以下的python,您可能需要替换inspect。通过检查获得全部规格。在上面的代码中获取目标规格。

之前接受的答案从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={})

这是获取函数的强制参数数量的解决方案(*)

如果使用了一些不常见的参数规范(具有默认值的仅限位置参数,没有默认值的仅限关键字参数,等等),那么本文提出的许多解决方案都无法实现这一目的。

from typing import Callable, Any
import inspect

def get_mandatory_argcount(f: Callable[..., Any]) -> int:
    """Get the number of mandatory arguments of a function."""
    sig = inspect.signature(f)
    
    def parameter_is_mandatory(p: inspect.Parameter) -> bool:
        return p.default is inspect.Parameter.empty and p.kind not in (
            inspect.Parameter.VAR_POSITIONAL,
            inspect.Parameter.VAR_KEYWORD,
        )
    
    return sum(parameter_is_mandatory(p) for p in sig.parameters.values())

# mandatory keyword-only
def f1(b=2, *args, c, d=1, **kwds): pass
print(get_mandatory_argcount(f1))

# positional only with default
def f2(a=1, /, b=3, *args, **kwargs): pass
print(get_mandatory_argcount(f2))

(*)我想把这个作为一个答案,以编程方式确定一个函数所需的参数数量- Python代替,但由于某种原因,这个问题被标记为重复的这个问题,尽管它专门询问所需参数的数量,而这个问题只询问参数的一般数量。

除此之外,我还看到help()函数在大多数情况下确实有帮助

例如,它给出了它所接受的参数的所有细节。

help(<method>)

给出以下内容

method(self, **kwargs) method of apiclient.discovery.Resource instance
Retrieves a report which is a collection of properties / statistics for a specific customer.

Args:
  date: string, Represents the date in yyyy-mm-dd format for which the data is to be fetched. (required)
  pageToken: string, Token to specify next page.
  parameters: string, Represents the application name, parameter name pairs to fetch in csv as app_name1:param_name1, app_name2:param_name2.

Returns:
  An object of the form:

    { # JSON template for a collection of usage reports.
    "nextPageToken": "A String", # Token for retrieving the next page
    "kind": "admin#reports#usageReports", # Th