How to change original variable - python

I am trying to change variable using new_variable
variable = 10
new_variable = variable
new_variable += 1
print(new_variable)
print(variable)
I see that new_variable has changed while variable has not.
Is there a way to modify the value of variable using new_variable?

You can use class objects to get this behaviour.
class num:
def __init__(self,n):
self.n = n
variable= num(5)
newvariable = variable
newvariable.n = 3
print(variable.n)
print(newvariable.n)
Or you can use lists for the same
variable= [5]
newvariable = variable
newvariable[0] = 3
print(variable[0])
print(newvariable[0])
OUTPUT
3
3

Related

Global scope ok with 2 variables but 3rd with identical treatment produces error

I'm working on learning tkinter but running into a problem with variable scope. In the code below 3 variables are declared global: bid, maxscore, and flg. None are declared global inside the function. Two work just fine but the third does not.
*When the 1st entry loses focus and val_1 (the callback routine) is entered, the values bid and maxscore have the values initially assigned but the variable flg produces the error: "UnboundLocalError: local variable 'flg' referenced before assignment". Yet it has been assigned exactly as the other two variables have. All 3 are treated equally. The print statement was added to confirm the values on entry. When the print statement does not contain "flg" I find the correct values for bid and max_*scores and "flg" errors out on the if statement. Put "flg" in the print statement and it blows up there. I must be violating the scope somehow but darned if I can see it.
Can anyone see what's happening ?
The Code:
import os
from tkinter import *
import tkinter.ttk as ttk
from tkinter import messagebox
global bid
global max_score
global flg
max_score = 25
bid = 20
flg = False
root = Tk()
f1_txt = StringVar()
f2_txt = StringVar()
def setup():
field_1.config(textvariable=f1_txt, validate='focusout', validatecommand=val_1)
field_2.config(textvariable=f2_txt, validate='focusout', validatecommand=val_2)
return
def val_1():
print (bid, max_score, flg)
if flg :
return True
else:
flg = True
s1 = int(f1_txt.get())
s2 = max_score - s1
if s1 < bid:
messagebox.showinfo("UH-OH","Looks like someone went up !!")
s1 = 0-bid
f1_txt.set(str(s1))
f2_txt.set(str(s2))
flg = False
return True
def val_2():
pass
root.geometry('300x300+20+20')
field_1 = ttk.Entry(root,width = 5)
field_1.grid(row = 0, column = 1, pady = 30, padx = 15)
field_2 = ttk.Entry(root,width = 5)
field_2.grid(row = 0, column = 2, pady = 30, padx = 15)
field_1.focus_set()
setup()
root.mainloop()
Variables assigned in a function or method are assumed to be local. You assign flg = True in the function so its a local variable. The others are merely referenced, so they are assumed to be global. The global keyword is used inside a function to change this rule for that one function only. Saying global bid at module level is meaningless - its a puzzle why this doesn't raise an error. It is only useful within a function to change a variable's assumed scope.

defining a variable in a class [duplicate]

This question already has answers here:
How can I access "static" class variables within methods?
(6 answers)
Closed 2 years ago.
I am trying to place a method in a class that will replace null values with running average of non null values. Please refer to the code below:
class ElNinoData(object):
# Your implementation here
add = 0
counter = 0
average = 0
# methods
def __init__(self , object):
self.object = object
def get_humidity(self):
if not math.isnan(self.object['humidity']):
global add
global counter
global average
add += self.object['humidity']
counter += 1
average = add/counter
else:
self.object['humidity'] = average
return self.object['humidity']
While executing this class in a method, I am getting the following error:
<ipython-input-40-c52c3ac6484b> in get_humidity(self)
19 global average
20
---> 21 add += self.object['humidity']
22 counter += 1
23 average = add/counter
NameError: name 'add' is not defined
Could anyone please explain the error,I am relatively new to python?
class ElNinoData(object):
add = 0
The add here is not a global variable,
global add
therefore this does not give access to it, but instead looks for that actual global.
add += self.object['humidity']
+= requires the variable to exist already (so that the old value can be added to), and you don't have a global add, nor a local one - you have a class attribute.
To access it directly, you can use ElNinoData.add, just as you would from code outside the class. Similarly for the other class attributes.
Looking up the class attribute via the instance - self.add - also succeeds. However, modifying the value then attaches a separate attribute to the instance, and leaves the class attribute unaffected.
If you want the members to be specific to an object, change it to this
class ElNinoData(object):
# Nothing here
# methods
def __init__(self , object):
self.add = 0
self.counter = 0
self.average = 0
self.object = object
and continue to refer to them with self..
If you want them to be class-wide, leave them where they are, but refer to them via ElNinoData..
In any case, you shouldn't use global here.
I think the problem is that your values add, counter and average are not global.
In order to set these values on your class instance, you have to use self instead.
Something like this:
def get_humidity(self):
if not math.isnan(self.object['humidity']):
self.add += self.object['humidity']
self.counter += 1
self.average = add/counter
else:
self.object['humidity'] = average
return self.object['humidity']
What you are missing here is that you have initialized the variables but not given them any values and then you are adding the values using +=, due to which python is throwing you this error.
Refer to the below code:-
class ElNinoData(object):
# Your implementation here
add = 0
counter = 0
average = 0
# methods
def __init__(self , object):
self.object = object
def get_humidity(self):
if not math.isnan(self.object['humidity']):
global add
global counter
global average
add = 0
counter = 1
add += self.object['humidity']
counter += 1
average = add/counter
else:
self.object['humidity'] = average
return self.object['humidity']
t = {'humidity' : 10}
a =ElNinoData(t)
a.get_humidity()

