Reputation: 346
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
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