Reputation: 109
class Foo():
help_message = ""
def Help_Decorator(func):
def wrapper(data, context, caller):
try:
if data[0] == "help":
return(help_message) #<--- cannot access this locally
else:
return func(data,context,caller)
except:
return func(data,context,caller)
return wrapper
class Bar(Foo):
help_message = "A real help message!"
@foo.Help_Decorator
def Run(data,context,caller):
pass
How can I access Bar's help_message from within my Help_Decorator without passing it as a parameter in Run
?
Upvotes: 0
Views: 72
Reputation: 71562
Since Run
is an instance method, data
is a Bar
instance. Normally this would be called self
by convention, but giving it a different name doesn't change the semantics of the function call.
You should therefore be able to access data.help_message
in your wrapper
function. (I would also expect that data[0]
gives you a TypeError
unless Bar
has implemented __getitem__
.)
If your intent is to call Run
on the class instead of an instance, it shouldn't be defined as an instance method. Make it a class method:
class Bar():
help_message = "A real help message!"
@classmethod
@foo.Help_Decorator
def Run(cls, data, context, caller):
pass
and in your wrapper now you can do:
def Help_Decorator(func):
def wrapper(cls, data, context, caller):
try:
if data[0] == "help":
return(cls.help_message)
else:
return func(cls, data, context, caller)
except:
return func(cls, data, context, caller)
return wrapper
Note that there is no need for Help_Decorator
to be a method of either Foo
or Bar
.
All together:
class Foo():
help_message = ""
def Help_Decorator(func):
def wrapper(cls, data, context, caller):
try:
if data[0] == "help":
return(cls.help_message)
else:
return func(cls, data, context, caller)
except:
return func(cls, data, context, caller)
return wrapper
class Bar(Foo):
help_message = "A real help message!"
@classmethod
@Foo.Help_Decorator
def Run(cls, data, context, caller):
return "derp"
print(Bar.Run(["help"], 1, 0))
prints:
A real help message!
Ripping Foo
out of the code completely produces the same exact result; there is no need for any kind of inheritance relation between the place where Help_Decorator
is implemented and the class whose methods it decorates:
def Help_Decorator(func):
def wrapper(cls, data, context, caller):
try:
if data[0] == "help":
return(cls.help_message)
else:
return func(cls, data, context, caller)
except:
return func(cls, data, context, caller)
return wrapper
class Bar:
help_message = "A real help message!"
@classmethod
@Help_Decorator
def Run(cls, data, context, caller):
return "derp"
print(Bar.Run(["help"], 1, 0))
Upvotes: 2
Reputation: 175
The first parameter passed to the wrapper is an instance of the Run class, you should add self as the first parameter. Then you can refer to self.help_message and it will return the help_message defined in the Run class.
(Edit) If you would like to use the decorator as a classmethod then just decorate it as such. Your example would become.
class foo():
help_message = "bad"
@classmethod
def Help_Decorator(cls, func):
@classmethod
def wrapper(cls, data, context, caller):
print(data, context, caller)
try:
if data[0] == "help":
print('helping', cls)
return(cls.help_message) #<--- cannot access this locally
else:
return func(data,context,caller)
except:
return func(data,context,caller)
return wrapper
class Bar():
help_message = "A real help message!"
@foo.Help_Decorator
@classmethod
def Run(cls, data,context,caller):
pass
Upvotes: 0