15

I'm looking for a way to check the number of arguments that a given function takes in Python. The purpose is to achieve a more robust method of patching my classes for tests. So, I want to do something like this:

class MyClass (object):
    def my_function(self, arg1, arg2):
        result = ... # Something complicated
        return result

def patch(object, func_name, replacement_func):
    import new

    orig_func = getattr(object, func_name)
    replacement_func = new.instancemethod(replacement_func, 
                           object, object.__class__)

    # ...
    # Verify that orig_func and replacement_func have the 
    # same signature.  If not, raise an error.
    # ...

    setattr(object, func_name, replacement_func)

my_patched_object = MyClass()
patch(my_patched_object, "my_function", lambda self, arg1: "dummy result")
# The above line should raise an error!

Thanks.

mjumbewu
  • 1,014
  • 5
  • 13
  • 28
  • "patching my classes for tests"? Why aren't you using mock objects? http://python-mock.sourceforge.net/? – S.Lott Aug 20 '10 at 21:34
  • 2
    I'm new to using mocks. I "grew up" stubbing and patching. I'm getting practice and figuring out when to use which, but in the mean time, I still have projects to finish, and tests to write :). – mjumbewu Aug 21 '10 at 22:40

4 Answers4

14

You can use:

import inspect
len(inspect.getargspec(foo_func)[0])

This won't acknowledge variable-length parameters, like:

def foo(a, b, *args, **kwargs):
    pass
carl
  • 48,340
  • 17
  • 72
  • 81
8

inspect.getargspec is deprecated in Python 3. Consider something like:

import inspect
len(inspect.signature(foo_func).parameters)
Tahlor
  • 1,146
  • 1
  • 14
  • 19
5

You should use inspect.getargspec.

hwiechers
  • 13,931
  • 7
  • 51
  • 60
2

The inspect module allows you to examine a function's arguments. This has been asked a few times on Stack Overflow; try searching for some of those answers. For example:

Getting method parameter names in python

Community
  • 1
  • 1
Richard Fearn
  • 24,169
  • 6
  • 56
  • 55