Global name v is not defined (but it actually is)? tkinter/python - python

I keep getting this error "global name v is not defined." I know this has most likely been heavily documented, however none of the other threads were very relavant to my GUI situation. Anyway, here we go:
v_amount= 5000
def set_v_to_something_else():
global v
v_amount=v_amount-1000
v.set(v_amount)
v = StringVar()
v.set(str(v_amount))
#create button that will allow v label to be set to something else
vbutton = Button(root, text = "change v", command = set_v_to_something_else).pack()
vlabel = Label(root, textvariable=v).pack()
Once again, it says that v is not defined, even though i set it equal to StringVar()
Thanks in advance

Perhaps you are getting the error
global name v_amount is not defined
That would be because, in this code,
v_amount= 5000
def set_v_to_something_else():
global v
v_amount=v_amount-1000
v.set(v_amount)
when Python parses the function set_v_to_something_else, it marks v_amount as a local variable because it appears on the left-hand side of an assignment:
v_amount=v_amount-1000
Later, when the function is called, since Python regards v_amount as a local variable, it tries to evaluate the right-hand side of the assignment statement first and finds v_amount is not defined. (Remember, it is looking for it in the local namespace, not the global namespace.)
The fix is to add global v_amount inside the function:
def set_v_to_something_else():
global v_amount
v_amount = v_amount-1000
v.set(v_amount)
You can also remove
global v
because you are not assigning a new value to v. v.set is merely calling a method of v.

v_amount= 5000
# you need to define variable 'v' here,
# before you define function that uses it
def set_v_to_something_else():
global v
v_amount=v_amount-1000
v.set(v_amount)
v = StringVar()
v.set(str(v_amount))
#create button that will allow v label to be set to something else
vbutton = Button(root, text = "change v", command = set_v_to_something_else).pack()
vlabel = Label(root, textvariable=v).pack()

Related

Tkinter: Assign Variables with Value with a Button Click

I would like to make a Button that assign a new variable with a value in a compact form.
I tried this:
def whichButton(self, _var, _pressedButton):
self._var = _pressedButton
def checkScooter(self):
self.checkScooter = Button(window, text="Standard", command=lambda: self.whichButton(edition, 1))
self.checkScooter(row=1, column=0)
def checkAbonnement(self):
self.checkAbonnement = Button(window, text="Gold", command=lambda: self.whichButton(abonnement, 3))
self.checkAbonnement(row=1, column=0)
It just gives me an error, that "edition" is not defined, but I want the Button to define it
Any tips?
Your request to set a new variable is odd, and probably not the right solution to whatever problem you're trying to solve.
That being said, you can use setattr to set the value based on the name of a variable. That variable doesn't have to exist. For example, to set the variable self.edition to 1 you can do setattr(self, "edition", 1).
Therefore, you can pass in the string name of the variable to your whichButton function, and use setattr to set a variable with that name.
It would look something like this:
def whichButton(self, _var, _pressedButton):
setattr(self, _var, _pressedButton)
...
self.checkScooter = Button(..., command=lambda: self.whichButton("edition", 1))
...
self.checkAbonnement = Button(..., command=lambda: self.whichButton("abonnement", 3))
In the above code, clicking either button will either set self.edition or self.abonnement.
There is almost certainly a better solution to your problem, but your question doesn't provide any details about what problem you're really trying to solve. A simple mprovement over this would be to use a dictionary to hold your "new" variables rather than creating literally new variables.
You can do that by defining a dictionary in your __init__ and then setting it in your whichButton function.
It would look something like this:
class Something:
def __init__(self):
self._vars = {}
def whichButton(self, name, new_value):
self._vars[name] = new_value
This has the advantage that all of these special variables exist in a single data structure, separate from the object. That means that it would be impossible to accidentally overwrite instance variables.

Is there a way to change a global value from inside a function?

I am currently working an a snake game, but I first want a settings window to show up.i used tkinter for this. In smaller projekts I just wrote all of the code into the pressButton function, but I want to have non spagetti code now, so im not going with that. The problem is, that I have no idea how to get the entered values in the entry brackets into my main code, as global variables, out of the pressButton function and the settingsWin function. The problem is that I use the function as a command for the Button, so I cannt use "return". Can you change global variables in the main code direcktly from inside of a function? If yes how? Or is there another way to solve this?
My Code:
def settingsWin():
def pressButton():
len = entryLen.get()
wid = entryWid.get()
speed = entrySpeed.get()
print(len+wid+speed)
SettingsWin.destroy()
return len
SettingsWin = Tk()
SettingsWin.geometry("600x600")
SettingsWin.title("Settings")
label1 = Label(SettingsWin, text="playing field [tiles]")
label1.pack()
entryLen = Entry(SettingsWin, bd=2, width=20)
entryLen.pack()
label2 = Label(SettingsWin, text="X")
label2.pack()
entryWid = Entry(SettingsWin, bd=2, width=20)
entryWid.pack()
labelblanc = Label(SettingsWin, text="")
labelblanc.pack()
label3 = Label(SettingsWin, text="Speed [ms per tick]")
label3.pack()
entrySpeed = Entry(SettingsWin, bd=2, width="20")
entrySpeed.pack()
okButton = Button(SettingsWin, text="OK", command=pressButton)
okButton.pack()
SettingsWin.mainloop()
len = "len"
wid = "wid"
speed = "speed"
It is often indicative of code smell to require that a function alter variables at scopes outside the function (except possibly in the case of closures, which are quite useful), it is possible to do so using the global keyword:
greeting = "Hello world!"
def greet():
global greeting
greeting = "Goodbye world!"
print(greeting)
greet()
print(greeting)
By declaring the variable greeting to be of global scope, altering the variable within the function definition allows the function to affect the global variable.
If you are working within nested subs, the nonlocal keyword will provide access within the inner sub, to the variable in the outer sub. It works similar to global, except that it is for broader lexical scope, not global scope.

