Let me start by saying I completely agree that you should
keep data out of your variable names
but let's pretend you wanted a function like this:
def setglobal(s, x):
# Some kind of eval or exec trick like eval(s+' = '+x) so we end up
# with a global variable whose name is the string s and that has a value of x.
Does it have to be an exec/eval trick?
def setglobal(s, x):
globals()[s] = x
This seems to work:
# Take a symbol name s as a string and a value x and eval(s+' = '+x) to set a
# global variable with name s to value x. For getglobal(s) use eval(s).
def setglobal(s, x):
exec "global "+s+"; "+s+" = "+repr(x) in globals()
Related
This is what I have
TEST_KEY = "test_key"
def get_dict():
return dict(TEST_KEY = "test_value")
print(get_dict())
This will print out {'TEST_KEY': 'test_value'}
but I want it evaluate to {'test_key': 'test_value'}
Is there a way to achieve this, to have python not evaluate TEST_KEY inside the dict function as a literal String but instead as the variable defined earlier?
Very close! But the way you're assigning the key and value is not quite right.
Try changing dict to {} and = to : like below. This will use the variable value as the key.
TEST_KEY = "test_key"
def get_dict():
return {TEST_KEY: "test_value"}
print(get_dict())
I tried to set a global variable in a funktion.
global the variable is set to Kategorie = ''
In one of my function I would like to set it to a other value:
elif methode=='show_select_dialog':
writeLog('Methode: show select dialog', level=xbmc.LOGDEBUG)
dialog = xbmcgui.Dialog()
cats = [__LS__(30120), __LS__(30121), __LS__(30122), __LS__(30123), __LS__(30116)]
ret = dialog.select(__LS__(30011), cats)
if ret == 6:
refreshWidget()
elif 0 <= ret <= 5:
writeLog('%s selected' % (cats[ret]), level=xbmc.LOGDEBUG)
global Kategorie
Kategorie = (cats[ret])
refreshWidget()
If I log the variable Kategorie in function refreshWidget the value is correct (cats[ret]), but after that if the function refreshedWidget is called again the value is gone...
elif methode == 'get_item_serienplaner':
sp_items = refreshWidget()
Once I have changed the variable to cats[ret] I would need it as cats[ret]
You have to declare your var outside your functions and everytime you want to use it inside a function you need to specify the global varName. As i see your global var name at declaration is Kategory and after you use Kategorie.
Python wants to make sure that you really know that you are using global variables by explicitly requiring the global keyword.
To use a global variable within a function you have to explicitly delcare you are using it.
Here a small example:
myGlobalVar= 0
def set_globvar():
global myGlobalVar # Needed to modify global copy of globvar
myGlobalVar = 5
def print_globvar():
print myGlobalVar # No need for global declaration to read value of myGlobalVar
set_globvar()
print_globvar() # Prints 5
in your case I see that you declare that you want to access global Kategorie but you do not declare access to global Kategory. I do not know if this is a simple typo or if they are 2 different variable. In any case you need to write global yourGlobalVariable
Are there really any globals in python? Yes there is a global keyword that allows you to access varibles in file scope. Another way of accessing the variable is to use the import statement. Lets say you have a file named file.py. In order to write to the variable you could. You could access another files variables just as easy.
import file
anyVariable = 42
# ...
def aFunc():
file.anyVarible = file.anyVarible + 1
If this works
x=5
def main():
for globe in locals():
globals().update(locals()[globe])
print x
main()
then why doesn't this?
x=5
def main():
for globe in locals():
globals().update(locals()[globe])
x+=1
print x
main()
The error in the latter statement claims that x is referenced before assignment, however it works in the first example...
In python when you assign a variable the declaration happens automatically.
So when you assign a value to x inside the function, python think that is a new local variable, shadowing the global x.
if you want to assign a value to the global x you can do this:
x=5
def main():
global x
x += 1
print x
main()
You cannot assign a global variable in python without explicitly doing so. By writing x+=1 you are assigning a value to x and are implicitly declaring x as a local variable. But it is not defined and therefore you get an error.
The loop has no actual effect, as the locals dictionary is empty.
If you want to use global variables in Python (which you shouldn't, but that's another matter), you should use the global keyword.
suffixing 1 and 2 your two functions, you can find local names (syntax slightly different in python 2) :
In [7]: main1.__code__.co_varnames
Out[7]: ('globe',)
In [8]: main2.__code__.co_varnames
Out[8]: ('globe', 'x')
So x have different status. In the second case the local x mask the global one, so x=x+1 cause the error, because not yet defined.
From docs :
If a name is bound in a block, it is a local variable of that block, unless declared as nonlocal or global.(...).If a variable is used in a code block but not defined there, it is a free variable.
I would like to create temporary variables visible in a limited scope.
It seems likely to me that you can do this with a "with" statement, and I would think there is a construct that makes it easy to do, but I cannot seem to find it.
I would like something like the following (but it does not work this way of course):
pronunciation = "E_0 g z #_1 m p l"
# ...
with pronunciation.split() as phonemes:
if len(phonemes) > 2 or phonemes[0].startswith('E'):
condition = 1
elif len(phonemes) < 3 and phonemes[-1] == '9r':
condition = 2
So is there a simple way to make this work, using built-ins?
Thanks!
Python creates local variables with function scope (once a name is used it stays alive until the end of the function).
If you really want to limit scope then "del <var>" when you want it explicitly discarded, or create separate function to act as a container for a more limited scope.
You can create a method
def process_pronunciation(pronunciation):
phonemes = pronunciation.split()
if len(phonemes) > 2 or phonemes[0].startswith('E'):
condition = 1
elif len(phonemes) < 3 and phonemes[-1] == '9r':
condition = 2
return condition
When you call the method, the local variable phonemes won't be available in the global namespace.
pronunciation = "E_0 g z #_1 m p l"
condition = process_phonemes(pronunciation)
You could do it with with, but I don't think it's worth the trouble. Basically (in a python function) you have two scopes - global or local, that's it. If you want a symbol to have a lifespan shorter than the function you'll have to delete it afterwards using del. You could define your own context manager to make this happen:
class TempVar:
def __init__(self, loc, name, val):
self.loc = loc
self.name = name
self.val
def __enter__(self):
if self.name in self.loc:
self.old = self.loc[self.name]
self.loc[self.name] = self.val
def __exit__(self, *exc):
if hasattr(self, "old"):
self.loc[self.name] = self.old
else:
del self.loc[self.name]
then you can use it to get a temporary variable:
with TempVar(locals(), "tempVar", 42):
print(tempVar)
The working is that it modifies the dict containing local variables (which is supplied to the constructor via locals()) on entry and restoring it when leaving. Please note that this relies on that modifying the result returned by locals() actually modifies the local namespace - the specification does NOT guarantee this behaviour.
Another (and safer) alternative that was pointed out is that you could define a separate function which would have it's own scope. Remember it's perfectly legal to nest functions. For example:
def outer():
def inner(tempVar):
# here tempVar is in scope
print(tempVar)
inner(tempVar = 42)
# here tempVar is out of scope
with statement does not have its own scope , it uses the surrounding scope (like if the with statement is directly inside the script , and not within any function, it uses global namespace , if the with statement is used inside a function, it uses the function's namespace(scope)).
If you want the statements inside a with block to run in its own local scope, one possible way would be to move the logic to a function , that way the logic would be running in its own scope (and not the surrounding scope of with.
Example -
def function_for_with(f):
#Do something.
with pronunciation.split() as phonemes:
function_for_with(phonemes)
Please note, the above will not stop phonemes from being defined in the surrounding scope.
If you want that as well (move the phonemes into its own scope), you can move the complete with statement inside a function. Example -
def function_with(pronunciation):
with pronunciation.split() as phonemes:
#do stuff
pronunciation = "E_0 g z #_1 m p l"
function_with(pronunciation)
Expanding on #skyking's answer, here's an even more magical implementation of the same idea that reads almost exactly like you wrote. Introducing: the with var statement!1
class var:
def __init__(self, value):
import inspect
self.scope = inspect.currentframe().f_back.f_locals
self.old_vars = set(self.scope.keys())
self.value = value
def __enter__(self):
return self.value
def __exit__(self, type, value, traceback):
for name in set(self.scope.keys()) - self.old_vars:
del self.scope[name]
### Usage:
line = 'a b c'
with var (line.split()) as words:
# Prints "['a', 'b', 'c']"
print(words)
# Causes a NameError
print(words)
It does all the nasty extracting of local variables and names for you! How swell. If you space it quirkily like I did and hide the definition in a from boring_stuff import * statement, you can even pretend var is a keyword to all of your confused co-workers.
[1] If you actually use this, the ghost of a dead parrot will probably haunt you forever. The other answers provide much saner solutions; this one is more of a joke.
I have 2 question regarding global variables:
Why can't I declare a list as a global variable as so: global list_ex = []?
I have already defined a global variable that I am trying to use in a function, but can't:
global column
def fx_foo(cols):
common = set(cols).intersection(set(column)) #Error Here!!
When I try to access column inside the function, I get an error:
NameError: global name 'column' is not defined
You are not using global correctly. You don't need to use it at all.
You need to actually set a global column variable, there is none right now. global does not make the variable available. Just create a global column first:
column = []
then refer to it in your function. That is what the NameError exception is trying to tell you; Python cannot find the global column variable, you didn't assign anything to the name so it doesn't exist.
You only need to use global if you want to assign to a global column in your function:
def somefunction():
global column
column = [1, 2, 3]
Here the global keyword is needed to distinguish column from a local variable in the function.
Compare:
>>> foo = 1
>>> def set_foo():
... foo = 2
...
>>> set_foo()
>>> foo
1
to
>>> foo = 1
>>> def set_foo():
... global foo
... foo = 2
...
>>> set_foo()
>>> foo
2
The first form only set a local variable, the second form set the global variable instead.
The keyword global means you are explicitly using a variable declared outside the scope of a function.
Your variable must be declared normally:
column = []
and declared global in the function that uses it
def fx_foo(cols):
global column
common = set(cols).intersection(set(column))
It is used to allow python to distinguish between new local variables and reused global variables.
this will work :
column =[]
def fx_foo(cols):
global column
common = set(cols).intersection(set(column))
but this will work even without global as column will be considered as nonlocal here
column =[]
def fx_foo(cols):
common = set(cols).intersection(set(column))
I think It is more interesting to assign data to column if You want to display global feature (as You can use column from nonlocals without global declaration if you don't assign anything to it)
column =[]
def fx_foo(cols):
global column
column = set(cols).intersection(set(column))
or
def fx_foo(cols):
column =[]
global column
column = set(cols).intersection(set(column))
Global variables need to be declared global inside of the function not on the outside. A variable declared outside a function is by default global.
Functions don't need to declare a variable as global if they only need to access it. The global declaration is just if you need to modify the global variable.
Therefore, in your case, I suggest that you look into what column actually is when you're passing it to the function, because I think the problem may have something to do with that.