Perform function on many variables - python

I have many variables I want to perform the same function on. The return value of the function should be saved in a variable with the the letter m appended to it. I'm currently using a dictionary but I'm having trouble converting the key value pair to a variable name with that pair. I'm listing my approach below and I'm opening to either appending/adding on to this method or using a better method all together
A=4
B=5
C=6
listletter = {'mA':A,'mB':B,'mC':C}
for key in listletter :
listletter[key]=performfunc(listletter[key])
Note that I do not want to use the dictionary to reference values. My actual use of the variables is in numpy and they're is already alot of indexing going on
and the lines are long. I therefore want distinct variable names as opposed to dict['variablename'][][]...
I am aware of the exec function but I here this is bad convention. I'd also appreciate any general advice on simple improvements unrelated to the task(perhaps I should use key, value instead?).
EDIT: I would also be okay with simply performing the function on the variables but not appending the letter m to it. I want to perform the same function on a, b and c. The function would return the new values of a,b and c. Once again I ultimately want to access the variables as a,b & c and not through a dictionary

You should be able to use locals() to convert all local variables into a dictionary then prepend m to them in your resulting dictionary.
res = {}
for key, value in locals().items():
res["m"+key] = somefunc(value)

I am not sure how many variables you have. If you have a handful then this should work.
a,b,c,d = 31,21,311,11
print("original values: ", a,b,c,d)
#replace the lambda function with whatever function that you want to use.
a,b,c,d = map(lambda x:x**2,(a,b,c,d))
print("changed values,same variables: ", a,b,c,d)

Related

When splitting data to a hash data structure, what is the syntax for multiple assignment?

I am going through the "Head First" Learn to Program text for python 2.7, and as I was working through one of the exercises. It gave me a clue to multiple assign a line of data while splitting it. And since I could not guess it, I went to the solution, and I do not understand the solution.
I am running the latest python in the native IDLE
line = "101;Johnny 'wave-boy' Jones;USA;8.32;Fish;21"
display = {}
(display['ID'], display['Name'], display['Country'], display['Average'], display['Board'], display['Age']) = line.split(';')
I do not understand what is going on with the multiple assignments in the code above. How is the splitting making key and value pairs?
What role are the braces playing in this?
When I guessed for multiple assignments I imagined this:
(ID, Name, Country, Average, Board, Age) = line.split(;)
for a, b, c, d, e, f in line:
display[ID] = Name, Country, Average, Board, Age
I thought that I could assign several values to one key, and just index or iterate the has with the keys() or items() method.
I am also going through the 'Head First Programming' book and I also didn't understand the multiple assignment technique so I went through the solution and I understood it. Let me explain it to you:
A hash data structure keeps the data in the key: value pair. It is called dictionary in Python language and is created using the curly braces - {}
If you read the section before the exercise it is given that when assigning a key: value to hash we use this code-
scores = {}
scores["joseph"] = 8.45
we put the key inside the square brackets of the scores variable(which is a hash data structure) and on the right hand side we put the value which is 8.45.
The same mechanism is used in the multiple assignment technique.
We know that the line.split(";") method will give us 6 values so we
put 6 keys[multiple assignment] on the left hand-side using the mechanism in the above code
(display['ID'], display['Name'], display['Country'],
display['Average'],display['Board'], display['Age']) = line.split(';')
and then the 6 values on the right hand side go to their respective key: value pairs
line.split(';') # gives 6 values
REMEMBER: When you want to assign key: value pairs then you put the key in the square brackets inside the scores variable(hash data structure)scores['Joseph'] = 8.45...
but when you have to refer to the value associated to the key you write this:
print(scores[key]) # this gives you the value in the key: value pair
print(ID) # this gives you the key in the key: value pair
The braces are a dictionary. This dictionary is called display.
The line is divided up by the semicolon into parts, and these parts are in turn assigned as values to a key in the display dictionary. For example, this first assignment is 101.
display = {}
display['ID'] = '101` # first part of `line`
In the code snippet in your question, could be simplified as something like the following:
display['first'], display['second'] = ['A', 'B']
Here is a list of values (A and B) is each being assigned to keys (first and second) in the display dictionary. Note: you can not assign several "things" to one key; rather KEY and VALUE are a pair. You may iterate over a collection of "things" assigning values to various keys.
You could assign the values if there are in a list. This would work for instance:
for ID, Name, Country, Average, Board, Age in lines:
display[ID] = [ Name, Country, Average, Board, Age ]

How to iterate over dict keys when assigning values to multiple variables

I have a multi-dim dict with primary key being a hash and sub values keyed on single chars. I'm trying to assign a subset of values to multiple vars by iterating over a string containing the chars of the sub-keys I want. Something like:
A,B,C = tree[hash][i] for i in "xyz"
This would equate to:
A = tree[hash]["x"]
B = tree[hash]["y"]
C = tree[hash]["z"]
But trying to do it all in a single line, possibly to imbed in a function where I would pass the list of vars and the corresponding string of sub-keys.
You have nearly done that. Just add square brackets around right side expression. It's called list comprehension:
A, B, C = [tree[hash][i] for i in "xyz"]
tree[hash][i] for i in "xyz" is already a generator comprehension, but it needs to be parenthesized unless it's passed as sole argument of a function like this:
my_function(tree[hash][i] for i in "xyz") # this is valid
my_function(tree[hash][i] for i in "xyz", 12) # this is invalid, parsing conflict
my_function((tree[hash][i] for i in "xyz"), 12) # this is valid
This is the same with your assignment expression. The parentheses are needed to avoid ambiguity when parsing.
this answer solves the issue, but is creating an unnecessary list when a generator comprehension is enough:
A, B, C = (tree[hash][i] for i in "xyz")
Unpacking assigns left hand variables by iterating on the generator comprehension without creating an unnecessary list.
Also maybe avoid hashing 3 times, use a variable
h = tree[hash]
A, B, C = (h[i] for i in "xyz")
variant with map and operator.itemgetter to avoid loops:
import operator
A,B,C = map(operator.itemgetter(tree[hash]),"xyz")
Aside: avoid hash as a variable name, since it's the built-in function to hash objects.

