Iteration over variable names in python? - python

I have a group of variables named k1, k2 k3....k52. They variables are lists/numpy arrays depending on the scenario. Essentially I'd like to perform the same manipulation on them en masse within a loop, but am having trouble ierating over them. Essentially what i'd like is something like this:
for i in arange(0,52):
'k'+ str(i) = log10(eval('k' + str(i)))
Obviously i know the above wont work, but it gives the idea. My actual attempt is this:
for i in arange(0,10):
rate = eval('k' + str(i))
rate = np.array(rate,dtype=float)
rate = log10(rate)
rate.tolist()
vars()[rate] = 'k' + str(i)
(Its changed to a numpy array so i can log it, and then back to a list so i change the variable name back to what it was) Thanks for any help you can provide. I get the feeling this is something quite simple, but its escaping me at the moment.
edit: thanks very much for the answers, i should have explained that I can't really store them a set array, they need to remain as independent variables for reasons i don't really want to go into.

The line:
vars()[rate] = 'k' + str(i)
has to be replaced by:
vars()['k' + str(i)]=rate

If the items are all globals you can use the globals() call to get a mapping, then manipulate them:
g = globals()
for i in arange(0,52):
varname = 'k{}'.format(i)
g[varname] = log10(g[varname])
but you really want to just store all those items in a list or dictionary instead.

Related

Doing calculations while creating a List (in Python)

