如何找到Python函数的参数数量?


163

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

例:

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

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


43
这个问题是完全有道理的;如果不是这样(因为您总是可以阅读源代码),那么inspect标准库模块就没有任何理由。
流程

许多语言至少实现了一种不合理的功能。该inspect模块还具有许多其他功能,因此,如果其中的一个特定功能是合理的,则不可以说整个模块是不合理的。此外,很容易看出该功能的使用方式不佳。(请参阅stackoverflow.com/questions/741950)。就是说,这是一个有用的功能,特别是对于编写装饰器和对功能进行操作的其他功能。
user1612868 2014年

Answers:


130

于接受的答案已于弃用Python 3.0inspect.getargspec现在,您应该选择Signature取代它的类,而不是使用它。

创建功能的签名是通过简单的signature功能

from inspect import signature

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

sig = signature(someMethod)

现在,您可以通过以下方式快速查看其参数str

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

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

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

此外,你可以叫lensig.parameters也看到的参数此功能,需要数量:

print(len(params))  # 3

params映射中的每个条目实际上都是一个具有更多属性的Parameter对象,使您的生活更加轻松。例如,现在可以轻松地执行以下操作来获取参数并查看其默认值:

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

包含在中的其余对象也类似parameters


对于Python 2.x用户,虽然inspect.getargspec 不建议弃用,但该语言很快就会成为:-)。该Signature课程在该2.x系列中不可用,也不会提供。因此,您仍然需要使用inspect.getargspec

至于Python 2和3之间的转换,如果你有一些代码依赖的接口getargspec在Python 2切换到signature3是太难了,你必须将有价值的选择使用inspect.getfullargspec。它提供了与getargspec(单个可调用参数)相似的接口,以获取函数的参数,同时还处理某些其他情况,这些getargspec情况不是:

from inspect import getfullargspec

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

args = getfullargspec(someMethod)

与一样getargspecgetfullargspec返回NamedTuple包含参数的。

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

1
不客气,@GeorgSchölly。令我感到惊讶的是,像这样一个受欢迎的问题提供的解决方案已被弃用或偷偷摸摸(偷看co_argcount属性。)
Dimitris Fasarakis Hilliard

1
getfullargspec未在Python 2.x中实现,您需要使用getargspec
Peter Gibson

getargspec不工作的内置功能:getargspec(open)TypeError: <built-in function open> is not a Python function这个答案的一些想法...
starfry

在您的最后一个示例中,当您print(args)不了解时,defaults=(None,)您会得到defaults=None
Seanny123 '18

有没有一种方法可以获取装饰后装饰的功能的原始参数计数。
Gulats

117
import inspect
inspect.getargspec(someMethod)

参见检查模块


5
通常是您想要的,但这不适用于内置功能。知道如何获取内置信息的唯一方法是解析其doc字符串,这很麻烦但可行。
塞林2010年


有没有在Python 3中不推荐使用的解决方案?
hlin117 '16

1
如果你跟随链接,你会看到,它建议使用inspect.signature- docs.python.org/3/library/inspect.html#inspect.signature
coderforlife

我在这里不解析文档字符串的情况下发布了内置函数的另一种可能方法:stackoverflow.com/questions/48567935/…–
HelloWorld

31
someMethod.func_code.co_argcount

或者,如果当前函数名称不确定,请执行以下操作:

import sys

sys._getframe().func_code.co_argcount

4
@elyase,只需执行:dir(someMethod)-> 'func_code'; 进一步:dir(someMethod.func_code)-> 'co_argcount'; 您可以使用内置dir()方法来确定对象的可用方法。

@elyase我也很好奇,所以我找到了这个docs.python.org/2/library/inspect.html#types-and-members
rodripf 2015年

支持Python 3:six.get_function_code(someMethod).co_argcount
noisecapella

8
@noisecapella,只要您可以做,就不需要第三方模块some_method.__code__.co_argcount
vallentin

1
通常,您应该在函数对象内部偷看这些内容。co_argcount在评估代码对象期间在内部使用。我要说的是,实际上并不能保证这些属性不会从一个发行版更改为另一个发行版。
Dimitris Fasarakis Hilliard

16

inspect.getargspec()

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

在2.6版中进行了更改:返回一个命名的元组ArgSpec(args,varargs,关键字,默认值)。

请参阅您可以列出关键字参数的python函数接收


5

除此之外,我还看到大多数时候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

人们最好对发布的问题发表评论,而不是仅单击减号按钮。
Venu Murthy

2
help函数仅显示文档字符串所说的内容。您甚至测试过它是否与问题中的函数定义兼容?
0xc0de 2014年

@ 0xc0de-您测试过了吗?因为它确实有效。help()吐出的不仅仅是文档字符串-即使在未记录的代码上,它仍然会打印出argspec并告诉您代码的定义位置。发布原始问题的人不清楚他们是否需要机器或人类友好的答案。如果只需要对人类友好,那就help()足够了。
ArtOfWarfare

@ArtOfWarfare根本没有,因为现在您必须解析任何help()返回值,然后尝试找到argskwargs
瓦伦丁

5

对于想要以可移植的方式在Python 2和Python 3.6+之间进行此操作的人们来说是个好消息:use inspect.getfullargspec()方法。它可以在Python 2.x和3.6+中使用

正如Jim Fasarakis Hilliard和其他人指出的那样,它以前是这样的:
1.在Python 2.x中:使用inspect.getargspec()
2.在Python 3.x中:使用签名,因为getargspec()getfullargspec()已弃用。

但是,从Python 3.6开始(受大众欢迎?),情况已经朝着更好的方向发展:

从Python 3 文档页面

inspect.getfullargspec(func)

在版本3.6中进行了更改:以前signature()在Python 3.5中记录了此方法的不推荐使用,但是为了恢复从原始getargspec()API 迁移来的单一源Python 2/3代码的明确支持的标准接口,该决定已被撤销。


3

inspect.getargspec()满足您的需求

from inspect import getargspec

def func(a, b):
    pass
print len(getargspec(func).args)

1
欢迎使用Stack Overflow!请不要只回答源代码。尝试提供有关您的解决方案如何工作的很好的描述。请参阅:我如何写一个好的答案?。谢谢
sɐunıɔןɐqɐp

2

正如其他答案所暗示的,getargspec只要被查询的东西实际上是一个功能,它就可以很好地工作。它不适用于,等内置函数openlen在以下情况下将引发异常:

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

以下功能(受此答案启发)展示了一种解决方法。它返回预期的args数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__字符串中解析出函数规范。显然,这依赖于所述字符串的格式,因此很难实现!


2

func.__code__.co_argcount给您任何数量的参数 之前 *args

func.__kwdefaults__给您关键字参数 之后的字典 *args

func.__code__.co_kwonlyargcount 等于 len(func.__kwdefaults__)

func.__defaults__为您提供出现在前面可选参数的值 *args

这是简单的例子:

插图

>>> def a(b, c, d, e, f=1, g=3, h=None, *i, j=2, k=3, **L):
    pass

>>> a.__code__.co_argcount
7
>>> a.__defaults__
(1, 3, None)
>>> len(a.__defaults__)
3
>>> 
>>> 
>>> a.__kwdefaults__
{'j': 2, 'k': 3}
>>> len(a.__kwdefaults__)
2
>>> a.__code__.co_kwonlyargcount
2

0

在:

import inspect 

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

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

出:

4


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

对于3.5以下的python,您可能需要在上面的代码中替换inspect.getfullargspecinspect.getargspec

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.