élet egy számítógépes tudós

korábban ma, azt mondtam egy munkatársa, hogy újra.a Pythonban a Finditer () általában a bemenet tokenizálásának előnyben részesített módja, nem pedig a lexer kézi görgetése egy iterálható karakterből. Azt mondta, hogy az egész fájlt el kell olvasni a memóriában. A helyszínen szégyenlősen azt mondtam, hogy valószínűleg sorról sorra elolvashatja, és felhívhatja re-t.finditer () ismételten, ha a token regexp nem kereszt vonal határ.
ez igaz, de nem jó válasz. Kiderül, hogy egy láncolt re építése.finditer () egy iterable húrok lehetséges, bár nem egészen egyértelmű.
az első kísérlet itt bemutatja a fő gondolatot: mivel re.finditer () mérkőzések nem átfedő, miután minden mérkőzés kimerült, a következő re.finditer () kell folytatni a fennmaradó páratlan karakterlánc.

def finditer_chained_bad(pattern, strings, flags=0): last = '' for s in strings: m = None for m in re.finditer(pattern, last + s, flags): yield m if not m: last = '' ##1 continue # m is the last match object. last = s

a ##1 megjegyzéssel ellátott sor vitatható pont lehet. Ha újra.a finditer () nem hozott egyezést, a végrehajtási döntés itt az s teljes elvetése, feltételezve, hogy abban semmi sem egyezik meg, de vitatható, hogy egy potenciális mérkőzés átlépheti a bemeneti karakterlánc határát. Ha ezt last += s – ra változtatnánk, akkor működne, ha a potenciális egyezés átlépné a bemeneti határt, a korlátlan memória növekedésének rovására, ha a bemenet hosszú tartománya soha nem eredményezett egyezést. A korlátlan növekedésre azért van szükség, mert ez azt jelenti, hogy a potenciális egyezés nagyobb, mint a bemeneti darab mérete, tehát a Teljes egyezés elérése érdekében, dinamikusan növelnünk kell a darab méretét, amit itt csinálunk.
további probléma, hogy az utolsó egyezés Lehet egy részleges egyezés, amely a következő karakterláncban folytatódik. Ha naiv módon adjuk meg, a hívó fél törött részleges egyezést kap. Ennek szemléltetésére tegyük fel, hogy a bemenet 8 karakterláncra van tagolva:

def main(): for m in finditer_chained_bad(r'\w+', ): print m.group(0)

kinyomtatja:

helloworld

a “világ” szó tévedésből két mérkőzésre oszlik a karakterlánc határa miatt. Ennek kijavításához csak el kell halasztanunk az utolsó mérkőzést, és újra kell indítanunk a következő re-t.finditer () elejétől az utolsó mérkőzés. A teljes munka kód lesz:

def finditer_chained(pattern, strings, flags=0): last_s = '' for s in strings: last_m = None last_s += s for m in re.finditer(pattern, last_s, flags): if last_m: yield last_m last_m = m if not last_m: continue assert last_m is m last_s = s if last_m: yield last_m

és helyesen kiírja:

helloworld

az eredményül kapott finditer_chained() Elfogad egy fájlszerű objektumot, mert a fájl sorokból iterálható, mintha re lenne.a finditer () a teljes fájlra vonatkozik. Úgy működik, hogy nem olvassa el az egész fájlt a memóriában.



+