Jak používat operátory rozbalování (*, **) v Pythonu?

Python je nejpoužívanější programovací jazyk. Dnes se naučíte používat jednu z jeho základních – ale často ignorovaných – funkcí, rozbalení v Pythonu.

Pravděpodobně jste viděli * a ** v cizím kódu nebo jste je dokonce použili, aniž byste vlastně věděli, jaký je jejich účel. Projdeme si koncept rozbalování a jak jej použít k psaní dalšího kódu Pythonic.

Zde je seznam pojmů, které se vám budou hodit při čtení tohoto návodu:

  • Iterovatelný: Jakákoli sekvence, kterou lze iterovat smyčkou for, jako jsou sady, seznamy, n-tice a slovníky
  • Callable: Objekt Pythonu, který lze volat pomocí dvojitých závorek (), například myfunction()
  • Shell: Interaktivní běhové prostředí, které nám umožňuje spouštět kód Pythonu. Můžeme to zavolat spuštěním „pythonu“ v terminálu
  • Proměnná: Symbolický název, který ukládá objekt a má vyhrazené místo v paměti.

Začněme nejčastějším zmatkem: Asteristika v Pythonu jsou také aritmetické operátory. Jedna hvězdička

se používá pro násobení, zatímco dva z nich (**) odkazují na umocňování.

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

Můžeme to dokázat otevřením shellu Pythonu a zadáním:

Poznámka: Abyste mohli pokračovat v tomto tutoriálu, musíte mít nainstalovaný Python 3. Pokud jej nemáte nainstalovaný, podívejte se na naši instalační příručku Pythonu.

Jak vidíte, používáme hvězdičku za prvním číslem a před druhým číslem. Když toto vidíte, znamená to, že používáme aritmetické operátory.

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

Na druhou stranu k rozbalení používáme hvězdičky (*, **) před iterovatelnou – například:

Nedělejte si starosti, pokud to nechápete, toto je jen preambule k rozbalení v Pythonu. Takže pokračujte a přečtěte si celý tutoriál!

Co se rozbaluje?

Rozbalení je proces získávání věcí – iterovatelných, jako jsou seznamy, n-tice a slovníky. Představte si to jako otevření krabice a vytažení různých položek, jako jsou kabely, sluchátka nebo USB.

  Jak zjistit, zda někdo četl vaši zprávu na WeChat

Rozbalení v Pythonu je podobné rozbalení krabice v reálném životě.

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

Pojďme si tento stejný příklad přeložit do kódu pro lepší pochopení:

Jak můžete vidět, tři položky v seznamu mybox přiřazujeme třem proměnným item1, item2, item2. Tento druh přiřazení proměnných je základním konceptem rozbalování v Pythonu.

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

Pokud se pokusíte získat hodnotu každé položky, všimnete si, že položka 1 odkazuje na „kabely“, položka 2 odkazuje na „sluchátka“ a tak dále.

>>> 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)

Až sem se zdá, že je s tímto kódem vše v pořádku, ale co kdybychom chtěli rozbalit seznam s více prvky – se zachováním stejného množství přiřazených proměnných?

Pravděpodobně jste očekávali takovou chybu. V podstatě přiřazujeme 4 položky seznamu třem proměnným, jak Python zvládá přiřadit správné hodnoty? Není, je to proto, že dostáváme a ValueError

se zprávou „příliš mnoho hodnot k rozbalení“. To se děje, protože nastavujeme tři proměnné vlevo a čtyři hodnoty (odpovídající seznamu newbox) vpravo.

>>> 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)

Pokud se pokusíte provést podobný proces, ale s více proměnnými než hodnotami k rozbalení, dostanete další ValueError kromě toho s mírně odlišnou zprávou:

Poznámka: Pracovali jsme se seznamy, ale tuto formu rozbalení můžete použít s libovolnými iterovatelnými (seznamy, sady, n-tice, slovníky)

Jak tedy tuto situaci překonat? Existuje nějaký způsob, jak rozbalit všechny položky iterovatelného na několik proměnných, aniž by došlo k chybám?

Jistě existuje a nazývá se to operátor rozbalení nebo operátor s hvězdičkou (*, **). Podívejme se, jak jej používat v Pythonu.

Jak rozbalit seznamy pomocí operátoru *

Operátor hvězdička

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

se používá k rozbalení všech hodnot iterovatelné, které ještě nebyly přiřazeny.

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

Předpokládejme, že chcete získat první a poslední prvek seznamu bez použití indexů, mohli bychom to udělat pomocí operátoru hvězdička:

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

Jak jistě oceníte, všechny nepoužité hodnoty získáváme pomocí operátoru hvězdička. Upřednostňovaným způsobem vyřazení hodnot je použití proměnné podtržítka (_), která se někdy používá jako „fiktivní proměnná“.

  Jak opravit Google Chrome nereaguje

