How to pass a function within another function when using Python
以下是我正在使用的csv文件:
1 2 3 4 5 | `"A","B","C","D","E","F","G","H","I","J" "88",18,1,"<Req TID=""34"" ReqType=""MS""><IISO /><CID>2</CID><MemID>0000</MemID><MemPass /><RequestData><S>[REMOVED]</S><Na /><La /><Card>[REMOVED]</Card><Address /><HPhone /><Mail /></ReqData></Req>","<Response T=""3"" RequestType=""MS""><MS><Memb><PrivateMembers /><Ob>0-12-af</Ob><Locator /></Memb><S>[REMOVED]</S><CNum>[REMOVED]</CNum><FName /><LaName /><Address /><HPhone /><Email /><IISO /><MemID /><MemPass /><T /><CID /><T /></MS></Response>",0-JAN-10 12.00.02 AM,27-JUN-15 12.00.00 AM,"26",667,0 "22",22,1,"<Req TID=""45"" ReqType=""MS""><IISO /><CID>4</CID><MemID>0000</MemID><MemPass /><RequestData><S>[REMOVED]</S><Na /><La /><Card>[REMOVED]</Card><Address /><HPhone /><Mail /></ReqData></Req>","<Response T=""10"" RequestType=""MS""><MS><Memb><PrivateMembers /><Ob>0-12-af</Ob><Locator /></Memb><S>[REMOVED]</S><CNum>[REMOVED]</CNum><FName /><LaName /><Address /><HPhone /><Email /><IISO /><MemID /><MemPass /><T /><CID /><T /></MS></Response>",0-JAN-22 12.00.02 AM,27-JUN-22 12.00.00 AM,"26",667,0 "32",22,1,"<Req TID=""15"" ReqType=""MS""><IISO /><CID>45</CID><MemID>0000</MemID><MemPass /><RequestData><S>[REMOVED]</S><Na /><La /><Card>[REMOVED]</Card><Address /><HPhone /><Mail /></ReqData></Req>","<Response T=""10"" RequestType=""MS""><MS><Memb><PrivateMembers /><Ob>0-12-af</Ob><Locator /></Memb><S>[REMOVED]</S><CNum>[REMOVED]</CNum><FName /><LaName /><Address /><HPhone /><Email /><IISO /><MemID /><MemPass /><T /><CID /><T /></MS></Response>",0-JAN-20 12.00.02 AM,27-JUN-34 12.00.00 AM,"26",667,0` |
下面的函数是注释的。简而言之,函数
到目前为止,它的输出是生成一个字典。然后,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | import csv from collections import OrderedDict from xml.etree.ElementTree import ParseError import collections from __future__ import print_function def get_clientresponses_2(filename = 's.csv'): with open(filename, 'rU') as infile: reader = csv.DictReader(infile) # read the file as a dictionary for each row ({header : value}) data = {} for row in reader: for header, value in row.items(): try: data[header].append(value) except KeyError: data[header] = [value] client_responses = data['E'] #returns a list for client_response in client_responses: xml_string = (''.join(client_response)) xml_string = xml_string.replace('&', '') try: root = ElementTree.XML(xml_string) print(root) except ET.ParseError: print("catastrophic failure") continue def allocate_and_write_2(get_clientresponses_2_gen): with open(filename, 'r') as infile: reader = csv.DictReader(infile) # read the file as a dictionary for each row ({header : value}) header = set() results = [] # data = {} # this is not needed for the purpose of this organization for row in reader: for get_clientresponses_2 in get_clientresponses_2_gen: xml_data = get_clientresponses_2() row.update(xml_data) # just for XML data results.append(row) # everything else header.update(row.keys()) # can't forget headers # print(row) # returns dictionary of key values pairs (headers : values) # print(results) # returns list wrapper for dictionary # print(headers) #returns set of all headers headers_list = list(header) # print(headers_list) #list form of set with open('csv_output.csv', 'wt') as f: writer = csv.writer(f) writer.writerow(headers_list) for row in results: data = [row.get(x, '') for x in headers_list] writer.writerow(data) # writer.writerows(zip(headers_list, data)) |
输出如下:
1 2 3 4 | C,HPhone,Locator,IISO,E,S,FName,LaName,J,D,MemID,ResponseRequestType,T,Email,I,Ob,G,MemPass,Address,A,PrivateMembers,H,CNum,ResponseT,CID,B,F 1,,,,"<Response T=""3"" RequestType=""MS""><MS><Memb><PrivateMembers /><Ob>0-12-af</Ob><Locator /></Memb><S>[REMOVED]</S><CNum>[REMOVED]</CNum><FName /><LaName /><Address /><HPhone /><Email /><IISO /><MemID /><MemPass /><T /><CID /><T /></MS></Response>",[REMOVED],,,0,"<Req TID=""34"" ReqType=""MS""><IISO /><CID>2</CID><MemID>0000</MemID><MemPass /><RequestData><S>[REMOVED]</S><Na /><La /><Card>[REMOVED]</Card><Address /><HPhone /><Mail /></ReqData></Req>",,MS,,,667,0-12-af,27-JUN-15 12.00.00 AM,,,88,,26,[REMOVED],10,,18,0-JAN-10 12.00.02 AM 1,,,,"<Response T=""10"" RequestType=""MS""><MS><Memb><PrivateMembers /><Ob>0-12-af</Ob><Locator /></Memb><S>[REMOVED]</S><CNum>[REMOVED]</CNum><FName /><LaName /><Address /><HPhone /><Email /><IISO /><MemID /><MemPass /><T /><CID /><T /></MS></Response>",[REMOVED],,,0,"<Req TID=""45"" ReqType=""MS""><IISO /><CID>4</CID><MemID>0000</MemID><MemPass /><RequestData><S>[REMOVED]</S><Na /><La /><Card>[REMOVED]</Card><Address /><HPhone /><Mail /></ReqData></Req>",,MS,,,667,0-12-af,27-JUN-22 12.00.00 AM,,,22,,26,[REMOVED],10,,22,0-JAN-22 12.00.02 AM 1,,,,"<Response T=""10"" RequestType=""MS""><MS><Memb><PrivateMembers /><Ob>0-12-af</Ob><Locator /></Memb><S>[REMOVED]</S><CNum>[REMOVED]</CNum><FName /><LaName /><Address /><HPhone /><Email /><IISO /><MemID /><MemPass /><T /><CID /><T /></MS></Response>",[REMOVED],,,0,"<Req TID=""15"" ReqType=""MS""><IISO /><CID>45</CID><MemID>0000</MemID><MemPass /><RequestData><S>[REMOVED]</S><Na /><La /><Card>[REMOVED]</Card><Address /><HPhone /><Mail /></ReqData></Req>",,MS,,,667,0-12-af,27-JUN-34 12.00.00 AM,,,32,,26,[REMOVED],10,,22,0-JAN-20 12.00.02 AM |
但是,当我试图在
1 2 3 4 5 6 7 8 | <ipython-input-91-cfd866a1c0b6> in allocate_and_write_2(get_clientresponses_2_gen) 37 # data = {} # this is not needed for the purpose of this organization 38 for row in reader: ---> 39 for get_clientresponses_2 in get_clientresponses_2_gen: 40 xml_data = get_clientresponses_2() 41 row.update(xml_data) # just for XML data TypeError: 'function' object is not iterable |
基于我对这个论坛上的生成器和其他帖子的理解,我知道这是由于这个问题。我想通过传递第一个函数的输出(
感谢@anandskumar的指导:
这确实是由于我如何在生成器函数的上下文中使用迭代器构造函数。我用阿南德的建议替换了我原来的剧本:
1 2 | for xml_data in get_clientresponses_2(): xml_dat = dict(flatten_dict(xml_data)) |
但是,我还必须通过返回每个XML树的根并将其传递给
为了防止任何副作用,我把它们保留为两个互斥的功能。
您只需在
1 2 | if __name__ =="__main__": main() |
我这样做的原因在这里有详细说明
以下是两个功能套件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | import csv from collections import OrderedDict from xml.etree.ElementTree import ParseError import collections from __future__ import print_function def get_clientresponses_2(filename = 's.csv'): with open(filename, 'rU') as infile: reader = csv.DictReader(infile) # read the file as a dictionary for each row ({header : value}) data = {} for row in reader: for header, value in row.items(): try: data[header].append(value) except KeyError: data[header] = [value] client_responses = data['E'] #returns a list for client_response in client_responses: xml_string = (''.join(client_response)) xml_string = xml_string.replace('&', '') try: root = ElementTree.XML(xml_string) # print(root) return root except ET.ParseError: print("catastrophic failure") continue def allocate_and_write_2(): with open(filename, 'r') as infile: reader = csv.DictReader(infile) # read the file as a dictionary for each row ({header : value}) header = set() results = [] # data = {} # this is not needed for the purpose of this organization for row in reader: for xml_data in get_clientresponses_2(): xml_dat = dict(flatten_dict(xml_data)) row.update(xml_dat) # just for XML data results.append(row) # everything else header.update(row.keys()) # can't forget headers # print(row) # returns dictionary of key values pairs (headers : values) # print(results) # returns list wrapper for dictionary # print(headers) #returns set of all headers headers_list = list(header) # print(headers_list) #list form of set with open('csv_output.csv', 'wt') as f: writer = csv.writer(f) writer.writerow(headers_list) for row in results: data = [row.get(x, '') for x in headers_list] # print(data) writer.writerow(data) # writer.writerows(zip(headers_list, data)) |
根据注释,似乎
1 2 | for get_clientresponses_2 in get_clientresponses_2_gen: xml_data = get_clientresponses_2() |
要遍历generator函数并将每个值放入
1 | for xml_data in get_clientresponses_2_gen(): |
(将此替换为上面给出的两行)。