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