Let's say I have two classes Child
and Parent
(which is base class for Child
). I have another class Dec
which contains a decorator dec
I'd like to be used over Parent
methods. I want to be able to specify a Dec
object that should be used in Child
.
Here's what I've tried so far:
class Dec():
def dec(self, func):
def wrapper(self):
print("Before func call")
func(self)
print("After func call")
return wrapper
class Parent():
dec = None
@dec.dec
def p(self):
print('hello')
dec = Dec()
class Child(Parent):
a = dec
t = Child()
t.p()
So, I got
AttributeError: 'NoneType' object has no attribute 'dec'
at @dec.dec
.
Is there any option to specify a class with decorator that should be used in Child
class?
The issue you are experiencing here has to do with scoping.
When I ran this code, I received this error:
...<stack trace>...
File ".\__main__.py", line 10, in <module>
class Parent():
File ".\__main__.py", line 13, in Parent
@dec.dec
AttributeError: 'NoneType' object has no attribute 'dec'
Using that, you can see that you have some scoping issues. In this file, you define dec
several times. Rather than instantiate Dec
like you do on line 11, define Dec.dec(...)
as a @classmethod
, callable from the class itself, instead of just an instance of the class.
here is a potential solution:
class Dec():
@classmethod
def dec(self, func):
def wrapper(self):
print("Before func call")
func(self)
print("After func call")
return wrapper
class Parent():
@Dec.dec
def p(self):
print('hello')
class Child(Parent):
pass # you didn't really need anything here.
t = Child()
t.p()
This provides what I believe to be the expected behavior:
Before func call
hello
After func call
As an alternative to the other solution, here's another approach:
define some sort of generic structure for your process, and then change the "decorator" or "extended processor" for your classes...
class Parent:
extended_processor = None
def p(self):
if (self.extended_processor is not None and
hasattr(self.extended_processor, "before") and
callable(self.extended_processor.before)):
self.extended_processor.before()
print('parent says hello')
if (self.extended_processor is not None and
hasattr(self.extended_processor, "after") and
callable(self.extended_processor.after)):
self.extended_processor.after()
class ex_proc:
@classmethod
def before(cls):
print("ex_proc before")
@classmethod
def after(cls):
print("ex_proc after")
class Child(Parent):
extended_processor = ex_proc
print("\n=== PARENT ===")
par = Parent()
par.p()
print("\n=== CHILD ===")
chi = Child()
chi.p()
this provides the following output:
=== PARENT ===
parent says hello
=== CHILD ===
ex_proc before
parent says hello
ex_proc after
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.