declaring a global dynamic variable in python - python

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?

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'

Instead of a dynamic global variable, use a dict:
movies = {}
a = 'BrokenCristals'
movies[a] = movieClass.shot()
movies[a].set_name(a)
# etc

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

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()

Related

New to using functions in Python

I am trying to understand why newNameList is not defined:
ListofNames1 = ['Mark', 'Andrew']
ListofNames2 = ['Anjela', 'Lora']
names = ListofNames1
def greeting(names):
newNameList = []
for item in names:
newNameList.append(str(names))
return (names)
print(greeting(names))
def function2(newNameList):
for each in newNameList:
newNameList2.append(newNameList.upper())
return (newNameList2)
print(function2(newNameList))
The output
['Mark', 'Andrew']
...
NameError: name 'newNameList' is not defined.
The name error occurs on the last line in the code.
newNameList is only defined within the scope of function2. Since the print statement is not indented at the same level of function2 then newNameList is not visible to it. The three variables defined at a top-level scope are ListofNames1, ListofNames1, and names. These are the only three variables that can be passed to function2 in the print statement.
Yes, You can do it.
For example:
def use_greeting_function(name):
new_list_name = greeting(name)
Now new_list_name has the output of greeting function and you can use it in the function afterwards.
NameError: name 'newNameList' is not defined.
tells you what's wrong. You should have defined newNameList outside the greetings() function.
I have rewritten your code:
ListofNames1 = ['Mark', 'Andrew']
ListofNames2 = ['Anjela', 'Lora']
names = ListofNames1
newNameList = []
def greeting(names):
for item in names:
newNameList.append(names)
return names
print(greeting(names))
def function2(newNameList):
newNameList2 = []
for each in newNameList:
newNameList2.append(str(newNameList).upper())
return newNameList2
print(function2(newNameList))
And using the upper() method on a list doesn't work. Convert it to str first.

How do you initialize a global variable only when its not defined?

I have a global dictionary variable that will be used in a function that gets called multiple times. I don't have control of when the function is called, or a scope outside of the function I'm writing. I need to initialize the variable only if its not initialized. Once initialized, I will add values to it.
global dict
if dict is None:
dict = {}
dict[lldb.thread.GetThreadID()] = dict[lldb.thread.GetThreadID()] + 1
Unfortunately, I get
NameError: global name 'dict' is not defined
I understand that I should define the variable, but since this code is called multiple times, by just saying dict = {} I would be RE-defining the variable every time the code is called, unless I can somehow check if it's not defined, and only define it then.
Catching the error:
try:
_ = myDict
except NameError:
global myDict
myDict = {}
IMPORTANT NOTE:
Do NOT use dict or any other built-in type as a variable name.
A more idiomatic way to do this is to set the name ahead of time to a sentinel value and then check against that:
_my_dict = None
...
def increment_thing():
global _my_dict
if _my_dict is None:
_my_dict = {}
thread_id = lldb.thread.GetThreadID()
_my_dict[thread_id] = _my_dict.get(thread_id, 0) + 1
Note, I don't know anything about lldb -- but if it is using python threads, you might be better off using a threading.local:
import threading
# Thread local storage
_tls = threading.local()
def increment_thing():
counter = getattr(_tls, 'counter', 0)
_tls.counter = counter + 1

How to call an arraylist from a function to another function in python?

Say for example I got the code:
def getRoute(getRouteFile):
getRoutePath = []
routeFile = open(getRouteFile, "r")
for routes in routeFile:
getRoutePath.append(map(ord, routes.split('>')))
return getRoutePath
If I do a function such as which would try and call the items in the getRoutePath array from a function called:
def routeCalculation(getRoute,nodeTable, currentNode):
How do I call it? I tried doing these:
def routeCalculation(getRoute,nodeTable, currentNode):
route = getRoutePath
def routeCalculation(getRoute,nodeTable, currentNode):
route = getRoute[getRouthPath]
And none seem to work. Can anyone help me?
Whenever you declare a variable in a function, when you exit the function, the variable is destroyed. Example:
a = ""
def function():
a = "hello"
b = "hello"
print(a) #prints "hello" because a was declared outside of the function
print(b) #does not print anything
This is called "scope", and if you have a problem understanding it, you should search up a tutorial about it. In order to fix your problem move the code getRoutePath = [] outside of your functions.

How can I use external variables in Python like 'extern int x;' in C?