Tento trik můžeme stále používat, i když seznam obsahuje pouze dva prvky:

V tomto případě proměnná podtržítka (fiktivní proměnná) ukládá prázdný seznam, takže další dvě proměnné kolem nich mohou přistupovat k dostupným hodnotám seznamu.

>>> *string = 'PythonIsTheBest'

Běžné odstraňování problémů

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

Můžeme rozbalit jedinečný prvek iterovatelného prvku. Například byste přišli s něčím takovým: Výše uvedený kód však vrátí SyntaxError:To proto, že podle

Specifikace PEP

:

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

N-tice (nebo seznam) na levé straně jednoduchého úkolu

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

Pokud chceme rozbalit všechny hodnoty iterovatelného do jedné proměnné, musíme nastavit n-tici, takže přidání jednoduché čárky bude stačit:

Dalším příkladem by bylo použití funkce range, která vrací posloupnost čísel.

Nyní, když víte, jak rozbalit seznamy a n-tice s hvězdičkou, je čas pustit se do rozbalování slovníků.

Jak rozbalit slovníky s operátorem **

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

Zatímco k rozbalování seznamů a n-tic se používá jedna hvězdička, k rozbalování slovníků se používá dvojitá hvězdička (**).

>>> 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'}

Bohužel nemůžeme rozbalit slovník do jedné proměnné, jak jsme to dělali s n-ticemi a seznamy. To znamená, že následující způsobí chybu:

Můžeme však použít operátor ** uvnitř callables a dalších slovníků. Pokud například chceme vytvořit sloučený slovník vytvořený z jiných slovníků, můžeme použít níže uvedený kód:

Toto je docela krátký způsob, jak vytvořit složené slovníky, ale toto není hlavní přístup k rozbalování v Pythonu.

Podívejme se, jak můžeme využít rozbalování s callables

Sbalení funkcí: args a kwargs

Pravděpodobně jste již viděli argy a kwargy implementované do tříd nebo funkcí. Podívejme se, proč je musíme používat spolu s callables.

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

Balení s operátorem * (args)

>>> product(12, 1)
12

Předpokládejme, že máme funkci, která vypočítá součin dvou čísel.

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

Jak můžete vidět, rozbalujeme čísla seznamu do funkce, takže ve skutečnosti spouštíme následující:

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

Až sem vše funguje dobře, ale co kdybychom chtěli projít delší seznam? Určitě to vyvolá chybu, protože funkce přijímá více argumentů, než je schopna zvládnout.

  Jak smazat spoustu rybích seznamek

To vše můžeme vyřešit pouhým nabalením seznamu přímo na funkci, která v něm vytvoří iterovatelný a umožní nám předat funkci libovolný počet argumentů.

Zde zacházíme s parametrem args jako s iterovatelným, procházíme jeho prvky a vracíme součin všech čísel. Všimněte si, že počáteční číslo výsledku musí být jedna, protože pokud začneme nulou, funkce vždy vrátí nulu. Poznámka: args je pouze konvence, můžete použít jakýkoli jiný název parametruTaké bychom mohli předat funkci libovolná čísla bez použití seznamu, stejně jako u vestavěné

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

funkce tisku

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

.

Nakonec získáme typ objektu argumentů funkce.

Jak je uvedeno ve výše uvedeném kódu, typ argumentů bude vždy n-tice a jeho obsahem budou všechny neklíčové argumenty předané funkci.

Balení s operátorem ** (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, '

Jak jsme viděli dříve, operátor ** se používá výhradně pro slovníky. To znamená, že s tímto operátorem jsme schopni předat páry klíč–hodnota funkci jako parametr.

Vytvořme funkci make_person, která obdrží poziční argument „jméno“ a nedefinované množství argumentů s klíčovými slovy.

Jak vidíte, příkaz **kwargs převede všechny argumenty s klíčovými slovy do slovníku, který můžeme uvnitř funkce iterovat.

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

Poznámka: kwargs je pouze konvence, tento parametr můžete pojmenovat jakkoli chcete

Můžeme zkontrolovat typ kwargů stejným způsobem, jako jsme to udělali s 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'}

Vnitřní proměnná kwargs se vždy změní na slovník, který ukládá páry klíč–hodnota předané funkci.

Nakonec použijme argy a kwargy ve stejné funkci:

Závěr

  • Operátory rozbalování jsou opravdu užitečné v každodenních úlohách, nyní víte, jak je používat jak v jednotlivých příkazech, tak v parametrech funkcí.
  • V tomto tutoriálu jste se naučili:
  • Používáte * pro n-tice a seznamy a ** pro slovníky
  • Operátory rozbalení můžete použít v konstruktorech funkcí a tříd

args se používají k předávání neklíčových parametrů funkcímkwargs se používají k předávání klíčových parametrů funkcím.