196

How can I find the number of arguments of a Python function? I need to know how many normal arguments it has and how many named arguments.

Example:

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

This method has 2 arguments and 1 named argument.

Aaron Digulla
  • 297,790
  • 101
  • 558
  • 777
Georg Schölly
  • 116,521
  • 48
  • 204
  • 258
  • 44
    the question is fully warranted; if it wasn't (since you can always read the source), there wouldn't be any justification for the `inspect` standard library module. – flow May 26 '11 at 12:31
  • Plenty of languages implement at least one unjustified feature. The `inspect` module has a lot of other features, so it is unfair to say that the whole module would be unjustified if one particular function in it was. Moreover, it's easy to see how this feature could be used poorly. (See http://stackoverflow.com/questions/741950). That said, it is a useful feature, especially for writing decorators and other functions that operate on function. – user1612868 May 29 '14 at 10:40
  • @flow what do you mean by 'fully warrented'? – Gulzar Aug 05 '20 at 06:32
  • https://stackoverflow.com/questions/20981789/difference-between-methods-and-functions-in-python-compared-to-c – Smart Manoj Oct 24 '20 at 14:27
  • https://stackoverflow.com/questions/47169033/parameter-vs-argument-python – Smart Manoj Oct 24 '20 at 14:29

11 Answers11

169

The previously accepted answer has been deprecated as of Python 3.0. Instead of using inspect.getargspec you should now opt for the Signature class which superseded it.

Creating a Signature for the function is easy via the signature function:

from inspect import signature

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

sig = signature(someMethod)

Now, you can either view its parameters quickly by string it:

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

or you can also get a mapping of attribute names to parameter objects via sig.parameters.

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

Additionally, you can call len on sig.parameters to also see the number of arguments this function requires:

print(len(params))  # 3

Each entry in the params mapping is actually a Parameter object that has further attributes making your life easier. For example, grabbing a parameter and viewing its default value is now easily performed with:

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

similarly for the rest of the objects contained in parameters.


As for Python 2.x users, while inspect.getargspec isn't deprecated, the language will soon be :-). The Signature class isn't available in the 2.x series and won't be. So you still need to work with inspect.getargspec.

As for transitioning between Python 2 and 3, if you have code that relies on the interface of getargspec in Python 2 and switching to signature in 3 is too difficult, you do have the valuable option of using inspect.getfullargspec. It offers a similar interface to getargspec (a single callable argument) in order to grab the arguments of a function while also handling some additional cases that getargspec doesn't:

from inspect import getfullargspec

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

args = getfullargspec(someMethod)

As with getargspec, getfullargspec returns a NamedTuple which contains the arguments.

