Pythonic way to update multiple class variables in a loop? - python

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)

Related

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

How to change original variable

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

Cant add variables to a class?

Ok, so i'm really starting to get annoyed at this. I can't seem to figure out what it is? Some are saying it is indentation but i've tried that.
Here is my code:
class player(object):
def __init__(self):
self.nation_name = None
self.race = None
self.name = None
self.special_unit = None
self.special_unitsize = 0
self.regular_army = 50
self.army_size = special_unitsize +regular_army
self.army_power = 250
self.IceColdCoins = 0
self.gold = 100
self.taxincome = 45
self.mineincome = 0
self.recruitrate = 30
self.totalincome = taxincome + mineincome
self.num_of_mines = 1
self.num_of_towns = 0
self.num_of_cities = 1
self.num_of_fort = 0
self.wait_till_upgrade = 0
And every time I try to add any type of variable it doesn't allow it saying:
attribute error (example) is not defined.
I did a test and well same error. Copy code and add a variable and make an if statement about the variable it won't work.
You forget to use self:
self.taxincome = 45
self.mineincome = 0
self.totalincome = taxincome + mineincome # there is no 'taxincome', etc.
The first two lines do not make taxincome and mineincome variables in the local (or global) namespace, but attributes of self:
self.taxincome = 45
self.mineincome = 0
self.totalincome = self.taxincome + self.mineincome # note the 'self'
The same goes for special_unitsize and regular_army.

Update an attribute each time the class constructor is invoked

I have this class in Python. (Removed the unecessary parts)
class Spillebrett:
def __init__(self, rader, kolonner):
self._rader = rader
self._kolonner = kolonner
self._generasjonsnummer = 0
I need to add 1 to _generasjonsnummer everytime i run the class. If i try _generasjonsnummer += 1 i get an error. I tried to make a def addGenerasjonsnummer() and call it in the init like so:
class Spillebrett:
def __init__(self, rader, kolonner):
self._rader = rader
self._kolonner = kolonner
self._generasjonsnummer = 0
addGenerasjonsnummer()
def addGenerasjonsnummer():
self._generasjonsnummer += 1
But i cant call on functions in the init. What i need is for this number to update to +=1 each time i start the init, how do i do this?
If your class has an attribute that is going to be incremented each time the constructor is called, then you should disassociate it with any instance to begin with. In other words, declare it as a class attribute, outside __init__.
I'd recommend something along these lines:
In [625]: class Spillebrett:
...: ctr = 0
...: def __init__(self):
...: print(Spillebrett.ctr)
...: Spillebrett.ctr += 1
...:
In [626]: Spillebrett()
0
Out[626]: <__main__.Spillebrett at 0x10b918da0>
In [627]: Spillebrett()
1
Out[627]: <__main__.Spillebrett at 0x109f1af98>
In [628]: Spillebrett()
2
Out[628]: <__main__.Spillebrett at 0x10b918470>

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