6

How can I assign a function argument to a global variable with the exact same name?

Note: I can't do self.myVariable = myVariable because my function is not inside of a class.

When write the following code, I get an error saying that "argument is both local and global."

myVar = 1
def myFunction(myVar):
    global myVar

Is this impossible? and if so is it uncommon in other languages? Coming from java I'm used to this.myVar = myVar

Edit I already know that I can rename the variable. That's the easy way out.

4 Answers 4

7

Best solution: refactor your code. Rename something, or use an object with object properties instead of a global variable.

Alternative, hacky solution: modify the global variable dict directly:

my_var = 1
def my_function(my_var):
    globals()['my_var'] = my_var
Sign up to request clarification or add additional context in comments.

Comments

1

The answer is to trick Python into doing it. In your code:

myVar = 1
def myFunction(myVar):
    global myVar

myFunction is never run (you never call it). So, the script never gets to the global myVar point. Yet, Python still blows up for some reason. I believe that that is because it has been told "Don't allow this". Regardless, you can trick it into doing what you want. One way that hasn't been suggested is to use a simple function in myFunction:

myVar = 1
def myFunction(myVar):
    def trick(arg):
        global myVar
        myVar = arg
    trick(myVar)

print myVar # Comes back with 1
myFunction(22)
print myVar # Comes back with 22

May not be on one line, but you don't have to import anything and it is easier to read.

2 Comments

thats the cleanest solution yet and it would work nicely with 20+ arguments like I need, any reason to use this over globals()?
@Stephan: Well, I can't see any technical reasons why. They do the same things at heart. However, it is a lost easier to read and maintain. Also, being how Python gives you a global keyword, it seems more Pythonic (at least to me) to use that rather than the globals built-in (which can also be redefined).
1

The best (and fastest) thing to do would be to take the easy way out and rename the variable(s). But if you insist, you could get around the naming conflict with this:

import sys
_global = sys.modules[__name__]
# or _globals = sys.modules[__name__].__dict__

myVar = 1
def myFunction(myVar):
    _global.myVar = myVar  # or _globals['myVar'] = myVar

print myVar  # 1
myFunction(42)
print myVar  # 42

Explanation:

Within a module, the module’s name (as a string) is available as the value of the global variable__name__. The namesys.modulesrefers to a dictionary that maps module names to modules which have already been loaded. IfmyFunction()is running, its module has been loaded, so at that timesys.modules[__name__]is the module it was defined within. Since the global variableMyVaris also defined in the module, it can be accessed using sys.modules[__name__].myVar. (To make its usage similar to java, you could name itthis-- but personally I think_globalis a better.)

In addition, since a module’s read-only__dict__attribute is its namespace -- aka the global namespace -- represented as a dictionary object,sys.modules[__name__].__dict__ is another valid way to refer to it.

Note that in either case, new global variables will be created if assignments to non-existent names are made -- just like they would be with the global keyword.

4 Comments

can you explain sys.modules[__name__]?
What about assigning the global: my_var = 1 and then using a class attribute: class MyClass: my_var = my_var. It works! :-D
@Stephan, sys.modules[__name__] is just a reference and look up. sys provides a map of all imported modules in modules. __name__ is a magic constant that always contains the name of the current module. sys.modules[__name__] therefore always refers to the current module in execution. All variables defined in a module are available as attributes of the module, just like variables defined in a class are available as attributes of a class. sys.modules[__name__].myVar is therefore the attribute in question. Use __dict__ if you don't know the name of the variable in advance.
@martineau, why not use globals()? As in def myFunction(myVar): globals()["myVar"] = 42. Then you can dispense with _global.
0

Alternatively you could simply use a setter

myVar = 1
def myFunction(myVar):
    set_my_var(myVar)

def set_my_var(value):
    global myVar
    myVar = value

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.