Що в Python означає dict.pop (a, b)?


92
class a(object):
    data={'a':'aaa','b':'bbb','c':'ccc'}
    def pop(self, key, *args):
            return self.data.pop(key, *args)#what is this mean.

b=a()
print b.pop('a',{'b':'bbb'})
print b.data

self.data.pop(key, *args) ← ------ чому є другий аргумент?


8
Або якщо ви справді ліниві help(b.data.pop)в REPL.
Michael Mior

Відповіді:


120

popМетод dicts (як self.data, наприклад {'a':'aaa','b':'bbb','c':'ccc'}, тут) приймає два аргументи - см документації

Другий аргумент - defaultце те, що popповертається, якщо перший аргумент key- відсутній. (Якщо ви телефонуєте popлише з одним аргументом, keyце викликає виняток, якщо цей ключ відсутній).

У вашому прикладі print b.pop('a',{'b':'bbb'})це не має значення, оскільки 'a' це ключ до b.data. Але якщо повторити цей рядок ...:

b=a()
print b.pop('a',{'b':'bbb'})
print b.pop('a',{'b':'bbb'})
print b.data

ви побачите , що він робить різницю: перший popВидаляє 'a'ключ, так що в другому аргумент фактично повернутого (так як в даний час відсутня ).popdefault'a'b.data


3
Лише невеликий невеликий коментар, який, на мою думку, є важливим у деяких ситуаціях, коли користувачеві потрібно до popелемента, dictале зберегти значення спливаючого елемента. Отже, dict.pop(key)видаляє keyспільно з пов'язаним, valueале також повертає valueте, keyщо щойно було видалено. Я знайшов це корисним ...
фламенко

@flamenco - це те, чого я чекаю pop()- загальна поведінка в більшості мов, таких як JavaScript, PHP, Java, хоча не всі мови це роблять - наприклад, C ++.
jave.web

27

Стільки питань тут. Я бачу принаймні два, а може три:

  • Що робить pop (a, b)? / Чому є другий аргумент?
  • Для *argsчого використовується?

На перше запитання тривіально відповідає посилання на Стандартну бібліотеку Python :

поп (клавіша [, за замовчуванням])

Якщо ключ є у словнику, видаліть його та поверніть його значення, інакше поверніть за замовчуванням. Якщо за замовчуванням не вказано, а ключа немає у словнику, піднімається помилка KeyError.


Друге питання висвітлюється в Довідковій мові Python :

Якщо форма «ідентифікатор *» присутня, вона ініціалізується кортежем, що отримує будь-які надлишкові позиційні параметри, за замовчуванням порожнім кортежем. Якщо форма “** ідентифікатор” присутня, вона ініціалізується в новий словник, що отримує будь-які надлишкові аргументи ключового слова, за замовчуванням новий порожній словник.

Іншими словами, popфункція приймає принаймні два аргументи. Першим двом присвоюються імена selfта key; а решта набиваються в кортеж під назвою args.

Те, що відбувається в наступному рядку, коли *argsйого передають у виклику, self.data.popє зворотним до цього - кортеж *argsрозширюється до позиційних параметрів, які передаються. Це пояснюється в Довідковій мові Python :

Якщо вираз синтаксису * з'являється у виклику функції, вираз повинен перетворитися на послідовність. Елементи з цієї послідовності трактуються так, ніби вони є додатковими позиційними аргументами

Коротше кажучи, a.pop()хоче бути гнучким і приймати будь-яку кількість позиційних параметрів, щоб він міг передати цю невідому кількість позиційних параметрів self.data.pop().

Це дає вам гнучкість; dataтрапляється dictзараз, і тому self.data.pop()приймає один або два параметри; але якщо ви dataперейшли на тип, який приймав 19 параметрів для дзвінка, self.data.pop()вам взагалі не доведеться змінювати клас a. Вам все одно доведеться змінити будь-який код, який викликав, a.pop()щоб передати необхідні 19 параметрів.


2
+1 за зусилля. Я боюся, що англійська мова ОП не відповідає завданням прочитати вашу відповідь.
mechanical_meat

Я писав це до того, як прочитав профіль ОП. Зараз я прочитав згаданий профіль і побачив кілька інших запитань щодо ОП. Я щойно зробив ще одну спробу, цього разу використовуючи лише код :)
Джеймс Поллі, 02

6
def func(*args): 
    pass

Коли ви визначаєте функцію таким чином, *argsбуде масив аргументів, переданих функції. Це дозволяє вашій функції працювати, не знаючи заздалегідь, скільки аргументів буде передано їй.

Ви також робите це з аргументами ключових слів, використовуючи **kwargs:

def func2(**kwargs): 
    pass

Див .: Списки довільних аргументів


У вашому випадку ви визначили клас, який діє як словник. dict.popМетод визначається як pop(key[, default]).

Ваш метод не використовує defaultпараметр. Але, визначивши свій метод *argsта перейшовши *argsдо dict.pop(), ви дозволяєте користувачеві використовувати defaultпараметр.

Іншими словами, ви повинні мати можливість використовувати popметод вашого класу, наприклад dict.pop:

my_a = a()
value1 = my_a.pop('key1')       # throw an exception if key1 isn't in the dict
value2 = my_a.pop('key2', None) # return None if key2 isn't in the dict

6
>>> def func(a, *args, **kwargs):
...   print 'a %s, args %s, kwargs %s' % (a, args, kwargs)
... 
>>> func('one', 'two', 'three', four='four', five='five')
a one, args ('two', 'three'), kwargs {'four': 'four', 'five': 'five'}

>>> def anotherfunct(beta, *args):
...   print 'beta %s, args %s' % (beta, args)
... 
>>> def func(a, *args, **kwargs):
...   anotherfunct(a, *args)
... 
>>> func('one', 'two', 'three', four='four', five='five')
beta one, args ('two', 'three')
>>> 

1
Я прочитав кілька запитань, як це детально описується в іншій моїй відповіді. Я також прочитав профіль ОП і зрозумів, що інша моя відповідь марна. Ця відповідь повинна продемонструвати принаймні частину того, що робить * args, і саме це, на мою думку, є справжньою плутаниною, незважаючи на тему.
Джеймс Поллі,

@James, +1 за додаткові зусилля. Я дійшов такого ж висновку щодо справжнього питання.
Пітер Хансен, 02
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.