Pythonic way to update multiple class variables in a loop?

I would like to update class variables with similar names in a loop:
I have the following code:
class Table:
def __init__(self):
pass
acc_counter = 0
acc0 = 0
acc1 = 0
acc2 = 0
acc3 = 0
acc4 = 0
I could update each value manually:
Table.acc0 = 0
Table.acc1 = 1
Table.acc2 = 2
Table.acc3 = 3
Table.acc4 = 4
However, I'm wondering if I could do it in a loop, something like that:
for i in range(5):
print(getattr(Table, f"acc{i}"))
#getattr(Table, f"acc{i}") = i
If the last line of the code is uncommented it returns: "SyntaxError: can't assign to function call"
You can use the setattr function:
for i in range(5):
setattr(Table, f"acc{i}", i)
Use setattr to set the object's attribute value
for i in range(5):
print(getattr(Table, f"acc{i}"))
setattr(Table, f"acc{i}", i)

Understanding variable scope in nested functions in Python

I have the following functions in Python3.7
def output_report():
sheet_dict = {1: 'All', 2: 'Wind', 3: 'Soalr'}
sheet_name = sheet_dict[sheet_num]
file_name = f'{file_name}_{sheet_name}_row_{row_num}.csv' if row_num else
f'{file_name}_{sheet_name}.csv'
return file_name
def test_file(x):
file_name = output_report(sheet_num)
return f'{x}_{file_name}'
def good_func():
sheet_num = 2
row_num = 2
a = test_file('new file')
return a
when I call: good_func()
It raises an error that:
NameError: name 'sheet_num' is not defined
But if I define sheet_name and row_num in the global scope like,
sheet_num = 2
row_num = 2
def good_func():
a = test_file('new file')
return a
the code works.
My question: My understanding was that in nested functions, the inner functions starts looking for the variables from itself and then goes to outer functions and finally to the global scope. Then, I expected the first function also runs, but that's not the case. What is that?
I read other scope related questions but didn't find my answer.
In your first case
def good_func():
sheet_num = 2
row_num = 2
a = test_file('new file')
return a
sheet_num and row_num are local to the function good_func and hence cannot be accessed in another function output_report
But when you do
sheet_num = 2
row_num = 2
def good_func():
a = test_file('new file')
return a
sheet_num and row_num become global variables accessible to all other functions, hence they are accessible in output_report as well
Also nested function are functions whose definition lies within another function like so, where a is accessible in inner
def outer():
a = 1
def inner():
print(a)
inner()
outer()
Calling another function inside a function like you do in good_func doesn't make them output_function nested.

Python how to reference variable

I'm getting a problem when referencing variables on a python file. Here is the code:
FG_E = 9
FG_R = 8
START = 7
READY = 9
MC = 3
BRAKE = 5
ERROR = 6
a = 2
b = 3
position = 0
def build_message(signal):
message = position
message = message | (0b1<<signal)
s = bin(message)
s = s[2:len(s)]
s = (16-len(s))*'0' + s
s0 = s[0:len(s)/2]
s1 = s[len(s)/2:len(s)]
s0 = s0[::-1]
s1 = s1[::-1]
s_final = int(s0 + s1, 2)
position = s_final
print bin(s_final)
return s_final
build_message(FG_R)
The error I get is:
UnboundLocalError: local variable 'position' referenced berofe assigment
The problematic line is actually position = s_final in the function build_message.
If it wasn't there then message = position would work because the Python interpreter would know to which position variable you are referring.
But in this case it is ambiguous because you're are later reassigning to position (position = s_final).
You should either re think the design of the code, or add global position as the first line in build_message. Keep in mind that as it says, it would make position a global variable and build_message will change the value of position every where throughout your code.
EDIT A quick demo:
global_var = 0
def foo1():
print(global_var)
def foo2():
print(global_var)
global_var = 1
def foo3():
global global_var
print(global_var)
global_var = 1
print(global_var)
foo1()
>> 0
foo2()
>> UnboundLocalError: local variable 'global_var' referenced before assignment
foo3()
>> 0
1
You need to use global keyword to access global variable.
def build_message(signal):
global position
message = position
If you are using an outside variable into a function maybe you should consider passing it as an argument, like:
def build_message(signal,position):
pass

Categories

Resources