3

Consider the following code:

args, varargs, varkw, defaults = inspect.getargspec(method)
if inspect.ismethod(method):
    args = args[1:]    # Skip 'self'

When running this on Python 2 and adding something with self, self is skipped (as mentioned in the comment). On Python 3, however I got trouble when using the code on Class.method (i.e. not instance.method). The problem is similar to Detecting bound method in classes (not instances) in Python 3, but non of the answers there works. Using inspect.isroutine() or inspect.isfunction() breaks the code for non-methods (no self). Using hasattr(method, '__self__') doesn't work on Class.method.

I've written a small testscript for this:

from __future__ import print_function
import inspect


def args_without_self(method):
    args, varargs, varkw, defaults = inspect.getargspec(method)
    if inspect.ismethod(method):
        args = args[1:]    # Skip 'self'
    return args


class Class(object):

    def method(self, a, b, c):
        pass

    @staticmethod
    def static(a, b, c):
        pass

    @classmethod
    def classmethod(cls, a, b, c):
        pass


def function(a, b, c):
    pass

instance = Class()

print(args_without_self(Class.method))
print(args_without_self(instance.method))
print(args_without_self(Class.static))
print(args_without_self(instance.static))
print(args_without_self(Class.classmethod))
print(args_without_self(instance.classmethod))
print(args_without_self(function))

The code works with both Python 2 and 3. However args_without_self(Class.method) also has self in Python 3 (and I would like to avoid that, but not break the others). Everythign should print ['a', 'b', 'c'].

Community
  • 1
  • 1
hroncok
  • 1,147
  • 8
  • 12

1 Answers1

8

You can't, on Python 3, detect methods on the class, as they are never bound. They are just regular functions.

At most you can look at their qualified name and guess if they might be methods, then see if the first argument is named self. Heuristics and guesses, in other words:

if inspect.isfunction(method) and `.` in method.__qualname__ and args[0] == 'self':
    args = args[1:]    # Skip 'self'
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343