Search code examples
pythoncpython

Get a list of class methods inside C-Python


Let's say I have a class defined in python as following

class A(object):
    def __init__(self):
        pass
    def rockabye(self):
        pass

class B(A):
    def __init__(self):
        pass
    def iamOnlyinB(self):
        pass

I am trying to get a list of the functions that only exist in B and not inherited from A or object.

PyTypeObject* l_typeObject = <a function out of scope of the question>

for (int i = 0; true; i++)
    {
        PyMethodDef method_def = l_typeObject->tp_methods[i];
        if(method_def.ml_name == NULL)
            break;
        std::cout << method_def.ml_name <<std::endl;

    }

I always find l_typeObject->tp_methods is NULL. Why ? and what are the possible alternative approaches ?


Solution

  • tp_methods is:

    An optional pointer to a static NULL-terminated array of PyMethodDef structures, declaring regular methods of this type.

    For each entry in the array, an entry is added to the type’s dictionary (see tp_dict below) containing a method descriptor.

    This field is not inherited by subtypes (methods are inherited through a different mechanism).

    In other words, these are the builtin methods attached to the class by the extension module that created it.

    For a class built in Python, there are no builtin methods, and there is no extension module that created it, so it will always be either NULL or empty.


    What you want to do is the same thing you do in Python:

    • Either look in the class's dict (which you can access via tp_dict), or
    • Call a method like dir or inspect.getmembers (the same way you'd call any other Python code).

    Of course that gets you all attributes of the class (depending on which you do, also possibly all inherited attributes), so if you want just the methods, you need to filter it. But you do this the same way as in Python as well.

    Since "method" is kind of an ambiguous term (Should it include classmethods and staticmethods? What about wrappers that act just like functions when bound as methods, but aren't functions? And so on…), you need to come up with exactly the rule you want to filter on, and apply it the same way you would from Python. (A few things, like PyCallable_Check, have special C API support; for anything else, you'll be doing a subclass check or calling a Python function.)