Brug af Python list comprehensions notation

Forretning

I Python er det nemt at bruge list comprehensions notation, når man genererer en ny liste.(List comprehensions)

I denne artikel vil vi først diskutere følgende

  • Grundlæggende type notation af listeforståelse
  • Notation af listeforståelse med betinget forgrening ved if
  • Kombination med ternære operatorer (if else-lignende behandling)
  • zip(),enumerate()Kombination med disse
  • notation for inddragelse af indlejrede lister

Dernæst forklarer vi sæt af listeforståelsesnotationer med kodeeksempler.

  • notation af sæt inklusion(Set comprehensions)
  • notation af ordbogsinddragelse(Dict comprehensions)
  • generator type(Generator expressions)

Grundlæggende type notation af listeforståelse

Notationen for listeforståelse skrives på følgende måde.

[Expression for Any Variable Name in Iterable Object]

Den tager hvert element i et iterbart objekt som f.eks. en liste, tupel eller rækkevidde med et vilkårligt variabelnavn og evaluerer det med et udtryk. En ny liste med evalueringsresultatet som et element returneres.

Der er givet et eksempel sammen med en tilsvarende for-angivelse.

squares = [i**2 for i in range(5)]
print(squares)
# [0, 1, 4, 9, 16]
squares = []
for i in range(5):
    squares.append(i**2)

print(squares)
# [0, 1, 4, 9, 16]

Den samme proces kan gøres med map(), men list comprehension-notationen foretrækkes på grund af dens enkelhed og klarhed.

Notation af listeforståelse med betinget forgrening ved if

Det er også muligt at foretage betinget forgrening med if. Skriv if i postfixet på følgende måde.

[Expression for Any Variable Name in Iterable Object if Conditional Expression]

Kun de elementer i det iterable objekt, hvis betingede udtryk er sandt, evalueres af udtrykket, og en ny liste, hvis elementer er resultatet, returneres.

Du kan bruge et hvilket som helst variabelnavn i det betingede udtryk.

Der er givet et eksempel sammen med en tilsvarende for-angivelse.

odds = [i for i in range(10) if i % 2 == 1]
print(odds)
# [1, 3, 5, 7, 9]
odds = []
for i in range(10):
    if i % 2 == 1:
        odds.append(i)

print(odds)
# [1, 3, 5, 7, 9]

Den samme proces kan udføres med filter(), men notationen med listeforståelse foretrækkes på grund af dens enkelhed og klarhed.

Kombination med ternære operatorer (if else-lignende behandling)

I eksemplet ovenfor behandles kun de elementer, der opfylder kriterierne, og de elementer, der ikke opfylder kriterierne, udelukkes fra den nye liste.

Hvis du ønsker at skifte proces afhængigt af betingelsen, eller hvis du ønsker at behandle elementer, der ikke opfylder betingelsen, anderledes, som i if else, skal du bruge den ternære operatør.

I Python kan den ternære operatør skrives på følgende måde

Value When True if Conditional Expression else Value When False

Dette bruges i udtryksdelen af listeforståelsesnotationen som vist nedenfor.

[Value When True if Conditional Expression else Value When False for Any Variable Name in Iterable Object]

Der er givet et eksempel sammen med en tilsvarende for-angivelse.

odd_even = ['odd' if i % 2 == 1 else 'even' for i in range(10)]
print(odd_even)
# ['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']
odd_even = []
for i in range(10):
    if i % 2 == 1:
        odd_even.append('odd')
    else:
        odd_even.append('even')

print(odd_even)
# ['even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd']

Det er også muligt at skrive udtryk ved hjælp af vilkårlige variabelnavne for de sande og falske værdier.

Hvis betingelsen er opfyldt, udføres der en behandling, ellers forbliver værdien af det oprindelige iterable-objekt uændret.

odd10 = [i * 10 if i % 2 == 1 else i for i in range(10)]
print(odd10)
# [0, 10, 2, 30, 4, 50, 6, 70, 8, 90]

Kombination med zip() og enumerate()

Nyttige funktioner, der ofte bruges i for-erklæringen, omfatter zip(), der kombinerer flere iterables, og enumerate(), der returnerer en værdi sammen med dens indeks.

Det er naturligvis muligt at bruge zip() og enumerate() med list comprehension notation. Det er ikke en speciel syntaks, og det er ikke svært, hvis man tænker på korrespondancen med for-erklæringen.

Eksempel på zip().

l_str1 = ['a', 'b', 'c']
l_str2 = ['x', 'y', 'z']

l_zip = [(s1, s2) for s1, s2 in zip(l_str1, l_str2)]
print(l_zip)
# [('a', 'x'), ('b', 'y'), ('c', 'z')]
l_zip = []
for s1, s2 in zip(l_str1, l_str2):
    l_zip.append((s1, s2))

print(l_zip)
# [('a', 'x'), ('b', 'y'), ('c', 'z')]

Eksempel på enumerate().

l_enu = [(i, s) for i, s in enumerate(l_str1)]
print(l_enu)
# [(0, 'a'), (1, 'b'), (2, 'c')]
l_enu = []
for i, s in enumerate(l_str1):
    l_enu.append((i, s))

print(l_enu)
# [(0, 'a'), (1, 'b'), (2, 'c')]

Ideen er den samme som tidligere, når du bruger if.

