Како користити операторе за распакивање (*, **) у Питхон-у?

Питхон је најчешће коришћени програмски језик. Данас ћете научити да користите једну од његових основних — али често занемарених — функција, распакивање у Питхон-у.

Вероватно сте видели * и ** у коду других или сте их чак користили, а да заправо нисте знали која је њихова сврха. Прошетаћемо кроз концепт распакивања и како га користити за писање више Питхониц кода.

Ево листе концепата који ће вам бити корисни док читате овај водич:

  • Итерабле: Било која секвенца која се може поновити помоћу фор-петље, као што су скупови, листе, тупле и речници
  • Позив: Питхон објекат који се може позвати помоћу двоструке заграде (), на пример, мифунцтион()
  • Схелл: Интерактивно окружење за извршавање које нам омогућава да покренемо Питхон код. Можемо га назвати покретањем „питхон“ у терминалу
  • Променљива: Симболично име које чува објекат и има резервисану меморијску локацију.

Почнимо од најчешће забуне: Астеристици у Питхон-у су такође аритметички оператори. Једна звездица

се користи за множење, док се два (**) односе на степеновање.

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

То можемо доказати отварањем Питхон љуске и куцањем:

Напомена: Морате да имате инсталиран Питхон 3 да бисте пратили овај водич. Ако га немате инсталиран, погледајте наш Питхон водич за инсталацију.

Као што видите, користимо звездицу после првог броја и пре другог. Када видите ово, то значи да користимо аритметичке операторе.

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

С друге стране, користимо звездице (*, **) пре итерабле да бисмо га распаковали — на пример:

Не брините ако не схватите, ово је само увод за распакивање у Питхон-у. Дакле, само напред и прочитајте цео водич!

Шта се распакује?

Распакивање је процес извлачења ствари — итераблес као што су листе, торке и речници. Замислите то као отварање кутије и вађење различитих предмета као што су каблови, слушалице или УСБ.

  10 недостатака куповине е-књига уместо штампаних копија

Распакивање у Питхон-у је слично распаковању кутије у стварном животу.

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

Хајде да преведемо овај исти пример у код ради бољег разумевања:

Као што видите, три ставке унутар мибок листе додељујемо три променљиве итем1, итем2, итем2. Ова врста додељивања променљивих је основни концепт распакивања у Питхон-у.

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

Ако покушате да добијете вредност сваке ставке, приметићете да се ставка 1 односи на „каблове“, ставка 2. односи се на „слушалице“ и тако даље.

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

До сада се чинило да је све у реду са овим кодом, али шта ако желимо да распакујемо листу са више елемената у њој — задржавајући исту количину додељених променљивих?

Вероватно сте очекивали ову врсту грешке. У суштини ми додељујемо 4 ставке листе трима променљивим, како Питхон успева да додели праве вредности? Није, то је зато што добијамо а ВалуеЕррор

са поруком „превише вредности за распакивање“. Ово се дешава зато што постављамо три променљиве са леве стране и четири вредности (које одговарају листи нових сандучића) са десне стране.

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

Ако покушате да урадите сличан процес, али са више променљивих него вредности за распакивање, добићете још једну грешку вредности осим оне са мало другачијом поруком:

Напомена: Радили смо са листама, али овај облик распакивања можете користити са било којим итерабле (листе, скупови, тупле, речници)

Па како да превазиђемо ову ситуацију? Да ли постоји начин да се распакују све ставке итерабле у неколико променљивих без икаквих грешака?

Наравно да постоји, и зове се оператор распакивања или оператор звездице (*, **). Хајде да видимо како да га користимо у Питхон-у.

Како распаковати листе помоћу * оператора

Оператор звездица

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

се користи за распакивање свих вредности итерабле које још нису додељене.

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

Претпоставимо да желите да добијете први и последњи елемент листе без коришћења индекса, могли бисмо то да урадимо са оператором звездица:

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

Као што можете да схватите, све неискоришћене вредности добијамо помоћу оператора звездица. Преферирани начин за одбацивање вредности је коришћење променљиве доње црте (_), која се понекад користи као „лажна променљива“.

  Мастер визуелно приповедање са Луцидцхарт-ом

И даље можемо да користимо овај трик чак и ако листа има само два елемента:

