Hvordan bruke utpakkingsoperatørene (*, **) i Python?

Python er det mest brukte programmeringsspråket. I dag vil du lære å bruke en av kjernefunksjonene – men ofte ignorert – ved å pakke ut i Python.

Du har sannsynligvis sett * og ** i andres kode eller til og med brukt dem uten å vite hva formålet er. Vi skal gå gjennom konseptet med utpakking, og hvordan du bruker det til å skrive mer pytonisk kode.

Her er en liste over konsepter som du vil finne nyttige mens du leser denne opplæringen:

  • Iterable: Enhver sekvens som kan itereres av en for-loop, som sett, lister, tuples og ordbøker
  • Callable: Et Python-objekt som kan kalles ved hjelp av dobbel parentes (), for eksempel myfunction()
  • Shell: Interaktivt kjøretidsmiljø som lar oss kjøre Python-kode. Vi kan kalle det ved å kjøre «python» i en terminal
  • Variabel: Symbolsk navn som lagrer et objekt og har en reservert minneplassering.

La oss starte med den hyppigste forvirringen: Asteristikk i Python er også aritmetiske operatorer. En stjerne

brukes til multiplikasjon, mens to av dem (**) refererer til eksponentiering.

>>> 3*3
9
>>> 3**3
27

Vi kan bevise det ved å åpne et Python-skall og skrive:

Merk: Du må ha Python 3 installert for å følge denne opplæringen. Hvis du ikke har den installert, sjekk ut vår Python-installasjonsveiledning.

Som du kan se, bruker vi stjernen etter det første tallet og før det andre. Når du ser dette, betyr det at vi bruker aritmetiske operatorer.

>>> *range(1, 6),
(1, 2, 3, 4, 5)
>>> {**{'vanilla':3, 'chocolate':2}, 'strawberry':2}
{'vanilla': 3, 'chocolate': 2, 'strawberry': 2}

På den annen side bruker vi stjernene (*, **) før en iterable for å pakke den ut – for eksempel:

Ikke bekymre deg hvis du ikke får det, dette er bare en innledning til utpakking i Python. Så fortsett og les hele veiledningen!

Hva er det som pakker ut?

Utpakking er prosessen med å få ut ting – iterables som lister, tuples og ordbøker. Tenk på det som å åpne en boks og få ut forskjellige ting som kabler, hodetelefoner eller en USB.

  Fix Kan ikke finne Logg på Hypixel Minecraft Server and Maps

Å pakke ut i Python ligner på å pakke ut en boks i det virkelige liv.

>>> mybox = ['cables', 'headphones', 'USB']
>>> item1, item2, item3 = mybox

La oss oversette det samme eksemplet til kode for en bedre forståelse:

Som du kan se, tildeler vi de tre elementene i mybox-listen til tre variabler item1, item2, item2. Denne typen variabeltildeling er det grunnleggende konseptet med utpakking i Python.

>>> item1
'cables'
>>> item2
'headphones'
>>> item3
'USB'

Hvis du prøver å finne verdien av hver vare, vil du legge merke til at item1, refererer til «kabler», item2, refererer til «hodetelefoner» og så videre.

>>> newbox = ['cables', 'headphones', 'USB', 'mouse']
>>> item1, item2, item3 = newbox
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 3)

Inntil her ser alt ut til å være helt fint med denne koden, men hva om vi ønsket å pakke ut en liste med flere elementer i den – beholde samme mengde tilordnede variabler?

Det er sannsynligvis du forventet denne typen feil. I hovedsak tildeler vi 4 listeelementer til tre variabler, hvordan klarer Python å tilordne de riktige verdiene? Det gjør det ikke, det er fordi vi får en ValueError

med meldingen «for mange verdier å pakke ut». Dette skjer fordi vi setter tre variabler til venstre, og fire verdier (tilsvarende newbox-listen) til høyre.

>>> lastbox = ['cables', 'headphones']
>>> item1, item2, item3 = lastbox
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 2)

Hvis du prøver å gjøre en lignende prosess, men med flere variabler enn verdier å pakke ut, får du en annen ValueError bortsett fra at med en litt annen melding:

Merk: Vi har jobbet med lister, men du kan bruke denne formen for utpakking med alle gjentakbare (lister, sett, tuples, ordbøker)

