1

What is the correct way in Python 3.7+ to check if a function is defined within a Python class. Example:

class A:

    def fun1(self):
        pass

def fun2():
    pass

I would like to distinguish that A.fun1 was defined within a class and fun2 is not.

Hernan
  • 5,811
  • 10
  • 51
  • 86
  • You're asking `magic(A.fun1)` should return `True` and `magic(fun2)` should return `False`, right? – deceze Feb 22 '21 at 15:41
  • 4
    what is the point of doing this? what problem are you trying to solve? – marcusshep Feb 22 '21 at 15:41
  • There are [inspect.ismethod](https://docs.python.org/3/library/inspect.html#inspect.ismethod) and [inspect.isfunction](https://docs.python.org/3/library/inspect.html#inspect.isfunction). `ismethod` should be called on object. Do these: `print(inspect.ismethod(A().fun1), inspect.isfunction(A().fun1)); print(inspect.ismethod(fun2), inspect.isfunction(fun2))`. – Arty Feb 22 '21 at 16:20
  • @deceze Exactly – Hernan Feb 22 '21 at 16:55
  • @Arty As you pointed out, is method requires instantiating the class which might not be possible or easy or have side effects in certain cases. – Hernan Feb 22 '21 at 16:56
  • @marcusshep I want to modify a callable differently when acting on static methods, class methods, methods or functions. Right now I have four distinct decorators, but it would be easier from the user perspective to have a single decorator that dispatch to the right implementation based on the target. When I tried to implement this, I was not able to find a robust way to get this information for an uninstatiated class. – Hernan Feb 22 '21 at 20:16

2 Answers2

2

You can use the attribute __qualname__ (defined in PEP 3155) and check whether it contains a . which indicates that this object was defined in a nested scope. Note that this also applies to functions defined inside other functions, so it might give you false positives in that sense.

>>> def test(): ...
... 
>>> test.__qualname__
'test'
>>> class Foo:
...     def test(self): ...
... 
>>> Foo.test.__qualname__
'Foo.test'
>>> def f():
...     def g(): ...
...     return g
... 
>>> f().__qualname__
'f.<locals>.g'
a_guest
  • 34,165
  • 12
  • 64
  • 118
-1

Here you go hasattr()

>>> hasattr(A, 'fun1')
>>> True

>>> hasattr(A, 'fun2')
>>> False
go2nirvana
  • 1,598
  • 11
  • 20
  • 1
    And how is my answer not solving that problem? – go2nirvana Feb 22 '21 at 15:37
  • Method is a function defined within a class. Determining if class has a specific function is exactly equal to "distinguish that function was defined within a class" - as OP requested. – go2nirvana Feb 22 '21 at 15:41
  • Well, i answer what was asked in the question, not playing a "guess what that really means" game. – go2nirvana Feb 22 '21 at 15:43
  • In this particular case question was very clear for me, so i see no need to clarify. In fact, if you take a look at answer's at deceze's suggestion: the third answer (and 2nd most voted) is the same as mine. This concludes to me, that questions in fact are similar. And rather than doubting my answer, the appropriate action would be to flag question as duplicate. Anyway, i suggest we move on. – go2nirvana Feb 22 '21 at 15:49
  • @go2nirvana I thought that the last phrase in my question was clarifying this: "I would like to distinguish that A.fun1 was defined within a class and fun2 is not" Which is not the same as saying if a given class defines a function with a given name. – Hernan Feb 22 '21 at 16:59
  • @Hernan https://stackoverflow.com/questions/961048/get-class-that-defined-method – go2nirvana Feb 23 '21 at 11:15