3

Most people will probably say this is a bad idea. I want to use the content of a string as the name of a variable. I want to accomplish the dreaded:

s = 'x'
x = 1

where the variable name x comes (somehow?) from the string s.

To answer the "why?", say I have a global default value for x that I want the option of overriding in a function. But:

x = 0
def f(**kw):
    print x
f(x=1)

prints 0 not 1. If I could use the strings in kw.keys() to reassign x (or any other globally set variables) then I'd be happy.

I realize that this works for reassigning x in f:

x = 0
def f(x=x):
    print x
f(x=1)

But I want to do this for cases where there are MANY variables in my namespace that I might at some point want to override without rewriting every function definition in my module.

1
  • 2
    Why not keep a dict of these "global" state variables? Commented Feb 8, 2013 at 1:09

6 Answers 6

5

Check out exec

>>> print x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> s = 'x'
>>> exec(s + " = 1")
>>> print x
1 

See also: How can I assign the value of a variable using eval in python?

After a little experimentation, this also seems to work:

>>> print x
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> s = 'x'
>>> globals()[s] = 1
>>> print x
1
Sign up to request clarification or add additional context in comments.

4 Comments

There is almost never a reason to use eval or exec. You can use getattr or setattr instead, in this case.
For my own learning, how would you use setattr in this context?
Your edited answer is one way to directly set a global variable. But I usually reserve globals for constant (read-only) values that are truly global. If you need to keep state then use a class and instance variables.
@JesseVogt Thanks for the direct answer to the original question. I appreciate the other posts saying that exec is a bad thing to rely on, but it's good to know it's there in a bind.
1

You should reconsider using the global keyword (http://docs.python.org/2.7/reference/simple_stmts.html#the-global-statement)

I recommend taking a look at Use of "global" keyword in Python as well.

Also, as promanow suggested, using a global mutable object might be a better approach.

However, keep in mind that having large amounts of code that might modify or depend on a mutating global is very scary idea, from a maintenance perspective. Tread carefully.

Comments

1

Assignment via function arguments is not obvious and therefore is not considered Pythonic (Python is not C). See import this.

The cheap way that I've done flat configuration is through a global partial dict:

In [1]: from functools import partial
In [2]: config = partial(dict)
In [3]: def f(x=None):
   ...:     print x or config.x
   ...:     
In [4]: config.x = 'foo'
In [5]: f()
foo

Something to this effect is obvious, readable and therefore much more maintainable.

Comments

1

But I want to do this for cases where there are MANY variables in my namespace that I might at some point want to override without rewriting every function definition in my module.

It sounds like you want a class:

class Foo(object):
    x = 0
    def f(self):
        print self.x

my_foo = Foo()
my_foo.x = 1
my_foo.f()

1 Comment

I'm sure you're right that this is the best big picture answer. I know I need to learn how to use classes in my code. So considering that I'm doing all this in a module that has a lot of different interacting functions, then I guess I should just wrap all these related functions in a class to have more control of the parameters they all share. I guess that would avoid or at least help with the problem of all these functions having to pass parameters back and forth.
0

I use the following for creating dynamically custom modeling databses for targets of interest from one global database:

DBs = ["Target_1_DB","Target_2_DB","Target_3_DB"]

for db in DBs:
    print(db)    
    exec_str = "Modeling_DB_Base = " + db
    exec(exec_str)
    #s = "Modeling_DB_Base"
    #globals()[s] = db
    print(Modeling_DB_Base.shape)

using the commented-out globals() results in error message: AttributeError: 'str' object has no attribute 'shape'

Comments

-3

You can use the following solution:

s = 'x'
locals()[s] = 1

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.