Re: [python] Rekurzivní generátor v Pythonu 3?
On 2016-08-30, 10:28 GMT, Petr Messner wrote: > To je veselé, když někdo dělá benchmark profilerem. a) uznávám: $ time python3 test_append.py real0m2.429s user0m1.850s sys 0m0.565s $ time python3 test_plus.py real0m2.471s user0m2.096s sys 0m0.372s $ time python3 test_plus.py Na svoji obranu bych dodal, že ten rozdíl je fakt minimální, a že se to opravdu v pythonu 2.5 změnilo. b) je to úplně jedno, protože o rychlost v tomhle případě opravdu nejde. Nějaké nápady k té rekurzivitě? Dělal jste někdo něco takového? Matěj -- https://matej.ceplovi.cz/blog/, Jabber: mc...@ceplovi.cz GPG Finger: 3C76 A027 CA45 AD70 98B5 BC1D 7920 5802 880B C9D8 The American Republic will endure, until politicians realize they can bribe the people with their own money. -- based on a statement of Alexander Fraser Tytler ___ Python mailing list python@py.cz http://www.py.cz/mailman/listinfo/python Visit: http://www.py.cz
Re: [python] Rekurzivní generátor v Pythonu 3?
Zdravím vespolek, kolega toto téma řešil tak před třemi lety a došel k závěru že je to jedno. Resp. v každé verzi to bylo jinak. Pravda vstupovali do toho i verze 2.x. Asi taky záleží jak moc jsou ty texty konstantní, resp. jako moc jsou dynamické, v jakém kompilátoru s jakými přepínači je pythoní interpretr kompilovaný a ad absurdum na jakém HW to běží. Ondra V Tue, 30 Aug 2016 12:28:30 +0200 Petr Messnernapsáno: > To je veselé, když někdo dělá benchmark profilerem. > > $ cat test_plus.py > out = '' > for i in range(1000): > out += 'Nebudu komentovat rychlost algoritmů bez měření' > $ cat test_append.py > out = [] > for i in range(1000): > out.append('Nebudu komentovat rychlost algoritmů bez měření') > outstr = ''.join(out) > $ time python3 test_plus.py > > real 0m2.835s > user 0m2.536s > sys 0m0.288s > $ time python3 test_append.py > > real 0m1.848s > user 0m1.588s > sys 0m0.256s > > > > Dne 30. srpna 2016 11:39 Matěj Cepl napsal(a): > > > On 2016-08-28, 10:54 GMT, Petr Messner wrote: > > > Na tohle se vykašli. Jakmile dokument nemá stromovou > > > strukturu, tak je vše tisíckrát složitější. Dikybohu toto XML > > > neumí. > > > > Tohle je rada s odpuštěním na h... Ten vstupní datový formát mám > > daný, s tím nemůžu nic dělat. > > > > > nedělej skládání řetězců stylem txt += part, je to strašně > > > pomalé (O(n^2) místo O(n)).. Z txt si udělej list a používej > > > append: txt.append(part) a na konci "".join(txt). > > > > To je veselé jak tyhle pověry drží. Tohle bylo opraveno > > v pythonu 2.5 (pokud se nemýlím). > > > > ~$ cat test_plus.py > > out = '' > > for i in range(1000): > > out += 'Nebudu komentovat rychlost algoritmů bez měření' > > ~$ python3 -mcProfile test_plus.py > > 3 function calls in 1.970 seconds > > > >Ordered by: standard name > > > >ncalls tottime percall cumtime percall > > filename:lineno(function) 11.9701.9701.9701.970 > > test_plus.py:1() 10.0000.0001.9701.970 > > {built-in method exec} 10.0000.0000.0000.000 > > {method 'disable' of '_lsprof.Profiler' objects} > > > > > > ~$ cat test_append.py > > out = [] > > for i in range(1000): > > out.append('Nebudu komentovat rychlost algoritmů bez > > měření') outstr = ''.join(out) > > ~$ python3 -mcProfile test_append.py > > 1004 function calls in 3.331 seconds > > > >Ordered by: standard name > > > >ncalls tottime percall cumtime percall > > filename:lineno(function) 11.8451.8453.3313.331 > > test_append.py:1() > > 10.0000.0003.3313.331 {built-in method > > exec} 10000.5280.0000.5280.000 {method 'append' > > of 'list' objects} > > 10.0000.0000.0000.000 {method 'disable' > > of '_lsprof.Profiler' objects} > > 10.9590.9590.9590.959 {method 'join' of > > 'str' objects} > > > > ~$ > > > > Hezký den, > > > > Matěj > > > > -- > > https://matej.ceplovi.cz/blog/, Jabber: mc...@ceplovi.cz > > GPG Finger: 3C76 A027 CA45 AD70 98B5 BC1D 7920 5802 880B C9D8 > > > > You either die a hero or you live long enough to see yourself > > become the villain. > > -- Harvey Dent in The Dark Knight > > ___ > > Python mailing list > > python@py.cz > > http://www.py.cz/mailman/listinfo/python > > > > Visit: http://www.py.cz > > -- Ondřej Tůma www: http://ipv6.mcbig.cz jabber: mc...@jabber.cz twitter: mcbig_cz pgpMsU4ScB0A8.pgp Description: OpenPGP digital signature ___ Python mailing list python@py.cz http://www.py.cz/mailman/listinfo/python Visit: http://www.py.cz
Re: [python] Rekurzivní generátor v Pythonu 3?
To je veselé, když někdo dělá benchmark profilerem. $ cat test_plus.py out = '' for i in range(1000): out += 'Nebudu komentovat rychlost algoritmů bez měření' $ cat test_append.py out = [] for i in range(1000): out.append('Nebudu komentovat rychlost algoritmů bez měření') outstr = ''.join(out) $ time python3 test_plus.py real 0m2.835s user 0m2.536s sys 0m0.288s $ time python3 test_append.py real 0m1.848s user 0m1.588s sys 0m0.256s Dne 30. srpna 2016 11:39 Matěj Ceplnapsal(a): > On 2016-08-28, 10:54 GMT, Petr Messner wrote: > > Na tohle se vykašli. Jakmile dokument nemá stromovou > > strukturu, tak je vše tisíckrát složitější. Dikybohu toto XML > > neumí. > > Tohle je rada s odpuštěním na h... Ten vstupní datový formát mám > daný, s tím nemůžu nic dělat. > > > nedělej skládání řetězců stylem txt += part, je to strašně > > pomalé (O(n^2) místo O(n)).. Z txt si udělej list a používej > > append: txt.append(part) a na konci "".join(txt). > > To je veselé jak tyhle pověry drží. Tohle bylo opraveno > v pythonu 2.5 (pokud se nemýlím). > > ~$ cat test_plus.py > out = '' > for i in range(1000): > out += 'Nebudu komentovat rychlost algoritmů bez měření' > ~$ python3 -mcProfile test_plus.py > 3 function calls in 1.970 seconds > >Ordered by: standard name > >ncalls tottime percall cumtime percall filename:lineno(function) > 11.9701.9701.9701.970 test_plus.py:1() > 10.0000.0001.9701.970 {built-in method exec} > 10.0000.0000.0000.000 {method 'disable' of > '_lsprof.Profiler' objects} > > > ~$ cat test_append.py > out = [] > for i in range(1000): > out.append('Nebudu komentovat rychlost algoritmů bez měření') > outstr = ''.join(out) > ~$ python3 -mcProfile test_append.py > 1004 function calls in 3.331 seconds > >Ordered by: standard name > >ncalls tottime percall cumtime percall filename:lineno(function) > 11.8451.8453.3313.331 > test_append.py:1() > 10.0000.0003.3313.331 {built-in method exec} > 10000.5280.0000.5280.000 {method 'append' of > 'list' objects} > 10.0000.0000.0000.000 {method 'disable' of > '_lsprof.Profiler' objects} > 10.9590.9590.9590.959 {method 'join' of 'str' > objects} > > ~$ > > Hezký den, > > Matěj > > -- > https://matej.ceplovi.cz/blog/, Jabber: mc...@ceplovi.cz > GPG Finger: 3C76 A027 CA45 AD70 98B5 BC1D 7920 5802 880B C9D8 > > You either die a hero or you live long enough to see yourself become the > villain. > -- Harvey Dent in The Dark Knight > ___ > Python mailing list > python@py.cz > http://www.py.cz/mailman/listinfo/python > > Visit: http://www.py.cz > ___ Python mailing list python@py.cz http://www.py.cz/mailman/listinfo/python Visit: http://www.py.cz
Re: [python] Rekurzivní generátor v Pythonu 3?
On 2016-08-28, 10:54 GMT, Petr Messner wrote: > Na tohle se vykašli. Jakmile dokument nemá stromovou > strukturu, tak je vše tisíckrát složitější. Dikybohu toto XML > neumí. Tohle je rada s odpuštěním na h... Ten vstupní datový formát mám daný, s tím nemůžu nic dělat. > nedělej skládání řetězců stylem txt += part, je to strašně > pomalé (O(n^2) místo O(n)).. Z txt si udělej list a používej > append: txt.append(part) a na konci "".join(txt). To je veselé jak tyhle pověry drží. Tohle bylo opraveno v pythonu 2.5 (pokud se nemýlím). ~$ cat test_plus.py out = '' for i in range(1000): out += 'Nebudu komentovat rychlost algoritmů bez měření' ~$ python3 -mcProfile test_plus.py 3 function calls in 1.970 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 11.9701.9701.9701.970 test_plus.py:1() 10.0000.0001.9701.970 {built-in method exec} 10.0000.0000.0000.000 {method 'disable' of '_lsprof.Profiler' objects} ~$ cat test_append.py out = [] for i in range(1000): out.append('Nebudu komentovat rychlost algoritmů bez měření') outstr = ''.join(out) ~$ python3 -mcProfile test_append.py 1004 function calls in 3.331 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 11.8451.8453.3313.331 test_append.py:1() 10.0000.0003.3313.331 {built-in method exec} 10000.5280.0000.5280.000 {method 'append' of 'list' objects} 10.0000.0000.0000.000 {method 'disable' of '_lsprof.Profiler' objects} 10.9590.9590.9590.959 {method 'join' of 'str' objects} ~$ Hezký den, Matěj -- https://matej.ceplovi.cz/blog/, Jabber: mc...@ceplovi.cz GPG Finger: 3C76 A027 CA45 AD70 98B5 BC1D 7920 5802 880B C9D8 You either die a hero or you live long enough to see yourself become the villain. -- Harvey Dent in The Dark Knight ___ Python mailing list python@py.cz http://www.py.cz/mailman/listinfo/python Visit: http://www.py.cz
Re: [python] Rekurzivní generátor v Pythonu 3?
> co takhle tohle? > > a b c de f g h > Oprava: a b c de f g h PM___ Python mailing list python@py.cz http://www.py.cz/mailman/listinfo/python Visit: http://www.py.cz
Re: [python] Rekurzivní generátor v Pythonu 3?
> > V mém případě může část dokumentu vypadat třeba takto: > >text text > >textB textB textC textC textD textD Na tohle se vykašli. Jakmile dokument nemá stromovou strukturu, tak je vše tisíckrát složitější. Dikybohu toto XML neumí. Co je špatného na tom příkladě se sID/eID? Jestli je to v tom, že to neoznačuje i část obsahu/verše, co takhle tohle? a b c de f g h Na pochopení toho kódu bych si musel sednout někam v klidu, ale zatím jen taková drobnost - nedělej skládání řetězců stylem txt += part, je to strašně pomalé (O(n^2) místo O(n)).. Z txt si udělej list a používej append: txt.append(part) a na konci "".join(txt). Petr Messner 27. 8. 2016 v 23:09, Matěj Cepl: > Dobrý den, > > zkouším napsat v Pythonu 3.4+ nástroj pracující s milestonovanými XML soubory > (zdrojové texty překladu Bible). Podrobně jsem to popsal v blogpostu > https://matej.ceplovi.cz/blog/parsing-milestoned-xml-in-python.html, zde > jenom velice stručně. Milestones (milníky?) jsou metoda jak obejít > neschopnost XML pracovat s několika překrývajícími se hierarchiemi v jednom > souboru. Tak třeba právě v biblických textech (TEI se potýká s podobnými > problémy) je základní struktura kniha-kapitola-verš, ale přes to jsou další > elementy které se překrývají. Několik veršů (nebo jejich částí) jsou sdruženy > do logických oddílů (ale některé začínají v půli verše a často přesahují > hranice kapitol), nebo třeba zejména anglické biblické překlady mají v oblibě > značit výroky Pána Ježíše zvlášť (což pochopitelně často začíná a končí v > půli verše). > > Jedna z metod (používaná husta právě v biblických textech, TEI a podobných > složitě strukturovaných dokumentech) jsou právě milníky. Takže místo aby byl > text značen nějak takto: > > > > text > ... > > ... > > > použijí se na hranici knihy, kapitoly i verše milníky takto (buď se zvláštním > označením konce veršů nebo taky ne): > > > > text of verse 1.1 > > > > V mém případě může část dokumentu vypadat třeba takto: > >text text > >textB textB textC textC textD textD > > A chtěl bych aby moje knihovna naparsovala toto XML a vyprodukovala takovýto > seznam: > >[(1, 1, "text text", ['text text']), > (1, 2, "textB textB textC textC", > ['', 'textB textB', '', 'textC textC']), > (1, 3, "textD textD", ['', 'textD textD', ''])] > > (první dvě čísla jsou číslo kapitoly a verše, poslední položka tuplu je > seznam kousků XML v podobě přijatelné pro ElementTree.fromstringlist). Takže > představoval bych si generátor, který by byl schopen takovéto API: > >if __name__ == '__main__': >xml_file = ET.parse('tests/data/Mat-old.xml') >parser = ET.XMLParser(target=ET.TreeBuilder()) > >with open('test.txt', 'w', newline='\r\n') as out_txt, \ >open('test.xml', 'w', newline='\r\n') as out_xml: >for ch, v, verse_txt, verse_xml in recursive_parse(xml_file): >print(verse_txt, file=out_txt) ># or directly parser.feed(verse_xml) ># if verse_xml is not a list >parser.feed(''.join(verse_xml)) > >print(ET.tostring(parser.close(), encoding='unicode'), > file=out_xml) > > Po různých peripetiích (popsaných v tom zmiňovaném blogpostu) jsem v > současném okamžiku u tohoto (zatím bez shromažďování XML kousků): > >def __iter__(self) -> Tuple[CollectedInfo, str]: >""" >iterate through the first level elements >""" >cur_chapter = 0 >cur_verse = 0 >collected_txt = '' ># collected XML is NOT directly convertable into Element objects, ># it should be treated more like a list of SAX-like events. ># ># xml.etree.ElementTree.fromstringlist(sequence, parser=None) ># Parses an XML document from a sequence of string fragments. ># sequence is a list or other sequence containing XML data fragments. ># parser is an optional parser instance. If not given, the standard ># XMLParser parser is used. Returns an Element instance. ># ># sequence = ["", "text"] ># element = ET.fromstringlist(sequence) ># self.assertEqual(ET.tostring(element), ># b'text') > >for child in self.root.iter(): >if child.tag in ['titulek']: >collected_txt += '\n{}\n'.format(child.text) >collected_txt += child.tail or '' >if child.tag in ['kap', 'vers']: >if collected_txt and collected_txt.strip(): >yield CollectedInfo(cur_chapter, cur_verse, >re.sub(r'[\s\n]+', ' ', collected_txt, > flags=re.DOTALL).strip()), \ >child.tail or '' > >if child.tag == 'kap': >