How to find out the arity of a method in Python
Module inspect
from Python's standard library is your friend -- see the online docs! inspect.getargspec(func)
returns a tuple with four items, args, varargs, varkw, defaults
: len(args)
is the "primary arity", but arity can be anything from that to infinity if you have varargs
and/or varkw
not None
, and some arguments may be omitted (and defaulted) if defaults
is not None
. How you turn that into a single number, beats me, but presumably you have your ideas in the matter!-)
This applies to Python-coded functions, but not to C-coded ones. Nothing in the Python C API lets C-coded functions (including built-ins) expose their signature for introspection, except via their docstring (or optionally via annotations in Python 3); so, you will need to fall back to docstring parsing as a last ditch if other approaches fail (of course, the docstring might be missing too, in which case the function will remain a mystery).
Use a decorator to decorate methods e.g.
def arity(method): def _arity(): return method.func_code.co_argcount - 1 # remove self method.arity = _arity return methodclass Foo: @arity def bar(self, bla): passprint Foo().bar.arity()
Now implement _arity
function to calculate arg count based on your needs
This is the only way that I can think of that should be 100% effective (at least with regard to whether the function is user-defined or written in C) at determining a function's (minimum) arity. However, you should be sure that this function won't cause any side-effects and that it won't throw a TypeError:
from functools import partialdef arity(func): pfunc = func i = 0 while True: try: pfunc() except TypeError: pfunc = partial(pfunc, '') i += 1 else: return idef foo(x, y, z): passdef varfoo(*args): passclass klass(object): def klassfoo(self): passprint arity(foo)print arity(varfoo)x = klass()print arity(x.klassfoo)# output# 3# 0# 0
As you can see, this will determine the minimum arity if a function takes a variable amount of arguments. It also won't take into account the self or cls argument of a class or instance method.
To be totally honest though, I wouldn't use this function in a production environment unless I knew exactly which functions would be called though as there is a lot of room for stupid errors. This may defeat the purpose.