3

Here is the context simplified:

class A(object):
    def __init__(self):
        self.vocab = [
            ('method1', self.method1),
            ('method2', 'arg2', self.method2),
            ('method3', self.method3),
        ]

class SubA(A):
    def method4(self):
        pass
    def method5(self, arg5):
        pass

class SubB(A):
    def method6(self):
        pass
    def method7(self):
        pass

I want to "automatically" fill self.vocab list from class A with all method from all subclasses and following the rule defined in self.vocab initialisation. So in this example I want to add method4,...,method7 automatically when object is instanciate. So self.vocab becomes:

    self.vocab = [
        ('method4', self.method4),
        ('method5', 'arg5', self.method5),
        ('method6', self.method6),
        ('method7', self.method7),
        ('method1', self.method1),
        ('method2', 'arg2', self.method2),
        ('method3', self.method3),
    ]

I think I have to change A into metaclass and use __new__ instead because I think it must be done before instanciation. In fact the class A is introspected by another code. self.vocab is extracted during instantiation and that's why I think it must be done before.

I don't know how to proceed and if it's possible.

Katsu
  • 1,868
  • 4
  • 19
  • 28

3 Answers3

3

The inspect module contains all tools that you need for this.

See this question how to get all methods of a class: How do I get list of methods in a Python class?

You can get your own current class in __init__ using self.__class__.

Community
  • 1
  • 1
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • 1
    +1 for inspect module. I will see more in details and I come back. – Katsu Nov 14 '13 at 16:14
  • You finally anwers the question (`self.__class__` in init). But in fact the inspection must be done after import of module (classes) and before instanciation. But it's another question I will post later. – Katsu Nov 14 '13 at 17:22
1

So, here is my solution. I changed initial setup a bit, though I tried to keep the original idea:

import inspect


class A(object):

    vocab = set()

    def __new__(cls, *args, **kwargs):
        A.vocab.update(inspect.getmembers(cls, inspect.ismethod))


class SubA(A):

    def method4(self):
        pass

    def method5(self, arg5):
        pass


class SubB(A):

    def method6(self):
        pass

    def method7(self):
        pass


print A.vocab  # set([])
SubA()
SubA()
SubB()
print A.vocab # set([('method5', <unbound method SubA.method5>), ('method6', <unbound method SubB.method6>), ('method4', <unbound method SubA.method4>), ('method7', <unbound method SubB.method7>)])
Alexander Zhukov
  • 4,357
  • 1
  • 20
  • 31
  • It seems to work when I try with dummy class. But here my classes are introspected by another code and if I add `__new__` method, it returns the error:`AttributeError: 'NoneType' object has no attribute 'vocab'`. Maybe I have to return something in new method? Of course I added the __init__ method with all features. – Katsu Nov 14 '13 at 17:02
  • In fact I have to had in __new__ method at the end: `return super(A, cls).__new__(cls)`. But it is the same as to do it before initialisation and with self.__class__ as reference (see @Aaron Digulla) – Katsu Nov 14 '13 at 17:17
0

Actually inspect package can do every thing for you. you can use it like this..

inspect.getmembers(mod, inspect.isfunction) # returns all the members of the given module which are functions

But you can change the predicate such as isfunction, isclass, ismethod for bound methods etc.

Hope this helps :)

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Sravan K Ghantasala
  • 1,058
  • 8
  • 14