Så hvordan overvinner vi denne situasjonen? Er det noen måte å pakke ut alle elementene i en iterable til et par variabler uten å få noen feil?

Klart det er det, og det kalles utpakkingsoperatør eller stjerneoperatør (*, **). La oss se hvordan du bruker det i Python.

Hvordan pakke ut lister med *-operatøren

Stjerneoperatøren

>>> first, *unused, last = [1, 2, 3, 5, 7]
>>> first
1
>>> last
7
>>> unused
[2, 3, 5]

brukes til å pakke ut alle verdiene til en iterable som ikke er tildelt ennå.

>>> first, *_, last = [1, 2, 3, 5, 7]
>>> _
[2, 3, 5]

La oss anta at du vil få det første og siste elementet i en liste uten å bruke indekser, vi kan gjøre det med stjerneoperatoren:

>>> first, *_, last = [1, 2]
>>> first
1
>>> last
2
>>> _
[]

Som du skjønner, får vi alle de ubrukte verdiene med stjerneoperatøren. Den foretrukne måten å forkaste verdier på er å bruke en understrekvariabel (_), som noen ganger brukes som en «dummy-variabel».

  Hvordan fikse PS4 feilkoder SU-30746-0, SU-42118-6

Vi kan fortsatt bruke dette trikset selv om listen bare har to elementer:

I dette tilfellet lagrer understrekvariabelen (dummy-variabelen) en tom liste slik at de to andre variablene rundt dem kan få tilgang til de tilgjengelige verdiene i listen.

>>> *string = 'PythonIsTheBest'

Vanlig feilsøking

>>> *string = 'PythonIsTheBest'
  File "<stdin>", line 1
SyntaxError: starred assignment target must be in a list or tuple

Vi kan pakke ut et unikt element av en iterable. Du vil for eksempel komme opp med noe slikt: Imidlertid vil koden ovenfor returnere en SyntaxError:Dette fordi i følge

PEP-spesifikasjon

:

>>> *string, = 'PythonIsTheBest'
>>> string
['P', 'y', 't', 'h', 'o', 'n', 'I', 's', 'T', 'h', 'e', 'B', 'e', 's', 't']

En tuppel (eller liste) på venstre side av en enkel oppgave

>>> *numbers, = range(5)
>>> numbers
[0, 1, 2, 3, 4]

Hvis vi ønsker å pakke ut alle verdiene til en iterabel til en enkelt variabel, må vi sette opp en tuppel, derfor vil det være nok å legge til et enkelt komma:

Et annet eksempel vil være å bruke rekkeviddefunksjonen, som returnerer en rekke tall.

Nå som du vet hvordan du pakker ut lister og tupler med en stjerne, er det på tide å sette seg inn i utpakking av ordbøker.

Hvordan pakke ut ordbøker med **-operatør

>>> **greetings, = {'hello': 'HELLO', 'bye':'BYE'} 
...
SyntaxError: invalid syntax

Mens en enkelt stjerne brukes til å pakke ut lister og tupler, brukes dobbeltstjernen (**) til å pakke ut ordbøker.

>>> food = {'fish':3, 'meat':5, 'pasta':9} 
>>> colors = {'red': 'intensity', 'yellow':'happiness'}
>>> merged_dict = {**food, **colors}
>>> merged_dict
{'fish': 3, 'meat': 5, 'pasta': 9, 'red': 'intensity', 'yellow': 'happiness'}

Dessverre kan vi ikke pakke ut en ordbok til en enkelt variabel slik vi har gjort med tupler og lister. Det betyr at følgende vil gi en feil:

Vi kan imidlertid bruke **-operatøren inne i callables og andre ordbøker. For eksempel, hvis vi ønsker å lage en sammenslått ordbok, laget av andre ordbøker, kan vi bruke koden nedenfor:

Dette er en ganske kort måte å lage sammensatte ordbøker på, men dette er ikke hovedmetoden for utpakking i Python.

La oss se hvordan vi kan bruke utpakking med callables

Pakking i funksjoner: args og kwargs

Du har sikkert sett args og kwargs før enten implementert på klasser eller funksjoner. La oss se hvorfor vi trenger å bruke dem sammen med callables.

>>> def product(n1, n2):
...     return n1 * n2
... 
>>> numbers = [12, 1]
>>> product(*numbers)
12

Pakking med *-operatøren (args)

>>> product(12, 1)
12