l_zip_if = [(s1, s2) for s1, s2 in zip(l_str1, l_str2) if s1 != 'b']
print(l_zip_if)
# [('a', 'x'), ('c', 'z')]

Hvert element kan også bruges til at beregne et nyt element.

l_int1 = [1, 2, 3]
l_int2 = [10, 20, 30]

l_sub = [i2 - i1 for i1, i2 in zip(l_int1, l_int2)]
print(l_sub)
# [9, 18, 27]

notation for inddragelse af indlejrede lister

Ligesom for-sløjfer kan list comprehension-notationen også være indlejret i hinanden.

[Expression for Variable Name 1 in Iterable Object 1
    for Variable Name 2 in Iterable Object 2
        for Variable Name 3 in Iterable Object 3 ... ]

For nemheds skyld er der tilføjet linjeskift og indrykninger, men de er ikke nødvendige for grammatikken; de kan fortsætte på en enkelt linje.

Der er givet et eksempel sammen med en tilsvarende for-angivelse.

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

flat = [x for row in matrix for x in row]
print(flat)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
flat = []
for row in matrix:
    for x in row:
        flat.append(x)

print(flat)
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Det er også muligt at bruge flere variabler.

cells = [(row, col) for row in range(3) for col in range(2)]
print(cells)
# [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]

Du kan også lave betinget forgrening.

cells = [(row, col) for row in range(3)
         for col in range(2) if col == row]
print(cells)
# [(0, 0), (1, 1)]

Det er også muligt at foretage en betinget forgrening for hvert iterbart objekt.

cells = [(row, col) for row in range(3) if row % 2 == 0
         for col in range(2) if col % 2 == 0]
print(cells)
# [(0, 0), (2, 0)]

notation af sæt inklusion(Set comprehensions)

Ved at ændre firkantede parenteser [] i listeforståelsesnotationen til krøllede parenteser {} oprettes et sæt (objekt af sæt-typen).

{Expression for Any Variable Name in Iterable Object}
s = {i**2 for i in range(5)}

print(s)
# {0, 1, 4, 9, 16}

notation af ordbogsinddragelse(Dict comprehensions)

Ordbøger (objekter af typen dict) kan også genereres med comprehension notation.

{}, og angiv nøgle og værdi i udtryksdelen som nøgle: værdi.

{Key: Value for Any Variable Name in Iterable Object}

Der kan angives et hvilket som helst udtryk for nøgle og værdi.

l = ['Alice', 'Bob', 'Charlie']

d = {s: len(s) for s in l}
print(d)
# {'Alice': 5, 'Bob': 3, 'Charlie': 7}

Hvis du vil oprette en ny ordbog ud fra en liste med nøgler og værdier, skal du bruge funktionen zip() for at oprette en ny ordbog.

keys = ['k1', 'k2', 'k3']
values = [1, 2, 3]

d = {k: v for k, v in zip(keys, values)}
print(d)
# {'k1': 1, 'k2': 2, 'k3': 3}

generator type(Generator expressions)

Hvis firkantede parenteser [] i list comprehensions notation anvendes som runde parenteser (), returneres en generator i stedet for en tupel. Dette kaldes generatorudtryk.

Eksempel på en listeforståelsesnotation.

l = [i**2 for i in range(5)]

print(l)
# [0, 1, 4, 9, 16]

print(type(l))
# <class 'list'>

Eksempel på et generatorudtryk. Hvis du printer() generatoren som den er, vil den ikke udskrive indholdet, men hvis du kører den med en for-anvisning, kan du få indholdet.

g = (i**2 for i in range(5))

print(g)
# <generator object <genexpr> at 0x10af944f8>

print(type(g))
# <class 'generator'>

for i in g:
    print(i)
# 0
# 1
# 4
# 9
# 16

Generatorudtryk tillader også betinget forgrening og indlejring ved hjælp af if- og list comprehension-notation.

g_cells = ((row, col) for row in range(0, 3)
           for col in range(0, 2) if col == row)

print(type(g_cells))
# <class 'generator'>

for i in g_cells:
    print(i)
# (0, 0)
# (1, 1)

Hvis en liste med et stort antal elementer f.eks. genereres ved hjælp af list comprehension notation og derefter gennemløbes med en for-anvisning, vil listen med alle elementerne blive genereret i begyndelsen, hvis list comprehension notation anvendes. Hvis du derimod bruger et generatorudtryk, genereres elementerne et efter et, hver gang løkken gentages, hvilket reducerer den anvendte hukommelse.

Hvis generatorudtrykket er det eneste argument for funktionen, kan de runde parenteser () udelades.

print(sum([i**2 for i in range(5)]))
# 30

print(sum((i**2 for i in range(5))))
# 30

print(sum(i**2 for i in range(5)))
# 30

Med hensyn til behandlingshastighed er listeforståelsesnotationen ofte hurtigere end generatornotationen, når alle elementer er behandlet.

Når man f.eks. dømmer med all() eller any(), bestemmes resultatet dog, når der er false eller true, så det kan være hurtigere at bruge generatorudtryk end at bruge list comprehension notation.

Der findes ingen tupelforståelsesnotation, men hvis du bruger et generatorudtryk som et argument for tuple(), kan du generere en tupel i forståelsesnotationen.

t = tuple(i**2 for i in range(5))

print(t)
# (0, 1, 4, 9, 16)

print(type(t))
# <class 'tuple'>
Copied title and URL