В Python, что означает dict.pop(a, b)?

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) & larr; ------ почему существует второй аргумент?

Ответ 1

Метод 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', поэтому во втором pop аргумент default фактически возвращается (поскольку 'a' теперь отсутствует в b.data).

Ответ 2

Здесь так много вопросов. Я вижу по крайней мере два, может быть три:

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

Первый вопрос тривиально отвечает в в стандартной библиотеке Python:

pop (клавиша [, по умолчанию])

Если ключ находится в словаре, удалите его и верните его значение, иначе верните значение по умолчанию. Если значение по умолчанию не задано и ключ не находится в словаре, возникает KeyError.


Второй вопрос рассмотрен в Python Language Reference:

Если присутствует форма "* идентификатор", он инициализируется получением кортежа любые избыточные позиционные параметры, по умолчанию для пустого кортежа. Если форма "** идентификатор" присутствует, это инициализирован в новый словарь получение лишнего ключевого слова аргументы, по умолчанию для нового пустого словарь.

Другими словами, функция pop принимает как минимум два аргумента. Первым двум присваиваются имена self и key; а остальные вставляются в кортеж под названием args.

То, что происходит на следующей строке, когда *args передается в вызове self.data.pop, является обратным из этого - кортеж *args расширяется до позиционных параметров, которые передаются вместе. Это объясняется в Python Language Reference:

Если выражение синтаксиса * появляется в вызов функции, выражение должно оценить последовательность. Элементы из эта последовательность обрабатывается так, как если бы они были дополнительными позиционными аргументами

Короче говоря, a.pop() хочет быть гибким и принимать любое количество позиционных параметров, чтобы он мог передать это неизвестное количество позиционных параметров на self.data.pop().

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

Ответ 3

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

Ответ 4

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