List of empty variables in Python - python

Is there any possibility of creating a list of variables/names* that have not been defined yet, and then loop through the list at a later stage to define them?
Like this:
varList = [varA, varB, varC]
for var in varList:
var = 0
print(varList)
>>>[0, 0, 0]
The reason I'm asking is because I have a project where I could hypothetically batch fill 40+ variables/names* this way by looping through a Pandas series*. Unfortunately Python doesn't seem to allow undefined variables in a list.
Does anyone have a creative workaround?
EDIT: Since you asked for the specific problem, here goes:
I have a Pandas series that looks like this (excuse the Swedish):
print(Elanv)
>>>
Förb. KVV PTP 5653,021978
Förb. KVV Skogsflis 0
Förb. KVV Återvinningsflis 337,1416119
Förb. KVV Eo1 6,1
Förb. HVC Återvinningsflis 1848
Name: Elanv, dtype: object
I want to store each value in this array to a set of new variables/names*, the names of which I want to control. For example, I want the new variable/name* containing the first value to be called "förbKVVptp", the second one "förbKVVsflis", and so forth.
The "normal" option is to assign each variable manually, like this:
förbKVVptp, förbKVVsflis, förbKVVåflis = Elanv.iloc[0], Elanv.iloc[1], Elanv.iloc[2] ....
But that creates a not so nice looking long bunch of code just to name variables/names*. Instead I thought I could do something like this (obviously with all the variables/names*, not just the first three) which looks and feels cleaner:
varList = [förbKVVptp, förbKVVsflis, förbKVVåflis]
for i, var in enumerate(varList): var = Elanv.iloc[i]
print(varList)
>>>[5653,021978, 0, 337,1416119]
Obviously this becomes pointless if I have to write the name of my new variables/names* twice (first to define them, then to put them inside the varList) so that was why I asked.

You cannot create uninitialized variables in python. Python doesn't really have variables, it has names referring to values. An uninitialized variable would be a name that doesn't refer to a value - so basically just a string:
varList = ['förbKVVptp', 'förbKVVsflis', 'förbKVVåflis']
You can turn these strings into variables by associating them with a value. One of the ways to do that is via globals:
for i, varname in enumerate(varList):
globals()[varname] = Elanv.iloc[i]
However, dynamically creating variables like this is often a code smell. Consider storing the values in a dictionary or list instead:
my_vars_dict = {
'förbKVVptp': Elanv.iloc[0],
'förbKVVsflis': Elanv.iloc[1],
'förbKVVåflis': Elanv.iloc[2]
}
my_vars_list = [Elanv.iloc[0], Elanv.iloc[1], Elanv.iloc[2]]
See also How do I create a variable number of variables?.

The answer to your question is that you can not have undefined variables in a list.
My solution is specific to solving this part of your problem The reason I'm asking is that I have a project where I could hypothetically batch fill over 100 arrays this way by looping through a Pandas array.
Below solution prefills the list with None and then you can change the values in the list.
Code:
varList = [None]*3
for i in range(len(varList)):
varList[i] = 0
print(varList)
Output:
[0, 0, 0]

So something you are trying to do in your example that won't do what you expect, is how you are trying to modify the list:
for var in varList:
var = 0
When you do var = 0, it won't change the list, nor the values of varA, varB, varC (if they were defined.)
Similarly, the following won't change the value of the list. It will just change the value of var.
var = mylist[0]
var = 1
To change the value of the list, you need to do an assignment expression on an indexed item on the list:
mylist = [None, None, None]
for i in range(len(mylist)):
mylist[i] = 0
print(mylist)
Note that by creating a list with empty slots before assigning the value is inefficient and not pythonic. A better way would be to just iterate through the source values, and append them to a list, or even better, use a list comprehension.

Related

Python assign list values into a new variables separately

Output = ['1)', 'JP', '*00000.0000/UNT', 0.07704, 61628.21, '0%(E)', 0.0, 'ND']
I have split my list item as above and would like to assign each value into separate variable something like below:
var1 = '1)'
var2 = 'JP'
.......
How can I accomplish it using for loop without need to manually specify how many variables are needed. In my example contains only 7 values, but in reality it could be less or more.
Don't assign each value to new variable. It will make things complicated. Just create a dictionary and work with key-value pairs, like below:
d={var1 : '1)', var2 : 'JP', .......}
and you can call them by d['var1'], d['var2'], etc whenever you want to use them
There are some possible solutions.
You can access list elements directly: Output[0] or Output[3]
It is possible to define variables programmatically in python, you can read more about it here: Programmatically creating variables in Python. But keep in mind that it is very bad practice so you probably don't want to use it.
Looks like best way to solve this is to use dictionary comprehensions:
output = ['1)', 'JP', '*00000.0000/UNT', 0.07704, 61628.21, '0%(E)', 0.0, 'ND']
result = {f"var{index}": value for index, value in enumerate(output)}
print(result['var0']) # 1)
print(result['var1']) # JP
You can read more about dictionary comprehensions here: https://www.programiz.com/python-programming/dictionary-comprehension.
It will works with lists of any length. Also, notice, f"" string are working with Python 3.8+ so if you are using older version, replace it with "".format. More about string formatting here: https://realpython.com/python-string-formatting/
I'm really don't understand why you want to do that and suggest you to reconsider, but you can try the following.
It's a bad practise!
class MyVariables():
def create_variables(self, vars: list):
for i, value in enumerate(vars, 1):
setattr(self, f"var{i}", value)
c = MyVariables()
output = ['1)', 'JP', '*00000.0000/UNT', 0.07704, 61628.21, '0%(E)', 0.0, 'ND']
c.create_variables(output)
print(c.var1)
>> 1)

