The mwe of my problem I just coded:
from decorator import decorator
@decorator
def deco(func, deco_name=None, *args, **kwargs):
print(f"DECORATOR {deco_name} APPLIED")
return func(*args, **kwargs)
deco_name = None
class Greeter:
def __init__(self, _deco_name):
global deco_name
deco_name = _deco_name
@deco(deco_name=deco_name)
def hello(self, name):
print(f"Hello {name} :)")
print(deco_name)
g = Greeter("MYDECO")
g.hello("Yoshi")
The console output:
DECORATOR None APPLIED
Hello Yoshi :)
MYDECO
I had a similar set-up in my project and I fail to understand why the decorator function deco() does not know the value of the updated value of the global variable deco_name (it prints DECORATOR None APPLIED instead of DECORATOR MYDECO APPLIED). The decorated function hello() does know the update value as seen by the MYDECO generated by the last print statement. I need some way to set a global variable on runtime and pass it to the decorator and would be happy if someone can a) explain to me why my approach is wrong and b) give me a fix/alternative solution.
Thanks in advance.
The main issue is the decorator is created when the class is made. So the outside decorator is called before you set the variable. You can put all this inside the wrapper function so it only gets called when hello()
is called.
I'm not certain why you are using a global variable here. You can access the instance variable in the wrapper function, which to me makes more sense. Here's an example that sets and accesses both a global variable and an instance variable. Maybe it will point things in a helpful direction:
def deco(f):
def wrapper(*args):
instance = args[0]
print(f"DECORATOR Instance {instance.deco_name} APPLIED")
print(f"GLOBAL NAME {global_deco_name} APPLIED")
f(*args)
return wrapper
global_deco_name = "global_deco"
class Greeter:
def __init__(self, _deco_name):
global global_deco_name
self.deco_name = _deco_name
global_deco_name = _deco_name
@deco
def hello(self, name):
print(f"Hello {name} :)")
print(self.deco_name)
print(global_deco_name)
g = Greeter("MYDECO")
g.hello("Yoshi")
Prints
DECORATOR Instance MYDECO APPLIED
GLOBAL NAME MYDECO APPLIED
Hello Yoshi :)
MYDECO
MYDECO