print(args)
FullArgSpec(args=['self', 'arg1', 'kwarg1'], varargs=None, varkw=None, defaults=(None,), kwonlyargs=[], kwonlydefaults=None, annotations={})
Dimitris Fasarakis Hilliard
  • 119,766
  • 27
  • 228
  • 224
  • 1
    You're welcome @GeorgSchölly. I was surprised a popular question like this one offered solutions that either were deprecated or down right sneaky (peeking in the `co_argcount` attribute.) – Dimitris Fasarakis Hilliard Dec 16 '16 at 16:37
  • 1
    `getfullargspec` is not implemented in Python 2.x, you need to use `getargspec` – Peter Gibson May 03 '17 at 22:59
  • 1
    `getargspec` does not work on built-in functions: `getargspec(open)` gives `TypeError: is not a Python function` See [this answer](http://stackoverflow.com/questions/3276635/how-to-get-the-number-of-args-of-a-built-in-function-in-python) for some ideas... – starfry May 08 '17 at 09:50
  • In your last example, when you do `print(args)` you don't get `defaults=(None,)` you get `defaults=None`. – Seanny123 Jul 04 '18 at 16:42
  • si there a way to get the original parameter count for a function which has been decorated post the decoration..? – Gulats Aug 06 '19 at 17:43
  • https://stackoverflow.com/questions/20981789/difference-between-methods-and-functions-in-python-compared-to-c – Smart Manoj Oct 24 '20 at 14:27
119
import inspect
inspect.getargspec(someMethod)

see the inspect module

Jochen Ritzel
  • 94,379
  • 28
  • 188
  • 182
  • 5
    Generally what you want, but this doesn't work for built-in functions. The only way to know to get this info for builtins is to parse their __doc__ string, which is fugly but doable. – Cerin Jul 14 '10 at 18:48
  • 5
    This is deprecated in Python 3: https://docs.python.org/3/library/inspect.html#inspect.getargspec – noisecapella Feb 08 '16 at 19:15
  • Is there a solution which is not deprecated in Python 3? – hlin117 May 27 '16 at 22:18
  • 1
    If you follow the link you will see that it recommends using `inspect.signature` - https://docs.python.org/3/library/inspect.html#inspect.signature – coderforlife Jun 01 '16 at 01:13
  • I posted another possible approach for builtin functions without parsing the docstring here: https://stackoverflow.com/questions/48567935/get-parameter-count-of-builtin-functions-in-python – HelloWorld Feb 01 '18 at 18:25
32
someMethod.func_code.co_argcount

or, if the current function name is undetermined:

import sys

sys._getframe().func_code.co_argcount
miaoever
  • 438
  • 5
  • 9
  • 4
    @elyase, just do: `dir(someMethod)` -> `'func_code'`; Go further: `dir(someMethod.func_code)` -> `'co_argcount'`; You can use the built-in `dir()` to determine available methods of an object. –  Feb 04 '14 at 08:00
  • @elyase I was courious too, so I found this https://docs.python.org/2/library/inspect.html#types-and-members – rodripf Sep 13 '15 at 21:12
  • To support Python 3: `six.get_function_code(someMethod).co_argcount` – noisecapella Feb 08 '16 at 19:25
  • 8
    @noisecapella no need for a third party module, when you can simply do `some_method.__code__.co_argcount` – vallentin Mar 30 '16 at 19:15
  • 1
    In general, you *shouldn't* be peeking inside the function object to look at these things. `co_argcount` is used internally during evaluation of the code object. What I'm trying to say is, there's really no guarantees that these attributes won't change from one release to the other. – Dimitris Fasarakis Hilliard Dec 16 '16 at 16:39
16

inspect.getargspec()

Get the names and default values of a function’s arguments. A tuple of four things is returned: (args, varargs, varkw, defaults). args is a list of the argument names (it may contain nested lists). varargs and varkw are the names of the * and ** arguments or None. defaults is a tuple of default argument values or None if there are no default arguments; if this tuple has n elements, they correspond to the last n elements listed in args.

Changed in version 2.6: Returns a named tuple ArgSpec(args, varargs, keywords, defaults).

See can-you-list-the-keyword-arguments-a-python-function-receives.

Community
  • 1
  • 1
gimel
  • 73,814
  • 10
  • 69
  • 104
9

func.__code__.co_argcount gives you number of any arguments BEFORE *args

func.__kwdefaults__ gives you a dict of the keyword arguments AFTER *args

func.__code__.co_kwonlyargcount is equal to len(func.__kwdefaults__)

func.__defaults__ gives you the values of optional arguments that appear before *args

Here is the simple illustration:

the illustration

>>> 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
Hzzkygcs
  • 644
  • 7
  • 14
6

Adding to the above, I've also seen that the most of the times help() function really helps

For eg, it gives all the details about the arguments it takes.

help(<method>)

gives the below

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
  • 1,604
  • 1
  • 13
  • 13
  • It would be good for people to leave a comment on what is wrong with a post than to just click on the minus button. – Venu Murthy Dec 24 '13 at 07:40
  • 2
    `help` function only shows what the docstring says. Have you even tested if it works with the function definition in the question? – 0xc0de Nov 02 '14 at 17:35
  • 1
    @0xc0de - Have you tested it? Because it actually does work. `help()` spits out more than just the docstring - even on undocumented code it still prints out the argspec and tells you where the code was defined. The person who posted the original question wasn't clear whether they needed an answer that was machine or human friendly. If it only needs to be human friendly, `help()` is perfectly adequate. – ArtOfWarfare Jan 17 '16 at 23:09
  • @ArtOfWarfare not at all, as now you would have to parse whatever `help()` returns, and try and find the `args` and `kwargs`. – vallentin Mar 30 '16 at 19:18
5

Good news for folks who want to do this in a portable way between Python 2 and Python 3.6+: use inspect.getfullargspec() method. It works in both Python 2.x and 3.6+

As Jim Fasarakis Hilliard and others have pointed out, it used to be like this:
1. In Python 2.x: use inspect.getargspec()
2. In Python 3.x: use signature, as getargspec() and getfullargspec() were deprecated.

However, starting Python 3.6 (by popular demand?), things have changed towards better:

From the Python 3 documentation page:

inspect.getfullargspec(func)

Changed in version 3.6: This method was previously documented as deprecated in favour of signature() in Python 3.5, but that decision has been reversed in order to restore a clearly supported standard interface for single-source Python 2/3 code migrating away from the legacy getargspec() API.

blackbrandt
  • 864
  • 7
  • 24
HAltos
  • 387
  • 2
  • 5
3

inspect.getargspec() to meet your needs

from inspect import getargspec

def func(a, b):
    pass
print len(getargspec(func).args)
Eds_k
  • 422
  • 5
  • 7
  • 1
    Welcome to Stack Overflow! Please don't answer just with source code. Try to provide a nice description about how your solution works. See: [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer). Thanks – sɐunıɔןɐqɐp Sep 30 '18 at 08:16
2

As other answers suggest, getargspec works well as long as the thing being queried is actually a function. It does not work for built-in functions such as open, len, etc, and will throw an exception in such cases:

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

The below function (inspired by this answer) demonstrates a workaround. It returns the number of args expected by 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

The idea is to parse the function spec out of the __doc__ string. Obviously this relies on the format of said string so is hardly robust!

Community
  • 1
  • 1
starfry
  • 7,737
  • 5
  • 57
  • 81
0

In:

import inspect 

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

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

Out:

4


Note: If xyz wasn't inside class X and had no "self" and just "a, b, c", then it would have printed 3.

For python below 3.5, you may want to replace inspect.getfullargspec by inspect.getargspec in the code above.

Guillaume Chevalier
  • 6,933
  • 5
  • 46
  • 67
0

The accepted answer by Dimitris Fasarakis Hilliard suggests getting parameters in the string format but I think one can make a mistake when parsing this string and thus I created rather a list of the parameters directly using the inspect module

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

result=list(inspect.signature(my_function).parameters.keys())
print(result)
['a','b','c']
DovaX
  • 488
  • 5
  • 11