nosheyakku
nosheyakku

Reputation: 346

Why don't all methods inherit from the class?

Just for example:

class Foo:
    def wrapper(func):
        def wrapped(self):
            try:
                return func(self)
            except Exception:
                raise
            finally:
                print('Some error in wrapped function')
        return wrapped

    @wrapper
    def division(self, x, y):
        return x / y


class Bar(Foo):
    @wrapper
    def multiplication(self, x, y):
        return x * y


f = Foo()
print(f.division(5, 2))

b = Bar()
print(b.multiplication(3, 3))

Error:

Traceback (most recent call last):
  File "d:\Dev\abc-python\count.py", line 18, in <module>
    class Bar(Foo):
  File "d:\Dev\abc-python\count.py", line 20, in Bar     
    @wrapper
NameError: name 'wrapper' is not defined

When inheriting, I expect that the child class will have all the methods of the parent, I did not find the reverse information, at least I see no reason why the wrapper is not inherited by the child class.

Yes, I can move the decorators into a separate file and import them, maybe it will be "more correct", but I want to understand why they are not inherited.

Upvotes: 2

Views: 91

Answers (1)

juanpa.arrivillaga
juanpa.arrivillaga

Reputation: 95863

None of those names are in scope in the class block. They are members of the parent class namespace, so it is available at Foo.wrapper. This has nothing really to do with inheritance. It is inherited, but Bar doesn't exist yet when the class definition is being executed.

This works the same with any attribute that belongs to the parent namespace, when you are trying to use it in the class scope of the child class definition statement.

 In [1]: class Foo:
   ...:     def division(self, x, y): return x/y
   ...:

In [2]: class Bar(Foo):
   ...:     division(1,1)
   ...:
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-8-03e47cf52ab3> in <module>
----> 1 class Bar(Foo):
      2     division(1,1)
      3

<ipython-input-8-03e47cf52ab3> in Bar()
      1 class Bar(Foo):
----> 2     division(1,1)
      3

NameError: name 'division' is not defined

To get around this, you can do:

class Bar(Foo):

    @Foo.wrapper
    def multiplication(self, x, y):
        return x * y

Or:

class Bar(Foo):
    
    def multiplication(self, x, y):
        return x * y

Bar.multiplication = Bar.wrapper(Bar.multiplication)

Upvotes: 2

Related Questions