Joe Liu
Joe Liu

Reputation: 13

python decorator modify variable

I am trying to use decorator to modify variable value in python with the following code

def config(func):
    def new_function():
        func()
        print(lr)
    return new_function
import ex
@ex.config
def config():
    lr = 0.1
    globals().update(locals())
config()

I would like to print out 0.1, but error with variable not defined was shown. Is there anyway to achieve this without changing func_a?

Upvotes: 1

Views: 555

Answers (2)

cajomar
cajomar

Reputation: 498

In short, no.
What is happening here is func_a() is declaring and assigning lr as a local variable. You can fix this by adding the global keyword:

lr = 0
def config(func):
    def new_function(*args,**kwargs):
        func(*args,**kwargs)
    return new_function
@config
def func_a():
    global lr
    lr = 0.1
func_a()
print(lr)

But using the global keyword is annoying and can cause bugs if you forget it, so you might be better off returning:

lr = 0
def config(func):
    def new_function(*args,**kwargs):
        return func(*args,**kwargs)
    return new_function
@config
def func_a():
    return 0.1
lr = func_a()
print(lr)

Edit

You could put it in a class somehow like this:

# Make an empty class:
class Foo: pass
# Or if you want to initalize the variables:
class Foo:
    def __init__(self):
        lr = 0
f = Foo()

# The decorator doesn't make much of a difference
def func_a():
    f.lr = 0.1

func_a()
print(f.lr)

Now, if you want to keep absolutely all the local variables that func_a defines, you could do this:

def func_a():
    lr = 0.1
    f.__dict__.update(locals())

Upvotes: 1

霖同学
霖同学

Reputation: 33

'lr' is an local variable and you didn't save or return its value.So you just can get the value of global variable 'lr' in the first line and its value is 0.

Upvotes: 0

Related Questions