Anta at vi har en funksjon som beregner produktet av to tall.

>>> numbers = [12, 1, 3, 4]
>>> product(*numbers)
...
TypeError: product() takes 2 positional arguments but 4 were given

Som du kan se, pakker vi ut listenumrene til funksjonen, så vi kjører faktisk følgende:

>>> def product(*args):
...     result = 1
...     for i in args:
...             result *= i
...     return result
...
>>> product(*numbers)
144

Inntil her fungerer alt helt fint, men hva om vi ville passere en lengre liste? Det vil sikkert gi en feil fordi funksjonen mottar flere argumenter enn den er i stand til å håndtere.

  Affiliate markedsføring vs. Nettverksmarkedsføring: Kjenn forskjellen

Vi kan løse alt dette bare ved å pakke listen direkte på funksjonen, noe som skaper en iterabel inne i den og lar oss sende et hvilket som helst antall argumenter til funksjonen.

Her behandler vi args-parameteren som en iterabel, går på tvers av elementene og returnerer produktet av alle tallene. Legg merke til hvordan startnummeret til resultatet må være ett fordi hvis vi starter med null, vil funksjonen alltid returnere null. Merk: args er bare en konvensjon, du kan bruke et hvilket som helst annet parameternavnVi kunne også sende vilkårlige tall til funksjonen uten å bruke en liste, akkurat som med den innebygde

>>> product(5, 5, 5)
125
>>> print(5, 5, 5)
5 5 5

utskriftsfunksjon

>>> def test_type(*args):
...     print(type(args))
...     print(args)
... 
>>> test_type(1, 2, 4, 'a string')
<class 'tuple'>
(1, 2, 4, 'a string')

.

Til slutt, la oss få objekttypen til argene til en funksjon.

Som nevnt i koden ovenfor, vil typen args alltid være tuppel, og innholdet i den vil være alle argumentene uten nøkkelord som sendes til funksjonen.

Pakking med **-operatøren (kwargs)

>>> def make_person(name, **kwargs):
...     result = name + ': '
...     for key, value in kwargs.items():
...             result += f'{key} = {value}, '
...     return result
... 
>>> make_person('Melissa', id=12112, location='london', net_worth=12000)
'Melissa: id = 12112, location = london, net_worth = 12000, '

Som vi så tidligere, brukes **-operatoren utelukkende for ordbøker. Dette betyr at med denne operatøren er vi i stand til å sende nøkkel-verdi-par til funksjonen som en parameter.

La oss lage en funksjon make_person, som mottar et posisjonsargument «navn», og en udefinert mengde nøkkelordargumenter.

Som du kan se, konverterer **kwargs-setningen alle søkeordargumentene til en ordbok, som vi kan iterere inne i funksjonen.

>>> def test_kwargs(**kwargs):
...     print(type(kwargs))
...     print(kwargs)
... 
>>> test_kwargs(random=12, parameters=21)
<class 'dict'>
{'random': 12, 'parameters': 21}

Merk: kwargs er bare en konvensjon du kan navngi denne parameteren med hva du vil

Vi kan sjekke typen kwargs på samme måte som vi gjorde med args:

>>> def my_final_function(*args, **kwargs):
...     print('Type args: ', type(args))
...     print('args: ', args)
...     print('Type kwargs: ', type(kwargs))
...     print('kwargs: ', kwargs)
... 
>>> my_final_function('Python', 'The', 'Best', language="Python", users="A lot")
Type args:  <class 'tuple'>
args:  ('Python', 'The', 'Best')
Type kwargs:  <class 'dict'>
kwargs:  {'language': 'Python', 'users': 'A lot'}

Den interne variabelen kwargs blir alltid en ordbok, som lagrer nøkkelverdi-parene som sendes til funksjonen.

Til slutt, la oss bruke args og kwargs i samme funksjon:

Konklusjon

  • Utpakkingsoperatører er veldig nyttige i daglige oppgaver, nå vet du hvordan du bruker dem både i individuelle utsagn og funksjonsparametere.
  • I denne opplæringen lærte du:
  • Du bruker * for tupler og lister og ** for ordbøker
  • Du kan bruke utpakkingsoperatorer i funksjons- og klassekonstruktører

args brukes til å sende parametere uten nøkkelord til funksjonerkwargs brukes til å sende nøkkelorddefinerte parametere til funksjoner.