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
Related
I wonder if there is a way to create variables automatically using strings, e.g. I have the following code (which does not work properly in Python):
def function(lst1, string1):
lst2 = 'processed_' + string1
lst2 = [] #here I created a string called lst2, but I want to use the string as the variable name.
for i in range(len(lst1)):
if abs(lst1[i]) >= 0.0001 :
lst2.append(i)
return lst2
function(list1, 'price') # list1 is a list which contains the index for column numbers, e.g., [1,2,3]
function(list1, 'promotion')
function(list1, 'calendar')
I would expect that with the function I would be able to create lists such as processed_price, processed_promotion, and processed_calendar, and the function will return these lists.
However the code above would not work as in Python. I wonder how should I write the code properly to achieve the same goal?
getattr(object, name, [default])
setattr(object, name, value)
To get or set values for a variable named via a string, use one of the above as appropriate. However, any time you use user input, it can be a source of injection attacks — the user could use a name that you did not expect them to use but the name is valid so the user gets access to data they should not have access to.
So it is usually advisable to use the user input as a key into a dictionary you define.
dictionary = {
'apple': 'my_value'
}
dictionary[user_input] = 'their_value'
var = {'hello': 'world', 'good': 'day', 'see': 'you'}
Function:
def func(key):
return newfunc(var[key])
I would like to get something like this: hello = func('hello') = newfunc('world').
varlist = list(var.keys())
for i, variab in enumerate(varlist):
varname = variab
variab = func(varname)
But the problem at last the variables are not defined because the variable variab is overwritten when the next iteration starts. So do I have other ways to code a for loop to define all the variables in the dict?
I know I can keep writing hello = func('hello') and other variables every line but I would like to know if another method is possible.
You may find this article to be a worthwhile read: http://stupidpythonideas.blogspot.com/2013/05/why-you-dont-want-to-dynamically-create.html/
The short answer to the problem is that when you do:
variab = func(varname)
You aren't defining a new variable, you are just defining the value stored in the variable. Variab is static. The name isnt changing. To define a static variable, you use the syntax
globlas()[variablename] = variablevalue
And while this is possible, it begs the question of why? There is pretty much no need to create variables dynamically in this way, and there's a reason why you don't generally see this pattern in programming. The solution? Use a data structure to solve the problem properly.
The article suggests dictionaries, but depending on your data structure you can use classes as well. It depends on the problem you are trying to accomplish.
If you must use dynamically created global variables I would strongly recommend getting past the new to Python stage before doing so. Again, the current code patterns and data structures exist for a reason, and I would discourage willingly avoiding them in favor of a workaround style solution.
Dynamically creating variables can be done, but it is not wise. Maintenance is a nightmare. It would be better to store the functions in a dictionary with the key value being what the dynamically created variable would have been. This should give you an idea of how it can be done:
#!/usr/bin/python
h = {'hello': 'world', 'good': 'day', 'see': 'you' }
def func(v):
def newfunc():
return v
return newfunc
for k,v in h.items():
h[k] = func(v)
a = h['hello']()
b = h['good']()
c = h['see']()
print("a = {}".format(a))
print("b = {}".format(b))
print("c = {}".format(c))
First of all, are those values callable functions or just string values?
If they are some callable functions, something like:
a = {'hello': hello, 'world': world}
It is simple and straight forward:
A = {'hello': hello, 'world': world}
def foo(var):
callback = A.get(var, None)
# You cancheck and raise when the value
# is not a method.
if not callable(callback):
raise
return callback
foo('hello')
You can put the variable, fn pairs in a dict.
Also some comments:
you don't use the index i in the for loop so there is no point in using enumerate.
there is no point renaming variab to varname. If you want to use this name then just use it from the beginning.
you can iterate the dict_keys so there is no need for the varlist = list(var.keys()) line, you can just use for variab in var.keys()...
... actually you don't even need the var.keys(). for key in dictionary iterates through the keys of the dictionary, so you can just use for variab in var.
So something like this would work:
fn_dict = {}
for varname in var:
fn_dict[varname] = func(varname)
At the end of the loop you will have the fn_dict populated with the key, function pairs you want.
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
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)
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] = ''