Chinmay Kanchi
Chinmay Kanchi

Reputation: 65893

Check if function belongs to a class

I'm trying to write a documentation testing tool which checks whether the docstrings match the actual function signature (among other things). However, I've run into a bit of a roadblock. I can't find a way to figure out whether a given function belongs to a class or not.

import inspect

def func1():
    pass


class Foo:
    def method(self):
        pass

print(inspect.ismethod(func1))  # prints False
print(inspect.ismethod(Foo().method)) # prints True
print(inspect.ismethod(Foo.method)) # prints False - I want something that prints True here

The problem is that methods usually have self as their first parameter, and this is never documented (for obvious reasons). This would cause my tests to fail, since they'd encounter a parameter that's not documented.

I would prefer to not explicitly check if the first parameter is called self and skip it, because a) nothing prevents a function from having a parameter called self and b) the name self itself is a matter of convention (so you could have a method with a first param that's called this_is_definitely_not_self) and my tool would fail in either case. I also can't just initialize an object and check if the function is a method, because this would fail with any class that takes required parameters in its __init__.

So the question is, is there any way I can detect if a function is a method before it is actually bound to an object? Or do I need to resign myself to just checking if the first parameter is called self?

Upvotes: 5

Views: 4751

Answers (1)

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160407

One option is __qualname__. For methods this includes the class name which you can use. This is one of the reasons why it was added:

definition.__qualname__

The qualified name of the class, function, method, descriptor, or generator instance.

See PEP 3155's proposal for more on this attribute.

Of course, since __qualname__ is set during class definition, one can get false-positives when functions are dynamically added to a class. So, this answer basically covers the question of if a function has been defined in a class.

So, there's no clear-cut way to detect this since, a function defined inside a class and accessed via the class and a function outside a class have no difference. (except for __qualname__ in most cases).

A sensible course of action would be to use the __qualname__ as a "quick" check to see if a function has been defined inside a class and, if that is False, fall back to checking for self with the inspect.signature function and 'self' in signature(func).parameters.

You won't be able to cover all cases, this is Python and I can do pretty much anything I'd like. Purportedly we are all consenting adults, though. :)

Upvotes: 6

Related Questions