can this code be written in two lines?

I have a feeling that using the setdefault method or lamda that this code can be written in two lines:
variables = ['a','b','c','d']
for value in indefinite_dict.values():
str1 = immediate_instantiation.get(value)
if str1 == None:
immediate_instantiation.update({value:variables[0]})
del variables[0]
It loops through the values of the indefinite_dict and puts them in and if that value is not already a key in the immediate instantiation dict then it adds that as an entry into that dict with a value of the first member of the variables list and deletes the first member of the variables list.
If you’re okay with values in variables being deleted even if a corresponding key already exists in immediate_instantiation when that key has the same value, you’re right that you can do it with only setdefault:
for value in indefinite_dict.values():
if immediate_instantiation.setdefault(value, variables[0]) is variables[0]:
del variables[0]
To get it down to two lines without any other context takes a different (and kind of unpleasant) approach, though:
updates = (v for v in indefinite_dict.values() if v not in immediate_instantiation)
immediate_instantiation.update({v: variables.pop(0) for v in updates})
And indefinite_dict had better be an OrderedDict – otherwise you’re removing variables in a potentially random order! (Don’t rely on Python 3.6’s dict representation for this.)
If you don’t need variables after this and variables is guaranteed to be at least as long as updates, a non-mutating solution is much cleaner, note:
updates = (v for v in indefinite_dict.values() if v not in immediate_instantiation)
immediate_instantiation.update(zip(updates, variables))
One line solution:
immediate_instantiation.update({value: variables.pop(0) for value in indefinite_dict.values() if value not in immediate_instantiation})

I have two lists. One of variable names one of initial values. I need to combine them so they can be used in function evaluation

I have three lists imported from a.csv file variable names, initial values, and constraints.
variables = [x1,x2,x3]
and a list of initial values
intialvalues = [1,2,5]
and a third list of constraints
constraints = ['x1+x2', 'x2-x3']
I am looking for a way to break the lists into variables so that the constraints can be evaluated using eval().
EDIT: Example .csv file
Varible Names,Initial Values,Constraints
x1,1,x1+x2
x2,2,x2-x1
x3,3,x3+x2
,,x1+x3
The column names are obviously discarded while reading.
Well, you can declare your variables within the namespace, but modifying globals() and using eval() is really a terrible thing to do, so take this only as an example.
variables = ['x1','x2','x3']
intialvalues = [1,2,5]
for var, val in zip(variables, intialvalues):
globals()[var] = val
constraints = ['x1+x2', 'x2-x3']
for c in map(eval, constraints):
print(c)
# 3
# -3

python: proper use of dictionaries

i try to create a function, which generates random int-values and after a value appeared twice the function should return the number of all generated int-values.
I have to use a dictionary.
This is my code so far:
def repeat(a,b):
dict={}
d=b-a+2
for c in range(1,d):
dict['c']=random.randint(a,b)
for f in dict:
if dict['f']==dict['c']:
return c
First problem: It doesn't work.
>>> repeat(1,5)
Traceback (most recent call last):
File "<pyshell#144>", line 1, in <module>
repeat(1,5)
File "<pyshell#143>", line 7, in repeat
if dict['f']==dict['c']:
KeyError: 'f'
Second problem: if dict['f']==dict['c']:
Should be true in first step because both values are the same.
I can't find a smart way to compare all values without comparing a key with itself.
Sorry for my bad english, it's kinda rusty and thank you for your time.
Enclosing your variable names in quotes makes them strings - Python is looking for the key of the letter f, not the key with the integer in the f variable.
Simply use the variable normally and it should work as you expected:
def repeat(a, b):
stored = {}
d = b - a + 2
for c in range(1, d):
stored[c] = random.randint(a, b)
for f in stored:
if stored[f] == stored[c]:
return c
Note also that you are shadowing the built-in function dict() by naming your variable dict - it is preferable to use another name because of this.
This isn't really an answer to your question. #Lattyware told you the problem. But I can't put code in a comment so I'm posting this as an answer.
Your code is using weird variable names, which makes the code harder to understand. I suggest you use variable names that help the reader to understand the program.
I've changed your variable names and added comments. I also put in a "doc string" but I don't really understand this function so I didn't actually write a documentation message.
def repeat(a,b): # short names are okay for a,b as they are just two numbers
"""
This is the "doc string". You should put in here a short summary of what the function
does. I won't write one because I don't understand what you are trying to do.
"""
# do not use built-in names from Python as variable names! So don't use "dict"
# I often use "d" as a short name for a dictionary if there is only one dictionary.
# However, I like #Lattyware's name "stored" so I will use it as well.
stored={}
# You only used "d" once, and it's the upper bound of a range; might as well just
# put the upper bound inside the call to range(). If the calculation was really long
# and difficult I might still use the variable, but this calculation is simple.
# I guess you can use "c" in the loop, but usually I use "n" for number if the loop
# is making a series of numbers to use. If it is making a series of indexes I use "i".
for n in range(1,b-a+2):
stored[n]=random.randint(a,b)
# Any for loop that loops over a dictionary is looping over the keys.
for key in stored:
# I don't understand what you are trying to do. This loop will always terminate
# the first time through (when n == 1). The line above this for loop assigns
# a value to stored[n], and n will be equal to 1 on the first loop; then this
# test will trivially succeed.
if stored[key] == stored[n]:
return n

Categories

Resources