A kicsomagolás során egy gyűjtemény, például egy list, tuple vagy dict elemeit nyered ki iterációval.
A kicsomagolt értékeket ezután ugyanabban az utasításban rendelheted változókhoz, amit általában többszörös értékadásnak neveznek.
A speciális * és ** operátort gyakran használjuk kicsomagolásnál és többszörös értékadásnál.
A *<variable_name> és a **<variable_name> nem tévesztendő össze a * és a ** operátorral. Míg a * a szorzásra, a ** a hatványozásra szolgál, addig a *<variable_name> és a **<variable_name> a becsomagolás és a kicsomagolás operátora.
Többszörös értékadásnál az értékadás operátor (=) bal oldalán lévő változók számának meg kell egyeznie a jobb oldalon lévő értékek számával.
Az értékek elválasztásához vesszőt , használj:
>>> a, b = 1, 2
>>> a
1
Ha a többszörös értékadásnál a megadott értékekhez nem megfelelő számú változó tartozik, ValueError hibát kapsz:
>>> x, y, z = 1, 2
ValueError: too many values to unpack (expected 3, got 2)
A többszörös értékadás nem korlátozódik egyetlen adattípusra:
>>> x, y, z = 1, "Hello", True
>>> x
1
>>> y
'Hello'
>>> z
True
A többszörös értékadást lists elemeinek felcserélésére is használhatod.
Ez a gyakorlat meglehetősen elterjedt a rendezési algoritmusokban.
Például:
>>> numbers = [1, 2]
>>> numbers[0], numbers[1] = numbers[1], numbers[0]
>>> numbers
[2, 1]
Mivel a tuples megváltoztathatatlan, egy tuple elemeit nem cserélheted fel.
Az alábbi példák lists-et használnak, de ugyanezek a fogalmak érvényesek a tuples-re is.
Pythonban kicsomagolhatod a list/tuple/dictionary elemeit különálló változókba.
Mivel az értékek egy meghatározott sorrendben szerepelnek a lists/tuples-ben, ugyanabban a sorrendben csomagolódnak ki a változókba:
>>> fruits = ["apple", "banana", "cherry"]
>>> x, y, z = fruits
>>> x
"apple"
Ha vannak olyan értékek, amelyekre nincs szükséged, _ jellel jelölheted őket:
>>> fruits = ["apple", "banana", "cherry"]
>>> _, _, z = fruits
>>> z
"cherry"
Egy list vagy tuple belsejében lévő list/tuple értékeinek kicsomagolása és értékadása (más néven egymásba ágyazott lista/tuple) ugyanúgy működik, mint a sekély kicsomagolás, de gyakran minősítőkre van szükség a kontextus vagy a pozíció tisztázásához:
>>> fruits_vegetables = [["apple", "banana"], ["carrot", "potato"]]
>>> [[a, b], [c, d]] = fruits_vegetables
>>> a
"apple"
>>> d
"potato"
Egy egymásba ágyazott list/tuple-nek akár csak egy részét is mélyen kicsomagolhatod:
>>> fruits_vegetables = [["apple", "banana"], ["carrot", "potato"]]
>>> [a, [c, d]] = fruits_vegetables
>>> a
["apple", "banana"]
>>> c
"carrot"
Ha a kicsomagolásnál a változók helytelenül helyezkednek el, illetve nem megfelelő számú érték van, ValueError hibát kapsz:
>>> fruits_vegetables = [["apple", "banana"], ["carrot", "potato"]]
>>> [[a, b], [d]] = fruits_vegetables
ValueError: too many values to unpack (expected 1)
*-galAmikor kicsomagolsz egy list/tuple-t, a * operátorral elkaphatod a „maradék” értékeket.
Ez áttekinthetőbb, mint a list/tuple szeletelése (ami bizonyos helyzetekben kevésbé olvasható).
Például az első elem kinyerhető, majd a maradék értékek egy új list-be kerülhetnek az első elem nélkül:
>>> fruits = ["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
>>> x, *last = fruits
>>> x
"apple"
>>> last
["banana", "cherry", "orange", "kiwi", "melon", "mango"]
Kinyerheted a list elején és végén lévő értékeket is, miközben az összes középső értéket egy csoportba fogod össze:
>>> fruits = ["apple", "banana", "cherry", "orange", "kiwi", "melon", "mango"]
>>> x, *middle, y, z = fruits
>>> y
"melon"
>>> middle
["banana", "cherry", "orange", "kiwi"]
A *-ot mély kicsomagolásnál is használhatod:
>>> fruits_vegetables = [["apple", "banana", "melon"], ["carrot", "potato", "tomato"]]
>>> [[a, *rest], b] = fruits_vegetables
>>> a
"apple"
>>> rest
["banana", "melon"]
Egy szótár kicsomagolása kicsit más, mint egy list/tuple kicsomagolása.
A szótárakon való iteráció alapértelmezés szerint a kulcsokat érinti.
Ezért amikor kicsomagolsz egy dict-et, csak a kulcsokat tudod kicsomagolni, az értékeket nem:
>>> fruits_inventory = {"apple": 6, "banana": 2, "cherry": 3}
>>> x, y, z = fruits_inventory
>>> x
"apple"
Ha az értékeket is ki szeretnéd csomagolni, használhatod a <dict>.values() metódust:
>>> fruits_inventory = {"apple": 6, "banana": 2, "cherry": 3}
>>> x, y, z = fruits_inventory.values()
>>> x
6
Ha egyszerre van szükséged a kulcsokra és az értékekre, használd a <dict>.items() metódust.
A <dict>.items() egy iterálható nézetet hoz létre, amely kulcs-érték párokat tartalmaz.
Ezek egy tuple-be csomagolhatók ki:
>>> fruits_inventory = {"apple": 6, "banana": 2, "cherry": 3}
>>> x, y, z = fruits_inventory.items()
>>> x
("apple", 6)
A becsomagolás során több értéket egyetlen list-be fogsz össze, amelyet egy változóhoz rendelsz.
Ez akkor hasznos, ha ki szeretnéd csomagolni az értékeket, módosítanál rajtuk, majd az eredményeket vissza csomagolnád egy változóba.
Arra is lehetőséget ad, hogy két vagy több lists/tuples/dicts összefésülését elvégezd.
*-galEgy list/tuple becsomagolását a * operátorral végezheted el.
Ez az összes értéket egy list/tuple-be csomagolja.
>>> fruits = ("apple", "banana", "cherry")
>>> more_fruits = ["orange", "kiwi", "melon", "mango"]
# fruits and more_fruits are unpacked and then their elements are packed into combined_fruits
>>> combined_fruits = *fruits, *more_fruits
# If there is no * on to the left of the "=" the result is a tuple
>>> combined_fruits
("apple", "banana", "cherry", "orange", "kiwi", "melon", "mango")
# If the * operator is used on the left side of "=" the result is a list.
# Note the trailing comma.
>>> *combined_fruits_too, = *fruits, *more_fruits
>>> combined_fruits_too
['apple', 'banana', 'cherry', 'orange', 'kiwi', 'melon', 'mango']
A * bal oldali használatáról bővebben lásd a PEP 3132 dokumentumot.
**-galEgy szótár becsomagolását a ** operátorral végzed el.
Ez az egyik szótár összes kulcs-érték párját egy másik szótárba csomagolja, vagy két szótárt fűz össze.
>>> fruits_inventory = {"apple": 6, "banana": 2, "cherry": 3}
>>> more_fruits_inventory = {"orange": 4, "kiwi": 1, "melon": 2, "mango": 3}
# fruits_inventory and more_fruits_inventory are unpacked into key-values pairs and combined.
>>> combined_fruits_inventory = {**fruits_inventory, **more_fruits_inventory}
# then the pairs are packed into combined_fruits_inventory
>>> combined_fruits_inventory
{"apple": 6, "banana": 2, "cherry": 3, "orange": 4, "kiwi": 1, "melon": 2, "mango": 3}
* és a ** használata függvényekkelAmikor olyan függvényt hozol létre, amely tetszőleges számú argumentumot fogad el, a függvény definíciójában használhatod a *args vagy **kwargs szintaxist.
A *args tetszőleges számú pozíciós (nem kulcsszavas) argumentumot csomagol egy tuple-be, a **kwargs pedig tetszőleges számú kulcsszavas argumentumot csomagol egy szótárba.
A *args használata:
# This function is defined to take any number of positional arguments
>>> def my_function(*args):
... print(args)
# Arguments given to the function are packed into a tuple
>>> my_function(1, 2, 3)
(1, 2, 3)
>>> my_function("Hello")
("Hello")
>>> my_function(1, 2, 3, "Hello", "Mars")
(1, 2, 3, "Hello", "Mars")
A **kwargs használata:
# This function is defined to take any number of keyword arguments
>>> def my_function(**kwargs):
... print(kwargs)
# Arguments given to the function are packed into a dictionary
>>> my_function(a=1, b=2, c=3)
{"a": 1, "b": 2, "c": 3}
A *args és a **kwargs együtt is használható:
>>> def my_function(*args, **kwargs):
... print(sum(args))
... for key, value in kwargs.items():
... print(str(key) + " = " + str(value))
>>> my_function(1, 2, 3, a=1, b=2, c=3)
6
a = 1
b = 2
c = 3
A *args elé paramétereket is írhatsz, hogy meghatározott pozíciós argumentumokat engedj meg.
Az egyedi kulcsszavas argumentumoknak ekkor a **kwargs előtt kell szerepelniük.
Az argumentumokat így kell elrendezni:
def my_function(<positional_args>, *args, <key-word_args>, **kwargs)
Ha nem tartod be ezt a sorrendet, hibát kapsz.
>>> def my_function(a, b, *args):
... print(a)
... print(b)
... print(args)
>>> my_function(1, 2, 3, 4, 5)
1
2
(3, 4, 5)
Ha az argumentumokat helytelen sorrendben írod le, az hibát eredményez:
>>>def my_function(*args, a, b):
... print(args)
>>>my_function(1, 2, 3, 4, 5)
Traceback (most recent call last):
File "c:\something.py", line 3, in <module>
my_function(1, 2, 3, 4, 5)
TypeError: my_function() missing 2 required keyword-only arguments: 'a' and 'b'
A * segítségével egy list/tuple argumentumait csomagolhatod ki egy függvényhívásba.
Ez nagyon hasznos azoknál a függvényeknél, amelyek nem fogadnak el iterable-t:
>>> def my_function(a, b, c):
... print(c)
... print(b)
... print(a)
numbers = [1, 2, 3]
>>> my_function(*numbers)
3
2
1
A *-os kicsomagolás a beépített zip() függvénnyel együtt szintén gyakori eset.
A zip() függvény több iterálhatót vesz át, és olyan list-et ad vissza, amely tuple-okat tartalmaz, bennük az egyes iterable-ok értékei csoportosítva:
>>> values = (['x', 'y', 'z'], [1, 2, 3], [True, False, True])
>>> a, *rest = zip(*values)
>>> rest
[('y', 2, False), ('z', 3, True)]
A barátod, Linus mozdonyvezető, aki tehervonatokat vezet a városok között. Bár a vonatok kezelésében lenyűgöző, a logisztikához és a számítógépekhez nem igazán ért. Szeretné igénybe venni a programozási segítségedet a vonat részleteinek rendszerezéséhez és az útvonaladatok hibáinak kijavításához.
Ez a feladat könnyedén megoldható szeleteléssel, indexeléssel és különféle dict metódusokkal.
Mi azonban szeretnénk, ha az alábbi részfeladatok megoldása során a csomagolást, kicsomagolást és a többszörös értékadást gyakorolnád.
A barátod nyomon követte az egyes vagonok azonosítóját (ID), de soha nem tudja biztosan, hogy a rendszernek egy adott pillanatban hány vagont kell feldolgoznia.
A logisztikai program többi része számára sokkal egyszerűbb lenne, ha ezek az adatok egy egységes list-be csomagolva lennének.
Készíts egy get_list_of_wagons() függvényt, amely tetszőleges számú vagonazonosítót fogad el.
Minden azonosító egy pozitív egész szám lesz.
A függvény ezután return-nel adja vissza a kapott azonosítókat egyetlen list-ként.
>>> get_list_of_wagons(1, 7, 12, 3, 14, 8, 5)
[1, 7, 12, 3, 14, 8, 5]
Ezen a ponton kezded megismerni az adatokat, és azt, hogyan használják őket a logisztikai programban. Az azonosítórendszer a mozdonynak mindig az 1 azonosítót adja, a vonat többi vagonja pedig egy véletlenszerűen választott, 1-nél nagyobb azonosítót kap.
A barátodnak két új vagont kellett a vonathoz kapcsolnia, de elfelejtette frissíteni a rendszert!
Most a vonat list első két vagonját a végére kell mozgatni, különben felborul a sorrend.
Hogy még bonyolultabb legyen, a barátod épp felfedezett egy második list-et, amely látszólag hiányzó vagonazonosítókat tartalmaz.
Csak arra emlékszik, hogy miután az új vagonokat átmozgatták, a második list-ből származó azonosítókat közvetlenül a kijelölt mozdony után kell elhelyezni.
Linus nagyon hálás lenne neked, amiért kijavítod a hibáit, és egyesíted az adatokat.
Készíts egy fix_list_of_wagons() függvényt, amely két lists-et fogad, amelyek vagonazonosítókat tartalmaznak.
Helyezze át az első list első két elemét a végére, és szúrja be a második list értékeit a mozdony azonosítója (1) mögé (annak jobb oldalára).
A függvény ezután return-nel adja vissza a módosított list-et.
>>> fix_list_of_wagons([2, 5, 1, 7, 4, 12, 6, 3, 13], [3, 17, 6, 15])
[1, 3, 17, 6, 15, 7, 4, 12, 6, 3, 13, 2, 5]
Most, hogy minden vagonadat helyes, Linus szeretné, ha frissítenéd a rendszer útvonalinformációit.
Egy szállítási útvonalon a vonat néhány különböző állomáson is megállhat, hogy árut vegyen fel és/vagy tegyen le.
Minden út során eltérő számú ilyen közbenső átadási pont lehet.
A barátod szeretné, ha frissítenéd a rendszer útválasztási dict-jét bármilyen hiányzó/további átadási információval.
Készíts egy add_missing_stops() függvényt, amely egy útválasztási dict-et fogad, majd tetszőleges számú kulcsszóargumentumot.
Ezek az argumentumok lehetnek egy dict formájában, amely egy vagy több megállót tartalmaz, vagy tetszőleges számú stop_number=city kulcsszópár.
A függvény ezután adja vissza az útválasztási dict-et frissítve egy további key-vel, amely az összes hozzáadott megállót sorrendben tartalmazó list-et tárolja.
>>> add_missing_stops({"from": "New York", "to": "Miami"},
stop_1="Washington, DC", stop_2="Charlotte", stop_3="Atlanta",
stop_4="Jacksonville", stop_5="Orlando")
{"from": "New York", "to": "Miami", "stops": ["Washington, DC", "Charlotte", "Atlanta", "Jacksonville", "Orlando"]}
Linus az útvonalprogramon dolgozott, és észrevette, hogy bizonyos útvonalakból hiányoznak fontos részletek.
A kezdeti útvonalinformáció dict-ként épült fel, és a barátod szeretné, ha frissítenéd azt a dict-et mindazzal, ami hiányozhat.
A rendszerben minden útvonal kissé eltérő részleteket igényel, ezért Linus igazán egy általános megoldást szeretne.
Készíts egy extend_route_information() nevű függvényt, amely két dicts-et fogad.
Az első dict az indulási és célvárosokat tartalmazza, amelyek között a vonat közlekedik.
A második dict egyéb útvonalrészleteket tartalmaz, például a vonat sebességét, hosszát vagy a hőmérsékletet.
A függvénynek egy összesített dict-et kell visszaadnia az összes útvonalinformációval.
A második dict tartalmazhat a példában láthatóktól eltérő vagy további tulajdonságokat is.
>>> extend_route_information({"from": "Berlin", "to": "Hamburg"}, {"length": "100", "speed": "50"})
{"from": "Berlin", "to": "Hamburg", "length": "100", "speed": "50"}
Amikor Linus a vagondepót felmérte, észrevette, hogy a vagonok nem a megfelelő sorrendben tárolódnak. Az azonosító mellett minden vagonnak van egy színe, amely megfelel a szállított rakomány típusának. A vagonokat a depóban rácsokban tárolják, ahol a rács minden oszlopában azonos színű vagonok vannak.
A logisztikai rendszer azonban úgy mutatja a depóban tárolandó vagonok lists-jeit, hogy a soraik szín szerint vannak csoportosítva.
De ahhoz, hogy a tárolórács megfelelően működjön, minden sorban három különböző színnek kell lennie, hogy az oszlopok szín szerint igazodjanak.
A barátod szeretné, ha rendbe raknád a vagondepó lists-jeit, hogy a vagonok megfelelően tárolódjanak.
Készíts egy fix_wagon_depot() nevű függvényt, amely egy három elemből álló list-et fogad.
Minden list elem egy allista (vagy „sor”), amely három tuples-et tartalmaz.
Minden tuple egy (<wagon ID>, <wagon color>) pár.
A függvényednek vissza kell adnia egy list-et, amelyben a három „sor” lists úgy van átrendezve, hogy a vagonok a helyes pozíciókba kerüljenek.
>>> fix_wagon_depot([
[(2, "red"), (4, "red"), (8, "red")],
[(5, "blue"), (9, "blue"), (13,"blue")],
[(3, "orange"), (7, "orange"), (11, "orange")],
])
[
[(2, "red"), (5, "blue"), (3, "orange")],
[(4, "red"), (9, "blue"), (7, "orange")],
[(8, "red"), (13,"blue"), (11, "orange")]
]
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Python nyelvet 17 fogalom146 feladat segítségével, valódi emberi mentorálással, mindez ingyen.