Python - efficient way to create 20 variables? - python

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] = ''

Related

PyCharm thinks variable is not used but clearly is inside class method?

For some reason PyCharm is telling me that 3 of my 5 list are not used in my function but they in fact are being used in the function and the code completes with the expected results.
This is odd behavior. Is this a bug?
I have seen some issues for f-strings reporting false positives but I do not think this is the same issue here.
def filter_for_vzb_vzt(self, query_results):
vzb_list = []
vzt_list = []
vzt_analyst_tkr = []
vzb_analyst_tkr = []
vzb_lpc_analyst_tkr = []
with open('./Files/{}.json'.format('VZT_ACNA_LIST'), 'r') as df:
vzt_analyst_tkr = json.load(df)
with open('./Files/{}.json'.format('VZB_TAX_ACNA_LIST'), 'r') as df:
vzb_analyst_tkr = json.load(df)
with open('./Files/{}.json'.format('VZB_LPC_ACNA_LIST'), 'r') as df:
vzb_lpc_analyst_tkr = json.load(df)
self.process_vzb_mass(vzb_list, vzb_analyst_tkr, vzb_lpc_analyst_tkr)
self.process_vzt_mass(vzt_list, vzt_analyst_tkr)
self.active_time = False
You are indeed not using those values. Read carefully the message:
local variable <...> value is not used
PyCharm is being very specific - you are assigning these three variables a new list with
<...> = json...
The original empty lists that these variables pointed to are then discarded.
These assignments are not conditional, so you will never use those empty lists - PyCharm is warning you you are not using the empty lists, rather than the variables themselves. You should probably just delete those lines - common practice is to first define variables with values that will actually be used.

List of empty variables in 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.

Python list being appended when not (directly) referenced

Okay so this is just a rough bit of code I made when trying to make a Guess Who(TM) for class challenge and I wanted to make a random character generator function (its only a proof of concept and I would expand it complexity later! Please don't judge!). However the character's template feature list seems to be appended every iteration (and so skewing my other loops) when it aught not to. It should be adding an item to the end of each new generated list - not the template. Yet the template variable is not appended to in the code, only a temporary copy is/should be. Here's the code:
tempfeatures = characters = []
for i in range(len(characternames)):
tempfeatures = []
charactername = characternames[random.randint(0,len(characternames)-1)]
characternames.remove(charactername)
a = features
tempfeatures = a
### "Debug bit" ###
print(features)
print("loooooop")
for y in range(len(features)):
print(len(features))
temp = random.randint(0,1)
if temp == 1:
tempfeatures[y][1] = True
else:
tempfeatures[y][1] = False
tempfeatures.append(["Dead",True])
characters.append([charactername,tempfeatures])
print(characters)
Thank you!
Apparently the tempfeature variable is "call by reference" and not "call by value". - thanks python.
So when duplicating lists, one must use this on the end of the variable name
tempfeature = feature[:]
(the [:] bit)
Thanks all for your comments!
This is called a shallow copy, it just referenciates the list to another variable, as seen here:
https://docs.python.org/2/library/copy.html
You need to make and intependent copy, or a deep copy, as: tempfeature = list(feature) so changing tempfeature won't interfere with feature

Syntax Error when creating lists

I'm fairly new to Python and some small experience in programming. I searched other questions but am still not sure what to do. My basic problem is this: I downloaded Python Shell (3.5.2) and I get a syntax error whenever I try to enter "names[]", such as:
>>> names[]
SyntaxError: invalid syntax
>>>
I don't know if I need to import some kind of library, or what I have to do and none of the other questions I've looked up answers something as basic as this. Any help would be appreciated.
You don't declare variables in Python. You just assign values to them. [] is an empty list.
>>> names = []
will create a variable called names and assign an empty list to it.
>>> names.append(1)
will append an integer with value 1 to it.
>>> names
[1]
Python values are strongly typed (you can't call append on an integer), but variables can be assigned new values at any time, and those values don't have to have the same type.
>>> names = 23
>>> names
23
The way you should use a list in python is :
list1 = ['physics', 'chemistry', 1997, 2000]
list2 = [1, 2, 3, 4, 5 ]
list3 = ["a", "b", "c", "d"]
or in your case, if you want an empty list, you could use :
list4 = list()
list5 = []
Python's syntax for declaring an empty list is names = [], not names[]. Once you've declared the list and put some items into it - e.g. names.append('John Smith') - you can then access items in the list using the names[] syntax - names[0] for the first element in the list, for example.
If you're having this kind of trouble with basic language syntax, I strongly recommend working through some exercises in an online course that will introduce you to the basic principles of the language. The CodeAcademy python course is free and has been very helpful for a lot of people I work with who are light users of the language.
you have to declare the variables
a = [] # for list
a = () # for tuple
a = {} # for dictionary
a = "" # for an empty variable

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

Categories