如何找到 Python 函数的参数数量?
Posted
技术标签:
【中文标题】如何找到 Python 函数的参数数量?【英文标题】:How can I find the number of arguments of a Python function? 【发布时间】:2010-10-25 06:41:21 【问题描述】:我需要知道它有多少普通参数以及有多少命名参数。
例子:
def someMethod(self, arg1, kwarg1=None):
pass
此方法有 2 个参数和 1 个命名参数。
【问题讨论】:
这个问题是完全有根据的;如果不是(因为您总是可以阅读源代码),那么inspect
标准库模块就没有任何理由。
很多语言都实现了至少一个不合理的特性。 inspect
模块还有很多其他功能,所以如果说整个模块中的一个特定功能是不合理的,这是不公平的。此外,很容易看出此功能如何使用不当。 (见***.com/questions/741950)。也就是说,它是一个有用的特性,尤其是对于编写装饰器和其他对函数进行操作的函数。
@flow 你所说的“完全保证”是什么意思?
***.com/questions/20981789/…
***.com/questions/47169033/…
【参考方案1】:
截至Python 3.0
,之前接受的答案是deprecated。您现在应该选择取代它的 Signature
类,而不是使用 inspect.getargspec
。
通过signature
function 为函数创建签名很容易:
from inspect import signature
def someMethod(self, arg1, kwarg1=None):
pass
sig = signature(someMethod)
现在,您可以通过str
ing 快速查看其参数:
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
object,它具有使您的生活更轻松的更多属性。例如,现在可以通过以下方式轻松获取参数并查看其默认值:
kwarg1 = params['kwarg1']
kwarg1.default # returns: None
parameters
中包含的其余对象也是如此。
对于 Python 2.x
用户,虽然 inspect.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)
与getargspec
一样,getfullargspec
返回一个包含参数的NamedTuple
。
print(args)
FullArgSpec(args=['self', 'arg1', 'kwarg1'], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations=)
【讨论】:
不客气@GeorgSchölly。我很惊讶像这样的一个流行问题提供的解决方案要么被弃用,要么被偷偷摸摸(偷看co_argcount
属性。)
getfullargspec
在Python 2.x中没有实现,需要使用getargspec
getargspec
不适用于内置函数:getargspec(open)
提供 TypeError: <built-in function open> is not a Python function
一些想法请参阅 this answer...
在上一个示例中,当您执行print(args)
时,您不会得到defaults=(None,)
,而是得到defaults=None
。
si 有一种方法可以获取装饰后装饰的函数的原始参数计数..?【参考方案2】:
import inspect
inspect.getargspec(someMethod)
见the inspect module
【讨论】:
通常是你想要的,但这不适用于内置函数。获取内置信息的唯一方法是解析它们的 doc 字符串,这很丑但可行。 这在 Python 3 中已被弃用:docs.python.org/3/library/inspect.html#inspect.getargspec 有没有在 Python 3 中不被弃用的解决方案? 如果您点击链接,您会看到它建议使用inspect.signature
- docs.python.org/3/library/inspect.html#inspect.signature
我在这里发布了另一种可能的内置函数方法,无需解析文档字符串:***.com/questions/48567935/…【参考方案3】:
someMethod.func_code.co_argcount
或者,如果当前函数名称未确定:
import sys
sys._getframe().func_code.co_argcount
【讨论】:
@elyase,就这样吧:dir(someMethod)
-> 'func_code'
;更进一步:dir(someMethod.func_code)
-> 'co_argcount'
;您可以使用内置的dir()
来确定对象的可用方法。
@elyase 我也很好奇,所以我找到了这个docs.python.org/2/library/inspect.html#types-and-members
支持 Python 3:six.get_function_code(someMethod).co_argcount
@noisecapella 不需要第三方模块,你可以简单地做some_method.__code__.co_argcount
一般来说,您不应该在函数对象内部偷看这些东西。 co_argcount
在评估代码对象期间在内部使用。我想说的是,确实不能保证这些属性不会从一个版本更改为另一个版本。【参考方案4】:
func.__code__.co_argcount
为您提供any 参数的数量 BEFORE *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
【讨论】:
感谢您的精彩说明!【参考方案5】:inspect.getargspec()
获取函数参数的名称和默认值。返回一个包含四件事的元组:(args、varargs、varkw、defaults)。 args 是参数名称的列表(它可能包含嵌套列表)。 varargs 和 varkw 是 * 和 ** 参数的名称或无。 defaults 是默认参数值的元组,如果没有默认参数,则为 None;如果这个元组有 n 个元素,它们对应于 args 中列出的最后 n 个元素。
在 2.6 版中更改:返回命名元组 ArgSpec(args, varargs, keywords, defaults)。
见can-you-list-the-keyword-arguments-a-python-function-receives。
【讨论】:
【参考方案6】:除此之外,我还看到大多数时候 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
【讨论】:
人们最好对帖子的问题发表评论,而不是只点击减号按钮。help
函数只显示文档字符串所说的内容。您是否测试过它是否适用于问题中的函数定义?
@0xc0de - 你测试过吗?因为它确实有效。 help()
吐出的不仅仅是文档字符串 - 即使在未记录的代码上,它仍然会打印出 argspec 并告诉您代码的定义位置。发布原始问题的人不清楚他们是否需要一个机器友好的答案或人类友好的答案。如果它只需要对人类友好,help()
就足够了。
@ArtOfWarfare 一点也不,因为现在你必须解析help()
返回的任何内容,并尝试找到args
和kwargs
。【参考方案7】:
对于想要在 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 中:使用签名,因为 getargspec()
和 getfullargspec()
已弃用。
然而,从 Python 3.6 开始(应大众需求?),事情已经变得更好了:
来自 Python 3 documentation page:
inspect.getfullargspec(func)
在 3.6 版中更改:此方法以前在 Python 3.5 中被记录为不推荐使用,而支持
signature()
,但为了恢复一个明确支持的标准接口,该决定已被撤销。源 Python 2/3 代码从旧版getargspec()
API 迁移出来。
【讨论】:
【参考方案8】:正如其他答案所暗示的,只要被查询的东西实际上是一个函数,getargspec
就可以很好地工作。它不适用于内置函数,例如open
、len
等,在这种情况下会抛出异常:
TypeError: <built-in function open> is not a Python function
以下函数(受this answer 启发)演示了一种解决方法。它返回 f
期望的 args 数量:
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__
字符串中解析出函数规范。显然,这依赖于所述字符串的格式,因此几乎没有鲁棒性!
【讨论】:
【参考方案9】:inspect.getargspec() 以满足您的需求
from inspect import getargspec
def func(a, b):
pass
print len(getargspec(func).args)
【讨论】:
欢迎来到 Stack Overflow!请不要只用源代码回答。尝试对您的解决方案如何工作提供一个很好的描述。请参阅:How do I write a good answer?。谢谢【参考方案10】:你得到参数的数量(用你的函数名替换“function”):
function.__code__.co_argcount ## 2
以及参数的名称:
function.__code__.co_varnames ## ('a', 'b')
【讨论】:
【参考方案11】:在:
import inspect
class X:
def xyz(self, a, b, c):
return
print(len(inspect.getfullargspec(X.xyz).args))
输出:
4
注意:如果 xyz 不在类 X 中并且没有“self”而只有“a,b,c”,那么它会打印 3。
对于低于 3.5 的 python,您可能希望在上面的代码中将 inspect.getfullargspec
替换为 inspect.getargspec
。
【讨论】:
【参考方案12】:Dimitris Fasarakis Hilliard 接受的答案建议以字符串格式获取参数,但我认为在解析此字符串时可能会出错,因此我直接使用检查模块创建了一个参数列表
import inspect
def my_function(a,b,c):
#some code
pass
result=list(inspect.signature(my_function).parameters.keys())
print(result)
['a','b','c']
【讨论】:
【参考方案13】:假设您可能正在处理基于类的method
s 或只是function
s,您可以执行以下操作。
如果输入是类方法,这将自动减去一个输入(因此包括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
【讨论】:
以上是关于如何找到 Python 函数的参数数量?的主要内容,如果未能解决你的问题,请参考以下文章