1

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?

Joe Liu
  • 13
  • 3
  • https://stackoverflow.com/questions/1360721/how-to-get-set-local-variables-of-a-function-from-outside-in-python – emirc Jun 19 '20 at 01:05
  • The decorator makes almost no difference here (aside from ignoring the return value). – alani Jun 19 '20 at 01:22

2 Answers2

1

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())
Community
  • 1
  • 1
cajomar
  • 428
  • 5
  • 9
  • 1
    Thanks for the comment, however the point is to keep ```func_a``` as it is. I am trying to replicate someone else's work and make adjustment based on it, the only part of the code I have is similar to ```func_a``` but with hundreds more variables. For more complete information, ```@config``` used to be ```@obj.config``` in their original code, but I don't think obj is a class. – Joe Liu Jun 19 '20 at 01:26
  • @JoeLiu I'm assuming that `lr` must be a file-wide global variable? Because ideally you could put that (and he other hundreds) in a class or something. Here's another idea, with only slight modification to `func_a()`: https://stackoverflow.com/a/11543718/12465821 – cajomar Jun 19 '20 at 02:11
  • The link you shared is very interesting. but I am not sure if the method would work if I were to separate the two functions into two files, like shown in the newly edited question above. I am also really interested in your ideal of putting the variables into a class? I tried it before but failed, Could you please share your idea of the implementation? – Joe Liu Jun 19 '20 at 18:22
  • @JoeLiu I just edited my answer to include two ways of doing that. – cajomar Jun 19 '20 at 21:43
  • This answer is really interesting, I think I can modify this to what I need. Thank you for your answer. – Joe Liu Jun 19 '20 at 22:04
0

'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.

霖同学
  • 33
  • 4