Python references to references in python

I have a function that takes given initial conditions for a set of variables and puts the result into another global variable. For example, let's say two of these variables is x and y. Note that x and y must be global variables (because it is too messy/inconvenient to be passing large amounts of references between many functions).
x = 1
y = 2
def myFunction():
global x,y,solution
print(x)
< some code that evaluates using a while loop >
solution = <the result from many iterations of the while loop>
I want to see how the result changes given a change in the initial condition of x and y (and other variables). For flexibility and scalability, I want to do something like this:
varSet = {'genericName0':x, 'genericName1':y} # Dict contains all variables that I wish to alter initial conditions for
R = list(range(10))
for r in R:
varSet['genericName0'] = r #This doesn't work the way I want...
myFunction()
Such that the 'print' line in 'myFunction' outputs the values 0,1,2,...,9 on successive calls.
So basically I'm asking how do you map a key to a value, where the value isn't a standard data type (like an int) but is instead a reference to another value? And having done that, how do you reference that value?
If it's not possible to do it the way I intend: What is the best way to change the value of any given variable by changing the name (of the variable that you wish to set) only?
I'm using Python 3.4, so would prefer a solution that works for Python 3.
EDIT: Fixed up minor syntax problems.
EDIT2: I think maybe a clearer way to ask my question is this:
Consider that you have two dictionaries, one which contains round objects and the other contains fruit. Members of one dictionary can also belong to the other (apples are fruit and round). Now consider that you have the key 'apple' in both dictionaries, and the value refers to the number of apples. When updating the number of apples in one set, you want this number to also transfer to the round objects dictionary, under the key 'apple' without manually updating the dictionary yourself. What's the most pythonic way to handle this?
Instead of making x and y global variables with a separate dictionary to refer to them, make the dictionary directly contain "x" and "y" as keys.
varSet = {'x': 1, 'y': 2}
Then, in your code, whenever you want to refer to these parameters, use varSet['x'] and varSet['y']. When you want to update them use varSet['x'] = newValue and so on. This way the dictionary will always be "up to date" and you don't need to store references to anything.
we are going to take an example of fruits as given in your 2nd edit:
def set_round_val(fruit_dict,round_dict):
fruit_set = set(fruit_dict)
round_set = set(round_dict)
common_set = fruit_set.intersection(round_set) # get common key
for key in common_set:
round_dict[key] = fruit_dict[key] # set modified value in round_dict
return round_dict
fruit_dict = {'apple':34,'orange':30,'mango':20}
round_dict = {'bamboo':10,'apple':34,'orange':20} # values can even be same as fruit_dict
for r in range(1,10):
fruit_set['apple'] = r
round_dict = set_round_val(fruit_dict,round_dict)
print round_dict
Hope this helps.
From what I've gathered from the responses from #BrenBarn and #ebarr, this is the best way to go about the problem (and directly answer EDIT2).
Create a class which encapsulates the common variable:
class Count:
__init__(self,value):
self.value = value
Create the instance of that class:
import Count
no_of_apples = Count.Count(1)
no_of_tennis_balls = Count.Count(5)
no_of_bananas = Count.Count(7)
Create dictionaries with the common variable in both of them:
round = {'tennis_ball':no_of_tennis_balls,'apple':no_of_apples}
fruit = {'banana':no_of_bananas,'apple':no_of_apples}
print(round['apple'].value) #prints 1
fruit['apple'].value = 2
print(round['apple'].value) #prints 2

how to increase variable name in Python?

