Em Python, o que dict.pop (a, b) significa?


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) ← ------ por que existe um segundo argumento?


8
Ou se você for realmente preguiçoso help(b.data.pop)no REPL.
Michael Mior

Respostas:


120

O popmétodo de dicts (como self.data, isto é {'a':'aaa','b':'bbb','c':'ccc'}, aqui) leva dois argumentos - veja a documentação

O segundo argumento,, defaulté o que popretorna se o primeiro argumento key,, estiver ausente. (Se você chamar popcom apenas um argumento key,, ele gerará uma exceção se essa chave estiver ausente).

Em seu exemplo, print b.pop('a',{'b':'bbb'})isso é irrelevante porque 'a' é uma chave em b.data. Mas se você repetir essa linha ...:

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

você verá que faz diferença: o primeiro popremove a 'a'chave, então no segundo popo defaultargumento é realmente retornado (já que 'a'agora está ausente de b.data).


3
Apenas um pequeno comentário que eu acho importante em algumas situações onde o usuário precisa de popum elemento, dictmas retém o valor do elemento exibido. Portanto, dict.pop(key)remove o keyjunto com o associado, valuemas também retorna o valuedo keyque acabou de ser removido. Achei útil ...
flamenco

@flamenco é isso que eu espero pop()- comportamento comum em mais linguagens como JavaScript, PHP, Java, embora nem todas as linguagens façam isso - por exemplo, C ++.
jave.web

27

Tantas perguntas aqui. Eu vejo pelo menos dois, talvez três:

  • O que pop (a, b) faz? / Por que há um segundo argumento?
  • Para que está *argssendo usado?

A primeira pergunta é trivialmente respondida na referência da Biblioteca Padrão do Python :

pop (tecla [, padrão])

Se a chave estiver no dicionário, remova-a e retorne seu valor, caso contrário, retorne o padrão. Se o padrão não for fornecido e a chave não estiver no dicionário, um KeyError é gerado.


A segunda pergunta é abordada na Referência da linguagem Python :

Se a forma “* identificador” estiver presente, ele é inicializado com uma tupla recebendo quaisquer parâmetros posicionais em excesso, assumindo como padrão a tupla vazia. Se a forma “** identificador” estiver presente, ele é inicializado para um novo dicionário recebendo quaisquer argumentos de palavra-chave em excesso, assumindo como padrão um novo dicionário vazio.

Em outras palavras, a popfunção leva pelo menos dois argumentos. Os dois primeiros recebem os nomes selfe key; e o resto é colocado em uma tupla chamada args.

O que acontece na próxima linha quando *argsé transmitido na chamada de self.data.popé o inverso disso - a tupla *argsé expandida para dos parâmetros posicionais que são transmitidos. Isso é explicado na Referência da linguagem Python :

Se a sintaxe * expressão aparecer na chamada de função, a expressão deve ser avaliada como uma sequência. Os elementos desta sequência são tratados como se fossem argumentos posicionais adicionais

Resumindo, a.pop()quer ser flexível e aceitar qualquer número de parâmetros posicionais, de modo que possa passar esse número desconhecido de parâmetros posicionais para self.data.pop().

Isso lhe dá flexibilidade; datapassa a ser um dictagora e, portanto, self.data.pop()leva um ou dois parâmetros; mas se você mudar datapara um tipo que usa 19 parâmetros para uma chamada para, self.data.pop()você não terá que mudar de classe a. Você ainda teria que alterar qualquer código chamado a.pop()para passar os 19 parâmetros necessários.


2
1 pelo esforço. Temo que o inglês do OP não esteja à altura de ler sua resposta.
Mechanical_meat

Eu escrevi isso antes de ler o perfil dos OPs. Agora li o referido perfil e vi várias outras perguntas sobre os OPs. Acabei de fazer outra tentativa, desta vez usando apenas código :)
James Polley

6
def func(*args): 
    pass

Quando você define uma função dessa maneira, *argsum array de argumentos é passado para a função. Isso permite que sua função funcione sem saber com antecedência quantos argumentos serão passados ​​para ela.

Você também faz isso com argumentos de palavra-chave, usando **kwargs:

def func2(**kwargs): 
    pass

Veja: Listas de argumentos arbitrários


No seu caso, você definiu uma classe que funciona como um dicionário. O dict.popmétodo é definido como pop(key[, default]).

Seu método não usa o defaultparâmetro. Mas, ao definir seu método com *argse passar *argspara dict.pop(), você está permitindo que o chamador use o defaultparâmetro.

Em outras palavras, você deve ser capaz de usar o popmétodo de sua classe como 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
Li várias perguntas, conforme detalhado na minha outra resposta. Também li o perfil dos OPs e percebi que minha outra resposta é inútil. Essa resposta deve demonstrar pelo menos parte do que * args faz, que é o que estou supondo que seja a verdadeira confusão dos OPs, apesar do assunto.
James Polley

@James, +1 pelo esforço extra. Eu cheguei à mesma conclusão sobre a questão real.
Peter Hansen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.