-1

if I run one of following code variants

var1, var2 ='', ''
globals()['var1']='value1'
print(f'{var1=}, {var2=}')

var1, var2 ='', ''
locals()['var1']='value1'
print(f'{var1=}, {var2=}')

var1, var2 ='', ''
vars()['var1']='value1'
print(f'{var1=}, {var2=}')

all of them will return var1='value1', var2='', which is what I expect, but if I put them into a function, then they will not work any more.

def test():
    var1, var2 ='', ''
    globals()['var1']='value1'
    return var1, var2

def test():
    var1, var2 ='', ''
    locals()['var1']='value1'
    return var1, var2

def test():
    var1, var2 ='', ''
    vars()['var1']='value1'
    return var1, var2

will return ('', ''),any clue about makeing it also work in a function? thanks.

edit: thank to the link above, using globals(), locals(), vars() are often not good idea since locals() and vars() are immutable. For similar purposes, use a dict instead:

def test():
    p = {'var1':'', 'var2':''}
    p['var1']='value1'
    return p['var1'], p['var2']
kay
  • 147
  • 1
  • 8
  • 1
    This (hack-ish) logic begs the question: What is the core purpose? Please update the question to explain the use case, as there is likely a more Pythonic (robust) way to address the intent. – S3DEV Oct 06 '22 at 10:30
  • 1
    Still not clear exactly why you are doing this, but there must be a better way to set / return parameters. Are you just trying to make a decorator so that the decorated function returns its own parameters? – Stuart Oct 06 '22 at 11:00
  • 1
    Well, TL;DR: *don't.* What you're trying to do, nobody does in practice. Thus it doesn't have to work. To what extend are you interested in the internals of Python, and to what extend are you trying to solve a practical issue? – deceze Oct 06 '22 at 11:01
  • Your `test` function with `globals` doesn't work, because `return var1, var2` operates on *local* variables, not globals. The other two don't work because see duplicate above. – deceze Oct 06 '22 at 11:17

1 Answers1

2

Mutating globals() is probably a bad idea, but to answer the question as asked, it is because assigning to names inside functions marks them as local variables by default. They then shadow the global variable of the same name if it exists. You can use a global declaration to mark them as global variables.

Example:

var1 = 'this is a global variable'
var2 = 'this is also a global variable'

print(var1, var2)

def example():
    global var2
    var1 = 'this is a local variable'
    var2 = 'this is still a global variable'
    print(var1, var2)

example()

print(var1, var2)

So to get your desired behaviour, you should do:

def test():
    global var1, var2
    var1, var2 = '', ''
    globals()['var1']='asdf'
    return var1, var2

But in practice you should avoid mutating globals() -- and avoid re-assigning global variables in general.

Jasmijn
  • 9,370
  • 2
  • 29
  • 43
  • thanks, actually I don't want to change the global vars, I can live with the locals()[], but none of them working. I updated my question. – kay Oct 06 '22 at 10:55
  • @kay `locals()` isn't mutable. – deceze Oct 06 '22 at 10:57
  • @deceze you mean not mutable in a function? but as I showed example above, the vars()[] and the locals()[] will work perfectly out of a function, that's what I don't understand about these build-in functions of python – kay Oct 06 '22 at 11:05
  • @kay See the duplicate(s) I added at the top… – deceze Oct 06 '22 at 11:05