3

Context: I'm making a Ren'py game. The value is Character(). Yes, I know this is a dumb idea outside of this context.

I need to create a variable from an input string inside of a class that exists outside of the class' scope:

class Test:
    def __init__(self):
        self.dict = {} # used elsewhere to give the inputs for the function below.

    def create_global_var(self, variable, value):
        # the equivalent of exec("global {0}; {0} = {1}".format(str(variable), str(value)))
        # other functions in the class that require this.

Test().create_global_var("abc", "123") # hence abc = 123

I have tried vars()[], globals()[variable] = value, etc, and they simply do not work (they don't even define anything) Edit: this was my problem.

I know that the following would work equally as well, but I want the variables in the correct scope:

setattr(self.__class__, variable, value) # d.abc = 123, now. but incorrect scope.

How can I create a variable in the global scope from within a class, using a string as the variable name, without using attributes or exec in python?

And yes, i'll be sanity checking.

7
  • If you say that this is a "dumb idea", why not think of a better one? Commented Nov 9, 2012 at 15:35
  • 1
    I say it merely because of similar questions I have seen asked that result in 20 answers that do not answer the original question, and merely say how much of a bad idea it is Commented Nov 9, 2012 at 15:36
  • Perhaps you should take a step back and start by explaining why you think you would need or want to do this. You're more likely to get a helpful answer that way. Commented Nov 9, 2012 at 15:38
  • If a group of experienced programmers respond by saying something is a bad idea, then that advice should be taken on board as constructive criticism and not simply dismissed. Commented Nov 9, 2012 at 15:40
  • 1
    @Hiroto That's fine, but you can't assume people know that. I've seen Ren'Py before, but I don't know how it's implemented, for example. Commented Nov 9, 2012 at 16:41

2 Answers 2

7

First things first: what we call the "global" scope in Python is actually the "module" scope (on the good side, it diminishes the "evils" of using global vars).

Then, for creating a global var dynamically, although I still can't see why that would be better than using a module-level dictionary, just do:

globals()[variable] = value

This creates a variable in the current module. If you need to create a module variable on the module from which the method was called, you can peek at the globals dictionary from the caller frame using:

from inspect import currentframe
currentframe(1).f_globals[variable] = name

Now, the this seems especially useless since you may create a variable with a dynamic name, but you can't access it dynamically (unless using the globals dictionary again)

Even in your test example, you create the "abc" variable passing the method a string, but then you have to access it by using a hardcoded "abc" - the language itself is designed to discourage this (hence the difference to Javascript, where array indexes and object attributes are interchangeable, while in Python you have distinct Mapping objects)

My suggestion is that you use a module-level explicit dictionary and create all your dynamic variables as key/value pairs there:

names = {}
class Test(object):
    def __init__(self):
        self.dict = {} # used elsewhere to give the inputs for the function below.

    def create_global_var(self, variable, value):
         names[variable] = value

(on a side note, in Python 2 always inherit your classes from "object")

Sign up to request clarification or add additional context in comments.

5 Comments

OP claimed this wasn't working for them. But it should: >>> class A(object): ... def foo(self, bar): ... globals()['foo'] = bar ... >>> A().foo('asdf') >>> foo 'asdf'
oddly, when i first tried this, it didn't work. I tried again, and it does indeed work. then again, I'm using a custom interpreter running inside a game engine, hence the odd need for this.
@Iguananaut: It might not work due to the __main__ gotcha. The module can be available via different names. globals() refers to the module the function is defined in i.e., globals() inside mod.func() refer to mod variables.
the actual need for the dynamic names is because the Character() variables and options are read from a file, and then globally defined for use in gameplay.
@J.F.Sebastian Ah good point; that's exactly what was going on with my example.
2

You can use setattr(__builtins__, 'abc', '123') for this.

Do mind you that this is most likely a design problem and you should rethink the design.

1 Comment

You shouldn't touch __builtins__, it is CPython implementation detail.

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.