abukaj
abukaj

Reputation: 2712

How to determine number of function/builtin/callable parameters programmatically?

I want to be able to classify an unknown function/builtin/callable based on its number of arguments.

I may write a piece of code like that:

if numberOfParameters(f) == 0:
    noParameters.append(f)
elif numberOfParameters(f) == 1:
    oneParameter.append(f)
else:
    manyParameters.append(f)

but I have no idea how to implement numberOfParameters(). inspect.getargspec does not work with builtins. I can not use exceptions, since it is potentially expensive to call the function.

It would be great if the solution work with both Python 2.7 and Python 3.3+

Upvotes: 1

Views: 94

Answers (2)

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160527

You can somewhat do this, but only in Python 3. This is when ArgumentClinic made information about the signature of objects available.

Take note, not all built-ins are actually available as of right now, currently:

__import__ vars max print dir __build_class__ min iter round getattr next 

do not expose information about their signature. For the rest getargspec (a thin wrapper around getfullargspec) and Signature would do.

In Python 2, you only have the option of getargspec which doesn't do the trick for built-ins and probably never will. So, there's no solution that spans across python versions. For the most compatible solution, I'd use getargspec as of right now.

As for the most simplistic way to check, just count the args from the NamedTuple returned:

def NumberOfParameters(f):
    try:
        r = getargspec(f)
        return len(r.args)  # if it has kwargs, what do you do?
    except TypeError as e:
        print("Function {0} cannot be inspected".format(f.__name__))

Upvotes: 0

vishes_shell
vishes_shell

Reputation: 23504

From Python 3.3

New in version 3.3.

Introspecting callables with the Signature object

>>> import inspect
>>> inspect.signature(sorted).parameters
mappingproxy(OrderedDict([('iterable', <Parameter "iterable">), ('key', <Parameter "key=None">), ('reverse', <Parameter "reverse=False">)]))

And then you can count them, and do whatever you like.

Upvotes: 1

Related Questions