I'm making a simulation program.
I manually write some initial conditions of particles with python list before starting program, such as
var1 = [mass_a, velocity_a, velocity_a]
var2 = [mass_b, velocity_b, velocity_b]
...
then how do I change that number in variable in for loop? Something I tried was
for i in range(2):
print(var+str(i))
but they don't work
Always remember
If you ever have to name variables suffixed by numbers as in your example, you should consider a sequential indexable data structure like array or list. In Python to create a List we do
var = [[mass_a, velocity_a, velocity_a],
[mass_b, velocity_b, velocity_b]]
If you ever have to name variables with varying suffixes like
var_A=[mass_a, velocity_a, velocity_a]
var_B=[mass_b, velocity_b, velocity_b]
you should consider a non-sequential indexable data structure like hashmap or dictionary. The key of this dictionary should be the varying suffix and the values should be the values assigned to the respective variable In Python to create a dictionary we do
var = {'A':[mass_a, velocity_a, velocity_a],
'B':[mass_b, velocity_b, velocity_b]}
Just to be the devil's advocate here, you can make this approach work as below.
for i in range(2):
print( globals()["var"+str(i+1)] )
You can put your variables in a list and iterate on it like,
var_list = [var_a,var_b...]
for var in var_list:
print var
Alternatively, you can put the your variables in a dictionary like,
var_dict = {"var_a":var_a,"var_b":var_b,...}
for var in var_dict:
print var_dict(var)
Could you put your variables var1, var2, ... into a list and iterate through the list, instead of relying upon numbered variable names?
Example:
vars = [var1, var2]
for var in vars:
do_something(var)

Updating dictionary with randint performing unexpectedly

I'm trying to run a simple program in which I'm trying to run random.randint() in a loop to update a dictionary value but it seems to be working incorrectly. It always seems to be generating the same value.
The program so far is given below. I'm trying to create a uniformly distributed population, but I'm unsure why this isn't working.
import random
__author__ = 'navin'
namelist={
"person1":{"age":23,"region":1},
"person2":{"age":24,"region":2},
"person3":{"age":25,"region":0}
}
def testfunction():
default_val={"age":23,"region":1}
for i in xrange(100):
namelist[i]=default_val
for index in namelist:
x = random.randint(0, 2)
namelist[index]['region']=x
print namelist
if __name__ == "__main__" :
testfunction()
I'm expecting the 103 people to be roughly uniformly distributed across region 0-2, but I'm getting everyone in region 0.
Any idea why this is happening? Have I incorrectly used randint?
It is because all your 100 dictionary entries created in the for loop refer to not only the same value, but the same object. Thus there are only 4 distinct dictionaries at all as the values - the 3 created initially and the fourth one that you add 100 times with keys 0-99.
This can be demonstrated with the id() function that returns distinct integer for each distinct object:
from collections import Counter
...
ids = [ id(i) for i in namelist.values() ]
print Counter(ids)
results in:
Counter({139830514626640: 100, 139830514505160: 1,
139830514504880: 1, 139830514505440: 1})
To get distinct dictionaries, you need to copy the default value:
namelist[i] = default_val.copy()
Or create a new dictionary on each loop
namelist[i] = {"age": 23, "region": 1}
default_val={"age":23,"region":1}
for i in xrange(100):
namelist[i]=default_val
This doesn't mean "set every entry to a dictionary with these particular age and region values". This means "set every entry to this particular dictionary object".
for index in namelist:
x = random.randint(0, 2)
namelist[index]['region']=x
Since every object in namelist is really the same dictionary, all modifications in this loop happen to the same dictionary, and the last value of x wipes the others.
Evaluating a dict literal creates a new dict; assignment does not. If you want to make a new dictionary each time, put the dict literal in the loop:
for i in xrange(100):
namelist[i]={"age":23,"region":1}
Wanted to add this as a comment but the link is too long. As others have said you have just shared the reference to the dictionary, if you want to see the visualisation you can check it out on Python Tutor it should help you grok what's happening.

Python - efficient way to create 20 variables?

I need to create 20 variables in Python. That variables are all needed, they should initially be empty strings and the empty strings will later be replaced with other strings. I cann not create the variables as needed when they are needed because I also have some if/else statements that need to check whether the variables are still empty or already equal to other strings.
Instead of writing
variable_a = ''
variable_b = ''
....
I thought at something like
list = ['a', 'b']
for item in list:
exec("'variable_'+item+' = '''")
This code does not lead to an error, but still is does not do what I would expect - the variables are not created with the names "variable_1" and so on.
Where is my mistake?
Thanks, Woodpicker
Where is my mistake?
There are possibly three mistakes. The first is that 'variable_' + 'a' obviously isn't equal to 'variable_1'. The second is the quoting in the argument to exec. Do
for x in list:
exec("variable_%s = ''" % x)
to get variable_a etc.
The third mistake is that you're not using a list or dict for this. Just do
variable = dict((x, '') for x in list)
then get the contents of "variable" a with variable['a']. Don't fight the language. Use it.
I have the same question as others (of not using a list or hash), but if you need , you can try this:
for i in xrange(1,20):
locals()['variable_%s' %i] = ''
Im assuming you would just need this in the local scope. Refer to the manual for more information on locals
never used it, but something like this may work:
liste = ['a', 'b']
for item in liste:
locals()[item] = ''

Categories