I'm getting data from an API and storing it on Python dictionary (and then a list of dictionaries).
I need to do calculations (max, sum, divisions...) on the dictionary data to create extra data to add to the same dictionary/list.
My current code looks like this:
stream = whatever (whatever, whatever)
keywords = []
for batch in stream:
for row in batch.results:
max_clicks = max(data_keywords["keywords_clicks"])
weighted_clicks = sum(data_keywords["keywords_weighted"])/sum(data_keywords["keywords_clicks"])
data_keywords = {}
data_keywords["keywords_text"] = row.ad_group_criterion.keyword.text
data_keywords["keywords_clicks"] = row.metrics.clicks
data_keywords["keywords_conversion_rate"] = row.metrics.conversions_from_interactions_rate
data_keywords["keywords_weighted"] = row.metrics.clicks * row.metrics.conversions_from_interactions_rate
data_keywords["etv"] = (data_keywords["keywords_clicks"]/max_clicks*data_keywords["keywords_conversion_rate"])+((1-data_keywords["keywords_clicks"]/max_clicks)*weighted_clicks)
keywords.append(data_keywords)
This doesn't work, it gives UnboundLocalError (local variable 'data_keywords' referenced before assignment). I've tried different options and got different errors.
data_keywords["etv"] is what I want to calculate ("max_clicks", "weighted_clicks" and data_keywords["keywords_weighted"] are intermediate calculations for that)
The main problem is that I need to calculate max and sum for all values inside the dictionary, then do a calculation using that max and sum for each value and then store the results in the dictionary itself.
So I don't know where to put the code to do the calculations (before the dictionary, inside the dictionary, after the dictionary or a mix)
I guess it should be possible, but I'm a Python/programming newbie and can't figure this out.
It's probably not relevant, but in case you are wondering, I'm trying to create a weighted sort (https://moz.com/blog/build-your-own-weighted-sort). And I can't use models/database to store data.
Thanks!
EDIT: Some extra info, in case it helps understand better what I need: The results that the keywords list gives without the calculations is something like this:
[{'keywords_text': 'whatever', 'keywords_clicks': 5, 'keywords_conversion_rate': 6.3}, {'keywords_text': 'whatever2', 'keywords_clicks': 50, 'keywords_conversion_rate': 2.3}, {'keywords_text': 'whatever3', 'keywords_clicks': 20, 'keywords_conversion_rate': 2.0}]
I want basically to add to this keywords list a new key/value of 'etv': 8.5 or whatever for each keyword. That etv should come from the formula that I put on my code (data_keywords["etv"] = ...) but maybe it needs changes to work in Python.
The info from this "original" keywords list comes directly from the API (I don't have that data stored anywhere) and it works perfectly if I just request the info and store it in that list. But when the problems come when I introduce the calculations (specially using sum and max inside a loop I guess).
The UnboundLocalError is because you are trying to access data_keywords["keywords_clicks"] before you have declared data_keywords or set the value for "keywords_clicks".
Also, I think you need to be clearer about what data structure you are trying to create. You mention "a list of dictionaries" which I don't see. Maybe you are trying to create a dictionary of lists, but it looks like you overwrite the dictionary values each time you go through your loop.
adding my response as an answer, as I do not have enough reputation to comment
To get rid of assignment error just move the line data_keywords = {} above max_clicks = max(data_keywords["keywords_clicks"])
Here you are trying to access a local variable before its declaration. The code in this case is trying to access a global variable which doesn't seems to exist.
stream = whatever (whatever, whatever)
keywords = []
for batch in stream:
for row in batch.results:
data_keywords = {}
max_clicks = max(data_keywords["keywords_clicks"])
weighted_clicks = sum(data_keywords["keywords_weighted"])/sum(data_keywords["keywords_clicks"])
data_keywords["keywords_text"] = row.ad_group_criterion.keyword.text
data_keywords["keywords_clicks"] = row.metrics.clicks
data_keywords["keywords_conversion_rate"] = row.metrics.conversions_from_interactions_rate
data_keywords["keywords_weighted"] = row.metrics.clicks * row.metrics.conversions_from_interactions_rate
data_keywords["etv"] = (data_keywords["keywords_clicks"]/max_clicks*data_keywords["keywords_conversion_rate"])+((1-data_keywords["keywords_clicks"]/max_clicks)*weighted_clicks)
keywords.append(data_keywords)
More on that here
You can't refer to elements of the dictionary before you create it. Move those variable assignments down to after you assign the dictionary elements.
for batch in stream:
for row in batch.results:
data_keywords = {}
data_keywords["keywords_text"] = row.ad_group_criterion.keyword.text
data_keywords["keywords_clicks"] = row.metrics.clicks
data_keywords["keywords_conversion_rate"] = row.metrics.conversions_from_interactions_rate
data_keywords["keywords_weighted"] = row.metrics.clicks * row.metrics.conversions_from_interactions_rate
max_clicks = max(data_keywords["keywords_clicks"])
weighted_clicks = sum(data_keywords["keywords_weighted"])/sum(data_keywords["keywords_clicks"])
data_keywords["etv"] = (data_keywords["keywords_clicks"]/max_clicks*data_keywords["keywords_conversion_rate"])+((1-data_keywords["keywords_clicks"]/max_clicks)*weighted_clicks)
keywords.append(data_keywords)

how to unpack specific items of dictionary into variables by using loop

I have some dynamic items in dictionary type. I want to unpack some of them into variables. I want to know some methods by using loop.
I have 'self.params = {}' to store basis and weights. Maybe 10 or 20 b and W, which depend on parameters into class. I want to unpack it into 'W1','W2'.....,'b1','b2'.....I have layer number in 'hidden_dims'
I want to realize some functions like follow false code:
for i in range(hidden_dims):
W(i+1) = self.params['W%s'% str(i+1)]
b(i+1) = self.params['b%s'% str(i+1)]
Then I can get some variables like:'W1','W2'...'Wn'(and n = hidden_dims) and 'b1','b2'...'bn'
can it be realized?
You can create variables dynamically using global(). Something like this:
for i in range(1, hidden_dims + 1):
w = 'W' + str(i)
b = 'b' + str(i)
global()[w] = self.params[w]
global()[b] = self.params[b]
Note: It is not advisable to try and create variables dynamically. For your use case, the use of two lists W[] and b[] seems like a much cleaner way to store the values

Syntax for adding sequential objects to a list

Very beginner question but it is driving me mad. sample1, sample2 etc. are Pygame.mixer.sound objects.
sample_list = []
sample_list.append(sample1)
sample_list.append(sample2)
sample_list.append(sample3)
Is fine, but I want to do that using a for style loop, e.g.
for j in range(1, 3, 1):
sample_list.append(sample + j)
But that is trying to add a number to a sound object so isn't right. I can add the equivalent string by;
for j in range(1, 3, 1):
sample_list.append("sample" + str(j))
But that doesn't refer to the objects I want, just adds those strings.
I've tried must permutations of syntax I can think of but it is still alluding me!
Thanks.
Don't store the objects in variables in the first place; store them directly into a list, and then you will be able to index them by integer.
If the integer identifiers are sparse, use a dict indexed by integer.
I would recommend storing these in a dict to begin with. It is almost the same effect for you to reference by a name, but without the explicit object symbol for each:
samples = {
"sample1": Sample(),
"sample2": Sample()
}
samples['sample3'] = Sample()
This is the preferred approach when you have a dynamic number of objects you are creating and want to be able to grab them by a name later. You can store 100's of these in your dict without cluttering up your namespace.
And later if you are trying to apply this to your loop, you can reference the string names:
for i in xrange(1,4):
sample_list.append(samples["sample" + str(i)])
As a side note another way to get attributes by name when they live on some object is to use getattr. Assume you have this:
class Sampler(object):
pass
sampler = Sampler()
sampler.sample1 = Sample()
sampler.sample2 = Sample()
sampler.sample3 = Sample()
You can then reference by name via: getattr(sampler, "sample1")
Note: As mentioned in comments by #Marcin, if you don't care about having a string identifier to be able to look up your items, and they are just purely sequential by number, you can use this same approach but with a list. It depends on your needs.
It is possible you might want to end up doing something like:
samples = {
"bang1": Sample(),
"bang2": Sample(),
"bang3": Sample(),
"shot1": Sample(),
"shot2": Sample(),
...
}
... Which would then allow you to look up sequential subsets of those sounds.
You can dynamically load variables from the locals() mapping:
for j in range(1, 4):
sample_list.append(locals()["sample" + str(j)])
Generally, you want to avoid such tricks; find other ways to store your sample variables, in a mapping or a list for example.
Looks like the wrong approach, but nevertheless.
sample_list = [eval('sample' + str(i)) for i in range(1, 4)]

getting Python variable name in runtime

This is different from retrieving variable/object name at run time.
2G_Functions={'2G_1':2G_f1,'2G_2':2G_f2}
3G_Functions={'3G_1':3G_f1,'3G_2':3G_f2}
myFunctionMap=[2G_Functions,3G_Functions]
for i in myFunctionMap:
print i.??? "\n"
for j in i:
print str(j)
I want the output look like below.
2G_Functions:
2G_1
2G_2
3G_Functions:
3G_1
3G_2
How can I get the name of dictionary variable in my code?I dont know which I am calling in the loop to know its name beforehand.
Despite the pessimism of the other answers, in this particular case you actually can do what you're asking for if there are no other names names assigned to the objects identified by G2_Functions and G3_Functions (I took the liberty of fixing your names, which are not valid Python identifiers as given.) That being said, this is a terrible, terrible, terrible idea and you should not do it, because it will eventually break and you'll be sad. So don't do it. Ever.
The following is analogous to what you're trying to do:
alpha = {'a': 1, 'b': 2}
beta = {'c': 2, 'd': 4}
gamma = [alpha, beta]
listOfDefinedLocals = list(locals().iteritems())
for x, y in listOfDefinedLocals:
if y is gamma[0]: print "gamma[0] was originally named " + x
if y is gamma[1]: print "gamma[1] was originally named " + x
This will output:
gamma[1] was originally named beta
gamma[0] was originally named alpha
I accept no responsibility for what you do with this information. It's pretty much guaranteed to fail exactly when you need it. I'm not kidding.
You can't. The myFunctionMap list contains the objects, not the name attached to them 2 lines above. BTW, calling a list variable "map" isn't a good practice, maps are usually dictionaries.
You can't start a variable name with a digit, so 2G_Functions and 3G_Functions won't work.
You can sidestep the problem by creating a dictionary with appropriate names
e.g.
myFunctionMap = {
"2G_Functions" : { ... },
"3G_Functions" : { ... },
}
for (name, functions) in myFunctionMap.iteritems():
print name
for func in functions.keys():
print func
In short, you can't.
In longer, it is sort of possible if you poke deep into, I think, the gc module (for the general case) or use locals() and globals()… But it's likely a better idea to simply define the list like this:
myFunctionMap = [ ("someName", someName), … ]
for name, map in myFunctionMap:
print name
…
Try making your list of lists as a list of strings instead:
d2G_Functions={'2G_1':"2G_f1",'2G_2':"2G_f2"}
d3G_Functions={'3G_1':"3G_f1",'3G_2':"3G_f2"}
myFunctions=["2G_Functions","3G_Functions"]
for dict_name in myFunctions:
print dict_name
the_dict = eval("d"+dict_name)
for j in the_dict:
print str(j)
(I changed the name of your original variables since python identifiers cannot begin with a digit)

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