I have a function(x). I have also several dctionaries items that will go as function() argument x. I need to write a dynamic name for x using for loop. In PHP used to be simple, but here I cannot find a simple way. I see posts about creating new dictionaries etc. very complicated. Am I missing something? I thought Python was extra simplistic.
EDIT:
I need this in a dynamic way where a number is replaced with i:
for i in range(1, 100):
function(x1)
I cannot write function(x1), function(x2), function(x3) 99 times. How to incorporate i in a simple way without creating dictionaries or lists etc.
Maybe it is not possible the way I want, because x1, x2, x3, ... x99 are dictionaries and also object and cannot generate their names in a simple way taking x and adding i at the end to make it x1, can I?
EDIT ends.
I need to add i at the end or a dictionary name:
for i in range(1, 100):
z = 'n'+str(i) # or something like this
function(m.''.i) # this is only an attempt, which is incorrect.
As others have pointed out in comments, this is probably an indication that you need to refactor the rest of your code so that the data is passed as a list rather than 99 individual variables.
If you do need to access all the values like this, and they're fields on an object, you can use the getattr() function:
for i in range(1, 100):
z = 'n'+str(i)
function(getattr(m, z))
However, if at all possible, do modify the rest of the code so that the data is in a list or similar.
Related
This is in relation to web scraping, specifically scrapy. I want to be able to iterate an expression to create my items. As an example, lets say I import the item class as "item." In order to then store an item, I would have to code something like:
item['item_name'] = response.xpath('xpath')
My response is actually a function so it actually looks something like:
item['item_name'] = eval(xpath_function(n))
This works perfectly. However, how can I iterate this to create multiple items with different names without having to manually name each one? The code below does not work at all (and I didn't expect it to), but should give you an idea of what I am trying to accomplish:
for n in range(1, 10):
f"item['item_name{n}'] = eval(xpath_function(n))"
Basically trying to create 10 different items names item_name1 - item_name10. Hope that makes sense and I appreciate any help.
If you are just creating keys for your dictionary based on the value of n you could try something like:
for n in range(10):
item['item_name' + str(n+1)] = eval(xpath_function(n+1))
If you need to format the number (e.g. include leading zeros), you could use an f-string rather than concatenating the strings as I did.
[NB your for loop as written will only run from 1 to 9, so I have changed this in my answer.]
I have a dictionary created from a json file. This dictionary has a nested structure and every few weeks additional parameters are added.
I use a script to generate additional copies of the existing parameters when I want multiple "legs" added. So I first add the additional legs. So say I start with 1 leg as my template and I want 10 legs, I will just clone that leg 9 more times and add it to the list.
Then I loop through each of the parameters (called attributes) and have to clone certain elements for each leg that was added so that it has a 1:1 match. I don't care about the content so cloning the first leg value is fine.
So I do the following:
while len(data['attributes']['groupA']['params']['weights']) < legCount:
data['attributes']['groupA']['params']['weights'].append(data['attributes']['groupA']['params']['weights'][0])
while len(data['attributes']['groupB']['paramsGroup']['factors']) < legCount:
data['attributes']['groupB']['paramsGroup']['factors'].append(data['attributes']['groupB']['paramsGroup']['factors'][0])
while len(data['attributes']['groupC']['items']['delta']) < legCount:
data['attributes']['groupC']['items']['delta'].append(data['attributes']['groupC']['items']['delta'][0])
What I'd like to do is make these attributes all strings and just loop through them dynamically so that when I need to add additional ones, I can just paste one string into my list and it works without having another while loop.
So I converted it to this:
attribs = [
"data['attributes']['groupA']['params']['weights']",
"data['attributes']['groupB']['paramsGroup']['factors']",
"data['attributes']['groupC']['items']['delta']",
"data['attributes']['groupD']['xxxx']['yyyy']"
]
for attrib in attribs:
while len(eval(attrib)) < legCount:
eval(attrib).append(eval(attrib)[0])
In this case eval is safe because there is no user input, just a defined list of entries. Tho I wouldn't mind finding an alternative to eval either.
It works up until the last line. I don't think the .append is working on the eval() result. It's not throwing an error.. just not appending to the element.
Any ideas on the best way to handle this?
Not 100% sure this will fix it, but I do notice one thing.
In your above code in your while condition you are accessing:
data['attributes']['groupA']['params']['weights']
then you are appending to
data['attributes']['groupA']['params']['legs']
In your below code it looks like you are appending to 'weights' on the first iteration. However, this doesn't explain the other attributes you are evaluating... just one red flag I noticed.
Actually my code was working. I was just checking the wrong variable. Thanks Me! :)
I'm guessing this will be a really simple problem but I have no solution yet.
I have a long code that does modelling and updates values of variables for optimisation. The code is initially written like this:
init_old(x,y):
return {(k):olddict[k][x][0]*prod[y] for k in realnames}
Q_house=init_old(“Q_house”,"P_house")
Q_car=init_old(“Q_car”,"P_car")
Q_holiday=init_old(“Q_holiday”,"P_holiday")
I already can simplify it a bit with a comprehension:
ListOfExpenses=["house","car","holiday"]
Q_house, Q_car, Q_holiday=[init_old(“Q_”+i,"P0_"+i) for i in ListOfExpenses]
I am trying to find an equivalent but more flexible way of writing that final line, so that I change the list of Expenses and the "Q_..." variables together easily:
ListOfExpenses=["house","car","holiday"]
ListOfCost=["Q_house","Q_car","Q_holiday"]
Elements_Of_ListOfCost=[init_old(“Q_”+i,"P0_"+i) for i in ListOfExpenses]
So when I look for Q_house, Q_car or Q_holiday later, it returns the same Q_house=init_old(“Q_house”,"P_house") calculated in the original code.
I don't want to use dictionaries for now as they would require major change to the rest of the code and calling dictionaries causes problems in some of the other functions. Thanks in advance for the help.
I'm not sure whether this kind of functionality exists or not or how is best to go about this. I am wanting to create a general problem solver where I can define the predicates, operations and such before solving rather than coding directly. So far I have been storing functions as part of a dictionary. The only way that it seems possible to do this with a dictionary is to create it with every potential combination imaginable.
For example, previously it was this:
self.Operators = {"STACK": self.stack, "UNSTACK": self.unstack,
"PICKUP": self.pickup, "PUTDOWN": self.putdown}
Where I would now like it to be something more like:
self.Operators = {("STACK", x, y): [[("clear", y), ("holding", x)], ["armempty", ("on", x, y)]]}
I know I am probably barking up the wrong tree with dictionaries here but this is the first time I've tried to do something like this and I have no idea what the appropriate/most Pythonesque way to manage this is?
I have solved this using the following (which is what I am going to go with):
self.Operators = {'PICKUP': [[['ontable', 'a'], ['armempty']], [['holding', 'a']]]}
The list that is then returned I parse using a list comprehension:
y = [w.replace("a", args[0]) for w in y]
For a list that has multiple variables, I will end up doing multiple list comprehensions by enumerating through characters.
I've defined a function as below to try to interpolate between two sets of data. When I run it, I get the message:
for i, j in range(0, len(wavelength)):
TypeError: 'int' object is not iterable
I'm not sure what I'm doing wrong. Admittedly, I'm not very good at this.
def accountforfilter(wavelength, flux, filterwavelength, throughput):
filteredwavelength=[]
filteredflux=[]
for i in range(0, len(wavelength)):
if wavelength[i] in filterwavelength[j]:
j=filterwavelength.index(wavelength[i])
filteredwavelength.append(wavelength[i])
filteredflux.append(flux[i]*throughput[j])
elif wavelength[i]<filterwavelength[j]<wavelength[i+1]:
m=((throughput[j+1]-throughput[j])/(filterwavelength[j+1]-filterwavelength[j])
c=throughput[j]-(m*(wavelength[i]))
filteredwavelength.append(wavelength[i])
filteredflux.append(flux[i]*(m*wavelength[i]+c)
return filteredwavelength, filteredflux
range() returns a list of integers. By using for i,j in range() you are telling Python to unpack each item in range() to two values. But since those values are integers, which are a single piece of data, and thus not iterable, you get the error message.
Your code also looks a bit strange.
At first it seems like you want to loop over all combinations of wavelength/filterwavelength, which would be the same as
for i in range(len(wavelength)):
for j in range(len(filterwavelength)):
do_stuff()
but then you are modifying the j parameter inside the loop body, which I don't understand.
Regardless, there is probably a lot easier, and more clear, way to write the code you want. But from the current code it is hard to know what is expected (and should probably go in a separate question).
The problem is that the range only works with one variable like so:
for i in range(0, len(wavelength))
You try to use two variables at once so python tries to unpack an integer which is impossible. You should use the above. If you need two independent indices, use
for i in range(0, len(...))
for j in range(0, len(...))
Btw ranges always start with zero so you can save yourself some typing and use range(len(...)) instead.
You can use zip if you want.
check this: Better way to iterate over two or multiple lists at once
if you have two sets of data.
for i,j in zip(set1,set2):
print i,j