How can I use external variables in Python, like extern int x; in C?
For example,
main1.py:
from myfunc import print_a
a = 10
print a
print_a()
myfunc.py:
def print_a():
global a
print a
Simply re-assign the variable in the module:
import myfunc
from myfunc import print_a
a = 10
print a
myfunc.a = a
print_a()
Otherwise it is not possible.
Rememeber that python treats modules in a way that is quite different from C.
The import in python does not "copy the contents" of the file in that place,
but it executes the code in the given file and creates a module object.
The global variable of the module are the module object attributes, which can be modified as I've shown. There is no such notion as "global variable" except for built-ins.
I'd suggest to refactor your code in such a way that you don't have to modify this global variable at all, moving the code that uses myfunc.a from main1 to myfunc.
The fact that you need such global variable is already a code smell that there's something wrong with your code and you should try to fix it.
Actually there is a way to affect the "global scope" but it is so hackish that I don't even want to mention it. Trust me: you don't want to use it. If people see your code using such a hack you may be in physical danger.
Unlike C, variables declared at global scope are still limited in scope to the module they are created in, so you need to qualify the name a with the module it lives in.
The global keyword is used when you are going to modify a global variable by reassigning, you do not need it when you are just referencing a global variable.
If you are trying to access a variable of another file, you must import that module, and because of the way your files are structured you have a couple of ways to resolve issues:
Option 1) Move the referencing of myfunc.print_a inside of a function and import main1 inside myfunc to see a
main1.py
import myfunc
a = 10
def main():
print a
myfunc.print_a()
if __name__ == '__main__':
main()
myfunc.py
import main1
def print_a():
print main1.a
Option 2) recommended Move the variable(s) into another module and have both myfunc and main1 import it.
vals.py
a = 20
main1.py
import vals
from myfunc import print_a
vals.a = 10
print vals.a
print_a()
myfunc.py
import vals
def print_a():
print vals.a
This is a workaround to this problem by using a common external file. In this example I am storing an index variable to flag in each application whether a file is being accessed. The variable indxOpen in ext1.py and indxO in ext2.py are being updated and stored in a common external text file "externalVars.txt"
lead application ext1.py
# lead application ext1.py
#this alternately flips the value of indxOpen on prime number intervals
import time
def update(d,v1):
f=open(d+'externalVars.txt','r+')
f.write(str( v1))
f.truncate()
f.close()
# ensure variable is initialised and made available to external apps
indxOpen = False
var_dir = "<your external var directory>/"
try:
f =open(var_dir+'externalVars.txt','r')
except:
f= open(var_dir+'externalVars.txt','w')
f.close()
# this alternately flips the value of indxOpen on prime number intervals
update(var_dir,indxOpen)
i = 0
while True:
while indxOpen:
i += 1
if (i % 13) ==0:
indxOpen = indxOpen ^ True
update(var_dir,indxOpen)
f=open(var_dir+'externalVars.txt','r+')
t=f.readline()
print "app1",t," ",i
if t=='False':
print "app1 updated"
update(var_dir,indxOpen)
indxOpen = False
else:
time.sleep(1.4)
while not indxOpen:
f=open(var_dir+"externalVars.txt","r+")
t=f.readline()
print "app1",t
if t=='True':
indxOpen = True
else:
time.sleep(1)
ext2.py following application
# ext2.py this alternately flips the value of indxO on prime number intervals but it is initialised by the lead application
# in this case ext1.py
# python 2.7.12
import time
def update(d,v1):
f=open(d+'externalVars.txt','r+')
f.write(str( v1))
f.truncate()
f.close()
var_dir = "<your external var directory>/"
# intialise external variable
f=open(var_dir+'externalVars.txt','r+')
t=f.readline()
if t=='True':
indxO= True
if t=='False':
indxO= False
i=0
while True:
while indxO:
f=open(var_dir+"externalVars.txt","r+")
t=f.readline()
print "app2",t
if t=='False':
indxO = False
update(var_dir,indxO)
else:
time.sleep(1.5)
while not indxO:
i += 1
if (i % 17) ==0:
indxO = indxO ^ True
update(var_dir,indxO)
f=open(var_dir+"externalVars.txt","r+")
t=f.readline()
print "app2",t," ",i
if t=='True':
indxO = True
print "apt2 updated"
update(var_dir,indxO)
else:
time.sleep(1.3)

How to refer to the local module in Python?

Let's say we have a module m:
var = None
def get_var():
return var
def set_var(v):
var = v
This will not work as expected, because set_var() will not store v in the module-wide var. It will create a local variable var instead.
So I need a way of referring the module m from within set_var(), which itself is a member of module m. How should I do this?
def set_var(v):
global var
var = v
The global keyword will allow you to change global variables from within in a function.
As Jeffrey Aylesworth's answer shows, you don't actually need a reference to the local module to achieve the OP's aim. The global keyword can achieve this aim.
However for the sake of answering the OP title, How to refer to the local module in Python?:
import sys
var = None
def set_var(v):
sys.modules[__name__].var = v
def get_var():
return var
As a follow up to Jeffrey's answer, I would like to add that, in Python 3, you can more generally access a variable from the closest enclosing scope:
def set_local_var():
var = None
def set_var(v):
nonlocal var
var = v
return (var, set_var)
# Test:
(my_var, my_set) = set_local_var()
print my_var # None
my_set(3)
print my_var # Should now be 3
(Caveat: I have not tested this, as I don't have Python 3.)

Categories