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)
Related
I have a function that returns different values based on different inputs.
I want it to go through a list, spitting out results for each input. But then I don't know how to store each of those results as a unique variable...
Here's an example of the list
list = ["input1", "input2", "input3"]
The function returns a different integer depending on the input.
I'm going through the list with a for loop like so
for input in list:
my_function(input)
The function in the loop runs for each item in the list and returns a unique integer for each. But how do I store each of the returned values as their own variable?
I've tried this. But it overwrites the variable each time and only leaves me with the last one in the loop
for input in list:
var = my_function(input)
Is there some way to dynamically change that variable in each run through the loop?
vars = []
for input in list:
vars.append(my_function(input))
or
vars = [my_function(input) for input in list]
or the dictionary approach
vars = {}
for input in list:
vars[input] = my_function(input)
or the inline
vars = {input: my_function(input) for input in list}
I'd like to know why you're trying to achieve what you're trying to achieve, it sounds like a terrible idea, what you want seems to be another list or dictionary.
With that being said, I wouldn't recommend it but this snippet of code might do the trick.
ctr = 0
def my_function(inp):
return f"RETURN VAL OF MY FUNCTION FOR INPUT {inp}"
lst = ["input1", "input2", "input3"]
for i in lst:
exec(f'var{ctr+1} = "{my_function(i)}"')
ctr+=1
print(var1)
print(var2)
l1 is a list that stores all inputs every time you call your function until the loop stops
l1 = []
for input in list:
l1.append(my_function(input))
I would like to change the word consolidation (two times in the following string) with an other value with a variable or ? (ex. breakout/outofconsolidation/inside)
Can I help me to achieve this, please?
dfconsolidationcsv.to_csv(r'symbols\stocks_consolidation_sp500.csv', index = False)
a = ('breakout')
df{a}csv.to_csv(r'symbols\stocks_{a}_sp500.csv', index = False)
Unless there is a justifiable reason to be creating dynamic variable assignments, I would avoid doing so. In this case, defining your DataFrame variables in a dict is probably sufficient:
# store df in a dict instead of separate variables
df_dict = dict()
df_dict['consolidation'] = dfconslidationcv
df_dict['breakout'] = dfbreakoutcv
...
# invoke command for a specific variable
a = 'breakout'
df_dict[a].to_csv(r'symbols\stocks_%s_sp500.csv' % a, index = False)
Now, if there is an overwhelming reason why you HAVE to use pre-existing variable names that need to be changed dynamically, I think you can do something like this:
a = 'breakout'
exec("df%scsv.to_csv(r'symbols\stocks_%s_sp500.csv', index=False)" % (a, a))
In Python 3, is there a way to concatenate a string/variable to a(nother) variable?
Say I have a some variables with similar names (for simplicity sake, they are variable; in actuality, I want to do it with class & objects):
var1 = 'Hello'
var2 = 'Greetings'
The user inputs a number, and the script prints using else if statements:
choice = input("Please select a number (1-2) >")
if choice = 1:
print(var1)
elif choice = 2:
print(var2)
But what I want to do is print directly without having to use else if/ switch statements/dictionaries etc. I want it so it prints(var+choice), where choice would concatenate to var, so if choice = 1, it would be print(var1); and if choice = 3, it would print(var3) (which would give an error, undefined variable).
If there isn't a way to do this, what is the cleanest way to print a choice of variables that have similar names?
In this particular case may use a list of variables and then simply print the indexed variable.
var = ['Hello', 'Greetings']
...
print(var[choice-1]) # since python is 0-indexed
Not a good practice, but you can use eval:
print(eval('var'+str(choice)))
Using globals() to dynamically get variable values
The globals function returns a dictionary of variables in module scope so you could get var1 or var2 with
selected_greeting = globals()[f"var{choice}"]
See the linked docs for caveats on which variables you'll have access to.
Further reading: getattr will let you dynamically get variable values of other objects.
Using a dict or list
We end up accessing var1 and var2 through a dict, so if your program allows you could use a dict or list anyway
# A dict example
# Note: I'm using var1 and var2 here for continuity only.
# Give a more descriptive key if you want
greetings = {
"var1": "hello",
"var2": "greetings",
}
selected_greeting = greetings[f"var{choice}"]
# A list example
greetings = ["hello", "greetings"]
selected_greeting = greetings[int(choice) - 1] # Cast to int, input gives us strings. Also subtract 1 because lists are zero indexed
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.
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