У овом случају, променљива доње црте (лажна променљива) чува празну листу тако да друге две променљиве око њих могу да приступе доступним вредностима листе.

>>> *string = 'PythonIsTheBest'

Уобичајено решавање проблема

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

Можемо распаковати јединствени елемент итерабле. На пример, смислили бисте нешто овако: Међутим, горњи код ће вратити СинтакЕррор:Ово зато што према

ПЕП спецификација

:

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

Корка (или листа) на левој страни једноставног задатка

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

Ако желимо да распакујемо све вредности итерабле у једну променљиву, морамо да поставимо тупле, па ће додавање једноставног зареза бити довољно:

Други пример би био коришћење функције опсега, која враћа низ бројева.

Сада када знате како да распакујете листе и торке са звездицом, време је да уђете у распакивање речника.

Како распаковати речнике помоћу ** оператора

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

Док се једна звездица користи за распакивање листа и торки, двострука звездица (**) се користи за распакивање речника.

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

Нажалост, не можемо да распакујемо речник у једну променљиву као што смо радили са торкама и листама. То значи да ће следеће избацити грешку:

Међутим, можемо користити ** оператор унутар позиваних и других речника. На пример, ако желимо да направимо спојени речник, направљен од других речника, могли бисмо да користимо код испод:

Ово је прилично кратак начин да се креирају сложени речници, међутим, ово није главни приступ распакивања у Питхон-у.

Хајде да видимо како можемо да користимо распакивање са позивима

Паковање у функције: аргс и кваргс

Вероватно сте раније видели аргове и кваргове имплементиране на класе или функције. Хајде да видимо зашто треба да их користимо заједно са позивима.

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

Паковање са * оператором (аргс)

>>> product(12, 1)
12

Претпоставимо да имамо функцију која израчунава производ два броја.

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

Као што видите, отпакујемо бројеве листе у функцију, тако да заправо покрећемо следеће:

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

До сада је све добро функционисало, али шта ако желимо да прођемо дужу листу? То ће сигурно изазвати грешку јер функција прима више аргумената него што је способна да управља.

  Како закачити и поново уоквирити видео феедове у Мицрософт тимовима

Све ово можемо решити само паковањем листе директно у функцију, што креира итерабле унутар ње и омогућава нам да проследимо било који број аргумената функцији.

Овде третирамо параметар аргс као итерабле, пролазимо кроз његове елементе и враћамо производ свих бројева. Запазите како почетни број резултата мора бити један јер ако почнемо са нулом, функција ће увек враћати нулу. Напомена: аргс је само конвенција, можете користити било које друго име параметраТакође бисмо могли да пренесемо произвољне бројеве у функцију без коришћења листе, баш као и са уграђеном

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

функција штампања

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

.

На крају, хајде да добијемо тип објекта аргс функције.

Као што је наведено у горњем коду, тип аргова ће увек бити тупле, а његов садржај ће бити сви аргументи без кључа који се прослеђују функцији.

Паковање са ** оператором (кваргс)

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

Као што смо раније видели, оператор ** се користи искључиво за речнике. То значи да са овим оператором можемо да проследимо парове кључ/вредност функцији као параметар.

Хајде да направимо функцију маке_персон, која прима позициони аргумент „име“ и недефинисану количину аргумената са кључним речима.

Као што видите, изјава **кваргс конвертује све аргументе са кључним речима у речник, који можемо поновити унутар функције.

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

Напомена: кваргс је само конвенција којом можете именовати овај параметар како год желите

Можемо да проверимо тип кваргова на исти начин као што смо урадили са аргс:

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

Унутрашња променљива кваргс се увек претвара у речник, који чува парове кључ-вредност прослеђене функцији.

Коначно, хајде да искористимо аргс и кваргс у истој функцији:

Закључак

  • Оператори за распакивање су заиста корисни у свакодневним задацима, сада знате како да их користите у појединачним изјавама и параметрима функције.
  • У овом водичу сте научили:
  • Користите * за торке и листе и ** за речнике
  • Можете користити операторе за распакивање у конструкторима функција и класа

аргс се користе за прослеђивање параметара без кључа функцијамакваргс се користе за прослеђивање параметара кључних речи функцијама.