Vra

Wanneer moet jy gebruik generator uitdrukkings en wanneer moet jy gebruik om'n lys van comprehensions in Python?

# Generator expression
(x*2 for x in range(256))

# List comprehension
[x*2 for x in range(256)]
Was dit nuttig?

Oplossing

Johannes se antwoord is goed (die lys comprehensions is beter wanneer jy wil om te itereer oor iets wat verskeie kere).Egter, dit is ook die moeite werd om daarop te let dat jy moet gebruik om'n lys as jy wil om te gebruik enige van die lys metodes.Byvoorbeeld, die volgende kode sal nie werk nie:

def gen():
    return (something for something in get_some_stuff())

print gen()[:2]     # generators don't support indexing or slicing
print [5,6] + gen() # generators can't be added to lists

Basies, die gebruik van'n kragopwekker uitdrukking as al wat jy doen is iterating keer.As jy wil stoor en gebruik die resultate gegenereer, dan is jy waarskynlik beter af met'n lys begrip.

Sedert prestasie is die mees algemene rede om van te kies die een oor die ander, my raad is om nie bekommerd wees oor dit en net kies een;as jy vind dat jou program loop te stadig, dan en slegs dan moet jy terug gaan en bekommerd wees oor tuning jou kode.

Ander wenke

iterating oor die kragopwekker uitdrukking of die lys begrip sal doen dieselfde ding. Maar die lys begrip sal die hele lys ter nagedagtenis eerste skep terwyl die kragopwekker uitdrukking sal die items op die vlieg te skep, sodat jy in staat is om dit te gebruik vir 'n baie groot is ( en ook oneindige!) rye.

Gebruik lys begripstoetse wanneer die gevolg moet word herhaal oor meer as een keer, of waar spoed is uiters belangrik. Gebruik kragopwekker uitdrukkings waar die reeks is groot of oneindig.

Die belangrike punt is dat die lys begrip skep 'n nuwe lys. Die kragopwekker skep 'n iterable voorwerp wat sal "filter" die bronmateriaal on-the-fly as jy die stukkies verteer.

Verbeel jou jy het 'n 2TB log lêer met die naam "hugefile.txt", en jy die inhoud en lengte vir al die lyne wat begin met die woord "inskrywing" wil.

So jy probeer begin deur 'n lys begrip:

logfile = open("hugefile.txt","r")
entry_lines = [(line,len(line)) for line in logfile if line.startswith("ENTRY")]

Dit slurps die hele lêer, verwerk elke lyn, en stoor die ooreenstemmende lyne in jou skikking. Hierdie verskeidenheid kan dus bevat tot 2TB van inhoud. Dit is 'n baie RAM, en waarskynlik nie prakties vir jou doeleindes.

So in plaas kan ons 'n kragopwekker gebruik om 'n "filter" van toepassing op ons inhoud. Geen data is eintlik lees totdat ons begin iterating oor die uitslag.

logfile = open("hugefile.txt","r")
entry_lines = ((line,len(line)) for line in logfile if line.startswith("ENTRY"))

Nie eens 'n enkele lyn is nog lees van ons lêer. Om die waarheid te sê ons wil ons gevolg nog verder te filtreer:

long_entries = ((line,length) for (line,length) in entry_lines if length > 80)

Nog niks is te lees, maar ons het gespesifiseer nou twee kragopwekkers wat sal optree op ons data as ons wil.

Kom skryf uit ons gefiltreer lyne na 'n ander lêer:

outfile = open("filtered.txt","a")
for entry,length in long_entries:
    outfile.write(entry)

Nou lees ons die insette lêer. As ons for lus gaan voort om bykomende lyne versoek, die long_entries kragopwekker vereis lyne van die entry_lines kragopwekker, terugkeer net diegene wie se lengte is groter as 80 karakters. En op sy beurt, die entry_lines kragopwekker versoek lyne (gefiltreer soos aangedui) vanaf die logfile iterator, wat op sy beurt die lêer lees.

So in plaas van "stoot" data om jou uitset funksie in die vorm van 'n ten volle bevolk lys, jy gee die uitset funksie 'n manier om data "trek" net vir sy nodig. Dit is in ons geval baie meer doeltreffend, maar nie heeltemal so buigsaam. Kragopwekkers is een manier, een pass; die data van die log lêer ons gelees het kry dadelik weggegooi, so ons kan nie terug te gaan na 'n vorige lyn. Aan die ander kant, het ons nie hoef te bekommer oor die behoud van data rondom sodra ons klaar is met dit.

Die voordeel van 'n kragopwekker uitdrukking is dat dit minder geheue gebruik, aangesien dit die hele lys nie gelyktydig nie bou. Kragopwekker uitdrukkings is die beste gebruik wanneer die lys is 'n tussenganger, soos die WHALM resultate, of die skep van 'n dict uit die resultate.

Byvoorbeeld:

sum(x*2 for x in xrange(256))

dict( ((k, some_func(k) for k in some_list_of_keys) )

Die voordeel is daar dat die lys nie volledig is gegenereer, en dus min geheue gebruik (en moet ook vinniger wees)

Jy moet egter gebruik lys begripstoetse wanneer die verlangde eindproduk is 'n lys. Jy is nie van plan om enige memeory red met behulp kragopwekker uitdrukkings, aangesien jy die gegenereerde lys. Jy kry ook die voordeel dat dit in staat is om enige van die lys funksies te gebruik soos gesorteer of omgekeer.

Byvoorbeeld:

reversed( [x*2 for x in xrange(256)] )

As jy 'n kragopwekker van 'n wispelturig voorwerp (soos 'n lys) daarvan bewus wees dat die kragopwekker sal kry geëvalueer op die toestand van die lys ten tye van die gebruik van die kragopwekker, nie ten tye van die skepping van die kragopwekker:

>>> mylist = ["a", "b", "c"]
>>> gen = (elem + "1" for elem in mylist)
>>> mylist.clear()
>>> for x in gen: print (x)
# nothing

As daar enige kans van jou lys om gemodifiseerde (of 'n wispelturig voorwerp binne die lys), maar jy die staat nodig het by die skepping van die kragopwekker wat jy nodig het om 'n lys begrip in plaas gebruik.

Ek gebruik die Hadoop Mincemeat module . Ek dink dit is 'n goeie voorbeeld van 'n kennis te neem:

import mincemeat

def mapfn(k,v):
    for w in v:
        yield 'sum',w
        #yield 'count',1


def reducefn(k,v): 
    r1=sum(v)
    r2=len(v)
    print r2
    m=r1/r2
    std=0
    for i in range(r2):
       std+=pow(abs(v[i]-m),2)  
    res=pow((std/r2),0.5)
    return r1,r2,res

Hier kry die kragopwekker getalle uit 'n tekslêer (so groot soos 15 GB) en geld eenvoudige wiskunde op daardie getalle deur gebruik te maak Hadoop se kaart-verminder. As ek nie die opbrengs funksie gebruik het, maar in plaas daarvan 'n lys begrip, sou dit 'n baie lang tyd die berekening van die bedrae en gemiddelde geneem (nie die ruimte kompleksiteit noem).

Hadoop is 'n goeie voorbeeld vir die gebruik van al die voordele van Generators.

Soms kan jy wegkom met die tee funksie van kry itertools , dit gee verskeie iterators vir dieselfde kragopwekker wat onafhanklik kan gebruik word.

hoe oor die gebruik [(exp vir x in iter)] aan die goeie van beide kry. Prestasie van kragopwekker begrip asook lys metodes

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top