Why is this variable not defined if it is a global variable?

I create a list and try to append it to another list, but even though it is a global list it still is not defined.
I had the same issue trying to apppend a string to another list, and that had the same error so I tried to make the string a list.
sees if the player hits
def hit_or_stand():
global hit **<-- notice hit is a global variable**
if hitStand == ("hit"):
player_hand()
card = deck()
hit = []
hit.append(card)
now I need to append hit to pHand (player's hand)
def player_hand():
global pHand
deck()
pHand = []
pHand.append(card)
deck()
pHand.append(card)
pHand.append(hit) **<--- "NameError: name 'hit' is not defined"**
pHand = (" and ").join(pHand)
return (pHand)
hit_or_stand()
player_hand()
global hit
This does not declare a variable which is global. It does not create a variable which does not exist. It simply says "if you see this name in this scope, assume it's global". To "declare" a global variable, you need to give it a value.
# At the top-level
hit = "Whatever"
# Or in a function
global hit
hit = "Whatever"
The only time you need a global declaration is if you want to assign to a global variable inside a function, as the name could be interpreted as local otherwise. For more on globals, see this question.
There is a misunderstanding of the global operation in OP's post. The global inside a function tells python to use that global variable name within that scope. It doesn't make a variable into a global variable by itself.
# this is already a global variable because it's on the top level
g = ''
# in this function, the global variable g is used
def example1():
global g
g = 'this is a global variable'
# in this function, a local variable g is used within the function scope
def example2():
g = 'this is a local variable'
# confirm the logic
example1()
print( g ) # prints "this is a global variable"
example2()
print( g ) # still prints "this is a global variable"

Python tkinter RadioButton callback function

This comes from a button that when pressed generates a radiobutton. I am not able to access to the choice made with radiobutton. Everything works fine, but the output of selected function is zero. I try using both local and global var but the result is the same.
def callback_st(): # RadioButton select technology
var = IntVar()
m=0
for m in range(len(un_tech)):
Radiobutton(radio_frame, text=un_tech[m], value=m, variable=var,
command=selected(var)).pack(anchor=W)
def selected(var):
print(var)
This doesn't work. I solved using lambda:
def selected(jst):
global sel_technology
sel_technology=un_tech[jst]
print(sel_technology)
def callback_st(): #RadioButton select technology
var_st = IntVar()
m=0
for m in range(len(un_tech)):
Radiobutton(radio_frame, text=un_tech[m], value=m, variable=var_st,
command = lambda jst=m: selected(jst)).pack(anchor=W)
This works as i want, but it isn't the solution that i want and i think is not the correct way. So, somebody can help me to find the right way?
In your first try, you call selected immediately, when var has a value of 0. You avoided this with the lambda expression, but you are correct that this is an awkward workaround for the original mistake. Make var global and have selected access it as a global. Modifying your first code:
var = IntVar()
def selected():
print(var.get())
def callback_st():
...
...command=selected...
If you were defining a class and methods, var would be an instance attribute instead of global.

Return statement not working python 3

The idea of this code is, the user presses the first button and enters what they want, then they press the second button and it prints it out. Can someone please tell me why my return statement is not working? It says that 'variable' is not defined. Thanks in advance for taking the time to read my question.
from tkinter import*
def fun():
variable = input('Enter Here:')
return variable
def fun_2():
print(variable)
window = Tk()
button = Button(text = 'Button', command = fun )
button2 = Button(text = 'Button2', command = fun_2 )
button.pack()
button2.pack()
window.mainloop()
In python when you create a variable inside of a function, it is only defined within that function. Therefore other functions will not be able to see it.
In this case, you will probably want some shared state within an object. Something like:
class MyClass:
def fun(self):
self.variable = input('Enter Here:')
def fun_2(self):
print(self.variable)
mc = MyClass()
window = Tk()
button = Button(text = 'Button', command = mc.fun )
button2 = Button(text = 'Button2', command = mc.fun_2 )
button.pack()
button2.pack()
fun() may return a value, but Tkinter buttons don't do anything with that return value.
Note that I used the phrase return a value, not return a variable. The return statement passes back the value of an expression, not the variable variable here. As such, the variable variable is not made into a global that other functions then can access.
Here, you can make variable a global, and tell fun to set that global:
variable = 'No value set just yet'
def fun():
global variable
variable = input('Enter Here:')
Since you did use any assignment in fun2, variable there is already looked up as a global, and it'll now successfully print the value of variable since it now can find that name.
The problem is in in fun2(). It does not get variable as an input parameter.
def fun_2(variable):
print(variable)
But note that you have to call fun_2 now with the appropriate argument. Also, as the function stands right now, there is little point in having the function if you just do a print inside of it.
Take away message: variable is not global in Python, and as such you must pass it to each function that wants to use it.

Categories