1

Let's say I have a class defined like this:

classA():
    def do_one():
        print("one")
    def do_two():
        print("two")
    def some_other():
        print("other")

I want to create a derived class and automatically define every method from the parent class that starts with do

I tried this:

class B(A):
    pass

for m in dir(A):
    if m[0:3] == "do_":
        def dm(self):
            print("somebething before")
            getattr(super(),m)()
        dm.__name__ = m
        setattr(B,m,dm)

But i'm getting this error: RuntimeError: super(): __class__ cell not found Also is there a non-so-hacky/pytonic way of achieving this?

B-K
  • 359
  • 1
  • 2
  • 9
  • Just to be more clear about the situation, what exactly are you trying to achieve? – lllrnr101 Mar 25 '21 at 04:08
  • I want to create a class wrapper that essentially overrides a number of (similar) methods from the parent, and those methods would consist in doing some stuff (the same for every method) and then calling the parent method – B-K Mar 25 '21 at 04:23
  • 1
    If going this route, I'd use the __init__ method to modify the instance's 'do_xxx' attributes so that super() etc. behave normally but it is probably cleaner to abstract further. Perhaps add the "actor" as a 'do' attribute and then wrap it for B. That way you would use e.g. `self.do.one()` rather than `self.do_one`. – Paul Whipp Mar 25 '21 at 06:12

1 Answers1

1

You cannot use super() without arguments outside a class definition. In order to perform lookups super() needs two arguments. Additionally, the definition of dm needs to be wrapped in another function. Otherwise, when it is executed the value of m will be taken from the global scope.

Putting this together, the following should work:

class A():
    def do_one(self):
        print("one")

    def do_two(self):
        print("two")

    def some_other(self):
        print("other")


class B(A):
    pass


for m in dir(B):
    if m[0:3] == "do_":

        def redef(m):
            def dm(self):
                print("something before")
                getattr(super(B, self), m)()

            return dm

        setattr(B, m, redef(m))

If you run:

x = B()
x.do_one()
x.do_two()
x.some_other()

It will give:

something before
one
something before
two
other
bb1
  • 7,174
  • 2
  • 8
  • 23