I load a row of data in a class, row by row with a loop. I'd like to append each row to a list.
class Biz:
def __init__(self, dba_name, legal_name):
self.dba_name = dba_name
self.legal_name = legal_name
MasterList = []
File_From_Excel = pd.read_excel('C:\file.xlsx')
for index, row in File_From_Excel.iterrows():
record = Biz(row['Field 1'], row['Field 2'])
MasterList.append(record)
print(MasterList)
When I run code like this, I do not get an error, but I get info like this printed:
"[<main.Biz object at 0x0C11BFB0>, <main.Biz object at 0x00BDED50>]"
I'm a newbie and I haven't figured out how to overcome this one. Thank you!
You are printing a list of class instances, so the output is their memory addresses. What you probably want instead is the attributes of these instances. It can be achieved as follows (for illustrative purposes):
# this goes at the end of your code, outside of the loop!
print([[record.dba_name, record.legal_name] for record in MasterList])
This approach is by no means optimal and and will give you memory issues if there are a lot of elements in MasterList. In that case you would want to use either a generator or a class iterator.
Edit: Come to think of it, there is no need for a generator here since a simple for loop can iterate over the list:
for record in MasterList:
print([record.dba_name, record.legal_name], end=' ')
Related
def read_prices(tikrList):
#read each file and get the price list dictionary
def getPriceDict():
priceDict = {}
TLL = len(tikrList)
for x in range(0,TLL):
with open(tikrList[x] + '.csv','r') as csvFile:
csvReader = csv.reader(csvFile)
for column in csvReader:
priceDict[column[0]] = float(column[1])
return priceDict
#populate the final dictionary with the price dictionary from the previous function
def popDict():
combDict = {}
TLL = len(tikrList)
for x in range(0,TLL):
for y in tikrList:
combDict[y] = getPriceDict()
return combDict
return(popDict())
print(read_prices(['GOOG','XOM','FB']))
What is wrong with the code is that when I return the final dictionary the key for GOOG,XOM,FB is represnting the values for the FB dictionary only.
As you can see with this output:
{'GOOG': {'2015-12-31': 104.660004, '2015-12-30': 106.220001},
'XOM': {'2015-12-31': 104.660004, '2015-12-30': 106.220001},
'FB': {'2015-12-31': 104.660004, '2015-12-30': 106.220001}
I have 3 different CSV files but all of them are just reading the CSV file for FB.
I want to apologize ahead of time if my code is not easy to read or doesn't make sense. I think there is an issue with storing the values and returning the priceDict in the getPriceDict function but I cant seem to figure it out.
Any help is appreciated, thank you!
Since this is classwork I won't provide a solution but I'll point a few things out.
You have defined three functions - two are defined inside the third. While structuring functions like that can make sense for some problems/solutions I don't see any benefit in your solution. It seems to make it more complicated.
The two inner functions don't have any parameters, you might want to refactor them so that when they are called you pass them the information they need. One advantage of a function is to encapsulate an idea/process into a self-contained code block that doesn't rely on resources external to itself. This makes it easy to test so you know that the function works and you can concentrate on other parts of the code.
This piece of your code doesn't make much sense - it never uses x from the outer loop:
...
for x in range(0,TLL):
for y in tikrList:
combDict[y] = getPriceDict()
When you iterate over a list the iteration will stop after the last item and it will iterate over the items themselves - no need to iterate over numbers to access the items: don't do for i in range(thelist): print(thelist[i])
>>> tikrList = ['GOOG','XOM','FB']
>>> for name in tikrList:
... print(name)
GOOG
XOM
FB
>>>
When you read through a tutorial or the documentation, don't just look at the examples - read and understand the text .
I'm a beginner in python, currently I'm trying to automate filling website field using selenium.
I'm trying to iterate over nested lists using for loop but always get only the last element. Any suggestions why?
fields = [['a','b','c'],['x','y','z']]
for i in range(len(fields)):
driver.find_element_by_xpath("element").send_keys(fields[i][0],fields[i[1],fields[i][2])
driver.find_element_by_xpath("element_save").click()
#then loop and iterate through 2nd nested list
# OUTPUT = x,y,z
I expect to iterate starting with index 0 to the end of the list.
You don't need range(len(list_)) for iterating over indeces only.
Usual for will do. You can also unpack list with *:
fields = [['a','b','c'],['x','y','z']]
len_ = len(fields)
for i in range(len_):
driver.find_element_by_xpath("element").send_keys(*fields[i])
You could also iterate trhrough the values of the fields itself:
fields = [['a','b','c'],['x','y','z']]
for field in fields:
driver.find_element_by_xpath("element").send_keys(*field)
Firstly there is a bug in your program as you have written it:
fields = [['a','b','c'],['x','y','z']]
for i, v in enumerate(fields):
driver.find_element_by_xpath("element").send_keys(fields[i][0],fields[i[1],fields[i][2])
^ # No closing ]
Secondly there is a term that Python developers like to throw around: Pythonic Code.
We like to write short concise code that favors readability over squeezing every last inch of performance.
Referring to this you should change your code as it is unnecessarily cluttered and you are not even utilizing the value element of enumerate. I would recommend the following:
fields = [['a','b','c'],['x','y','z']]
for field in fields:
name, age, height = field # Replace this line with whatever the fields represent
driver.find_element_by_xpath("element").send_keys(name, age, height)
This code is short, concise, and above all extremely readable to someone else.
Note: Replace the name, age, height with whatever they represent in your program.
If in fact this didn't solve your problem, your problem may not be with python but with selenium itself and that is out of the scope of this question. You can test this with simply printing the values before feeding it to the selenium function like this:
fields = [['a','b','c'],['x','y','z']]
for field in fields:
name, age, height = field # Replace this line with whatever the fields represent
print(name, age, height)
driver.find_element_by_xpath("element").send_keys(name, age, height)
Hope this helps.
I'm trying to create generator object for the list of records with the data from mysql database, so I'm passing the mysql cursor object to the function as parameter.
My issue here is if the "if block" containing yield records is commented then cust_records function works perfectly fine but if I uncomment the line then the function is not working.
Not sure if this is not the way to yield the list object in Python 3
My code so far:
def cust_records(result_set) :
block_id = None
records = []
i = 0
for row in result_set :
records.append((row['id'], row, smaller_ids))
if records :
yield records
The point of generators is lazy evaluation, so storing all records in a list and yielding the list makes no sense at all. If you want to retain lazy evalution (which is IMHO preferable, specially if you have to work on arbitrary datasets that might get huge), you want to yield each record, ie:
def cust_records(result_set) :
for row in result_set :
yield (row['id'], row, smaller_ids)
# then
def example():
cursor.execute(<your_sql_query_here>)
for record in cust_records(cursor):
print(record)
else (if you really want to consume as much memory as possible) just male cust_record a plain function:
def cust_records(result_set) :
records = []
for row in result_set :
records.append((row['id'], row, smaller_ids))
return records
I'm making a program that allows the user to log loot they receive from monsters in an MMO. I have the drop tables for each monster stored in text files. I've tried a few different formats but I still can't pin down exactly how to take that information into python and store it into a list of lists of lists.
The text file is formatted like this
item 1*4,5,8*ns
item 2*3*s
item 3*90,34*ns
The item # is the name of the item, the numbers are different quantities that can be dropped, and the s/ns is whether the item is stackable or not stackable in game.
I want the entire drop table of the monster to be stored in a list called currentDropTable so that I can reference the names and quantities of the items to pull photos and log the quantities dropped and stuff.
The list for the above example should look like this
[["item 1", ["4","5","8"], "ns"], ["item 2", ["2","3"], "s"], ["item 3", ["90","34"], "ns"]]
That way, I can reference currentDropTable[0][0] to get the name of an item, or if I want to log a drop of 4 of item 1, I can use currentDropTable[0][1][0].
I hope this makes sense, I've tried the following and it almost works, but I don't know what to add or change to get the result I want.
def convert_drop_table(list):
global currentDropTable
currentDropTable = []
for i in list:
item = i.split('*')
currentDropTable.append(item)
dropTableFile = open("droptable.txt", "r").read().split('\n')
convert_drop_table(dropTableFile)
print(currentDropTable)
This prints everything properly except the quantities are still an entity without being a list, so it would look like
[['item 1', '4,5,8', 'ns'], ['item 2', '2,3', 's']...etc]
I've tried nesting another for j in i, split(',') but then that breaks up everything, not just the list of quantities.
I hope I was clear, if I need to clarify anything let me know. This is the first time I've posted on here, usually I can just find another solution from the past but I haven't been able to find anyone who is trying to do or doing what I want to do.
Thank you.
You want to split only the second entity by ',' so you don't need another loop. Since you know that item = i.split('*') returns a list of 3 items, you can simply change your innermost for-loop as follows,
for i in list:
item = i.split('*')
item[1] = item[1].split(',')
currentDropTable.append(item)
Here you replace the second element of item with a list of the quantities.
You only need to split second element from that list.
def convert_drop_table(list):
global currentDropTable
currentDropTable = []
for i in list:
item = i.split('*')
item[1] = item[1].split(',')
currentDropTable.append(item)
The first thing I feel bound to say is that it's usually a good idea to avoid using global variables in any language. Errors involving them can be hard to track down. In fact you could simply omit that function convert_drop_table from your code and do what you need in-line. Then readers aren't obliged to look elsewhere to find out what it does.
And here's yet another way to parse those lines! :) Look for the asterisks then use their positions to select what you want.
currentDropTable = []
with open('droptable.txt') as droptable:
for line in droptable:
line = line.strip()
p = line.find('*')
q = line.rfind('*')
currentDropTable.append([line[0:p], line[1+p:q], line[1+q:]])
print (currentDropTable)
I have following kind of data, which I want to collect to one big list so that each row in the big list has one of these below (c-d and e-f correspond to second and third of these). What I mean is that lista_results[0] includes the first of these and lista_results[1] the second etc.
(Name) (Amount-of-points)
Some name 12
Other name 19
... ...
I have a loop that takes information from other lists and then adds it to result list. The code is along the following lines:
lista_results = []
lista_temp = []
for y in range(0,10):
for x in range(0,10):
lista_temp.append(name_list[y][x], point_list[y][x])
lista_results.append(lista_temp)
#lista_temp[:] = []
Without the emptying, all are appended to same list every time x loop finishes. Basically what I get is:
[0]["Some name",12]
[0]["Other name",19]
[1]["Some name",12]
[1]["Other name",19]
[1][c,1c]
[1][d,2d]
[2]["Some name",12]
[2]["Other name",19]
[2][c,1c]
[2][d,2d]
[2][e,1e]
[2][f,2f]
...
But what I want is:
[0]["Some name",12]
[0]["Other name",19]
[1][c,1c]
[1][d,2d]
[2][e,1e]
[2][f,2f]
...
Which would mean that I would have to somehow empty the lista_temp after appending it to the lista_results. But when I do empty it (using #lista_temp[:] = []), it seems that also the parts that were appended to lista_results are emptied, or at least I get "IndexError" when trying to print out even lista_results[0][0][0]. I assume that bot reference to same list and emptying either empties also the other.
I also tried lista_newtemp=lista_temp and even then I got an IndexError after emptying lista_temp.
What would be a way to empty lista_temp after append without losing previous information already appended?
(Also, my first question here, I hope I did it well. I hope the problem explanation was clear. Feedback appreciated!)
It's really hard to tell from your output samples what data you're working on, but it sounds to me like you don't want to empty the list but create a new list for the next iteration. Something like:
lista_results = []
for y in range(0,10):
lista_temp = [] # we have a new lista_temp for every y
for x in range(0,10):
lista_temp.append(something_here)
lista_results.append(lista_temp)
The behaviour you see is because Python does not generally make implicit copies. Every lista_temp you appended into lista_results is the same object, which in turn kept changing.
It would be more Pythonic to use list comprehesions.
The inner list, lista_temp, can be created like this:
lista_temp = [something_here for x in range(0, 10)]
The outer list, lista_results, can be created like this:
lista_results = [make_lista_temp(y)
for y in range(0, 10)]
You can combine them, and lose the temporary variable lista_temp:
lista_results = [[something_here for x in range(0, 10)]
for y in range(0, 10)]
edit:
Your main problem was that you weren't copying lista_temp, so every element of lista_results points to the same instance that lista_temp points to. You could have copied it like this:
lista_results.append(list(lista_temp))
However, as above, there are better ways.