8

I'm a python/programming newbie and maybe my question has no sense at all.

My problem is that I can't get a variable to be global if it is dynamic, I mean I can do this:

def creatingShotInstance():

    import movieClass

    BrokenCristals = movieClass.shot()
    global BrokenCristals #here I declare BrokenCristals like a global variable and it works, I have access to this variable (that is a  shot class instance) from any part of my script.
    BrokenCristals.set_name('BrokenCristals')
    BrokenCristals.set_description('Both characters goes through a big glass\nand break it')
    BrokenCristals.set_length(500)
    Fight._shots.append(BrokenCristals)

def accesingShotInstance():
    import movieClass

    return BrokenCristals.get_name()#it returns me 'BrokenCristals'

but if instead of doing that I declare a string variable like this:

def creatingShotInstance():

    import movieClass

    a = 'BrokenCristals'

    vars()[a] = movieClass.shot()
    global a #this line is the only line that is not working now, I do not have acces to BrokenCristals class instance from other method, but I do have in the same method.
    eval(a+".set_name('"+a+"')")
    eval(a+".set_description('Both characters goes through a big glass\nand break it')")
    eval(a+".set_length(500)")
    Fight._shots.append(vars()[a])

def accesingShotInstance():
    import movieClass

    return BrokenCristals.get_name()#it returns me 'BrokenCristals is not defined'

I tried this :

global vars()[a]

and this:

global eval(a)

but It gives me an error. What should I do?

user497457
  • 327
  • 2
  • 3
  • 9
  • 6
    Take the hint. Don't do this. It doesn't make sense in the long run to have a "dynamic" variable. Why would you even want such a thing? – S.Lott Nov 25 '10 at 12:33
  • aaronasterling is not a joke( thanks for your nice comment anyway) what I'm trying to do is to create a class instance with a name that I get from an entry in an UI, so the name is a dynamic variable. – user497457 Nov 25 '10 at 12:49
  • 1
    Well then Ned Batchelder solveed the problem for you. Unless you want a quasi-fancy metaclass that registers instances based on the name of the movie and provides a constructor implementing the fly-weight pattern. Ned's solution is almost certainly better. – aaronasterling Nov 25 '10 at 12:55
  • Remember that `global a` deals with a global variable named 'a'; `global a` becomes `global('a')`, not `global(a)`, if you see what I mean (not that global is a function - `global(a)` won't work). – Chris Morgan Nov 25 '10 at 13:09
  • If the variable, including its very name are dynamic, how can you be hardcoding it into functions? If you're going to use a global variable for this, give it an unchanging global name and make it a container object of some kind, like a dictionary or class instance, and store any data you need inside of it. BTW, the [docs](http://docs.python.org/library/functions.html?highlight=vars#vars) suggest **not** modifying the dictionary `vars()` returns. – martineau Nov 25 '10 at 13:15

4 Answers4

19

For completeness, here's the answer to your original question. But it's almost certainly not what you meant to do -- there are very few cases where modifying the scope's dict is the right thing to do.

globals()[a] = 'whatever'
Katriel
  • 120,462
  • 19
  • 136
  • 170
  • 1
    sorry it doesn't seem to work...I still getting this message: name 'BrokenCristal, is not defined – user497457 Nov 25 '10 at 17:31
  • This isn't actually working for me in Python 2.7. It seems to modify the globals, but then when I leave the scope, the globals revert to what they were previously. – Translunar Jan 28 '16 at 15:32
  • Thank you, it actually works for Python 2.7.17, at least I could pickle and unpickle a namedtuple, which was dynamically created in other module (and I added it to globals there). – Yaroslav Nikitenko Feb 20 '20 at 15:16
8

Instead of a dynamic global variable, use a dict:

movies = {}

a = 'BrokenCristals'

movies[a] = movieClass.shot()
movies[a].set_name(a)
# etc
Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • sorry but I still having the same problem, when I try get values from the BrokenCristals shot class instance from any other method I get this message: name 'BrokenCristals' is not defined....any idea? – user497457 Nov 25 '10 at 17:31
  • try `movies['BrokenCristals'].get_name()`, for example. You don't have a variable named BrokenCristals. You have a dict named `movies` with a key of `'BrokenCristals'`. – Ned Batchelder Nov 25 '10 at 18:31
  • thanks a lot both for the answer and your patience with a newbie like me :-D – user497457 Nov 26 '10 at 22:24
2

The global keyword specifies that a variable you're using in one scope actually belongs to the outer scope. Since you do not have nested scopes in your example, global doesn't know what you're trying to do. See Using global variables in a function other than the one that created them

Community
  • 1
  • 1
robert
  • 33,242
  • 8
  • 53
  • 74
0

Your code works fine!

It was just a spelling mistake and missing brackets!

First syntax error there are no square brackets:

  File "main.py", line 6
    global BrokenCristals
    ^
SyntaxError: name 'BrokenCristals' is assigned to before global declaration

Second syntax error there is no letter s on the end of global:

  File "main.py", line 6
    global [BrokenCristals]
           ^
SyntaxError: invalid syntax

Corrected syntax:

def creatingShotInstance():

    import movieClass

    BrokenCristals = movieClass.shot()
    globals [BrokenCristals]
    BrokenCristals.set_name('BrokenCristals')
    BrokenCristals.set_description('Both characters goes through a big glass\nand break it')
    BrokenCristals.set_length(500)
    Fight._shots.append(BrokenCristals)

def accesingShotInstance():
    import movieClass

    return BrokenCristals.get_name()

Corrected syntax using declared string:

def creatingShotInstance():

    import movieClass

    a = 'BrokenCristals'

    vars()[a] = movieClass.shot()
    globals [a] 
    eval(a+".set_name('"+a+"')")
    eval(a+".set_description('Both characters goes through a big glass\nand break it')")
    eval(a+".set_length(500)")
    Fight._shots.append(vars()[a])

def accesingShotInstance():
    import movieClass

    return BrokenCristals.get_name()
mOmOney
  • 333
  • 3
  • 5