In Python, cosa significa 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) ← ------ perché c'è un secondo argomento?


8
O se sei davvero pigro help(b.data.pop)nel REPL.
Michael Mior

Risposte:


120

Il popmetodo di dicts (come self.data, cioè {'a':'aaa','b':'bbb','c':'ccc'}, qui) accetta due argomenti - vedi la documentazione

Il secondo argomento,, defaultè ciò che poprestituisce se il primo argomento key,, è assente. (Se chiami popcon un solo argomento, keysolleva un'eccezione se quella chiave è assente).

Nel tuo esempio, print b.pop('a',{'b':'bbb'})questo è irrilevante perché 'a' è una chiave in b.data. Ma se ripeti quella riga ...:

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

vedrai che fa la differenza: il primo poprimuove la 'a'chiave, quindi nel secondo popl' defaultargomento viene effettivamente restituito (poiché 'a'ora è assente da b.data).


3
Solo un piccolo piccolo commento che penso sia importante in alcune situazioni in cui l'utente ha bisogno di popun elemento dictma conserva il valore dell'elemento saltato. Quindi, dict.pop(key)rimuove il keyinsieme con gli associati valuema restituisce anche valueil keyche è stato appena rimosso. L'ho trovato utile ...
flamenco

@flamenco, questo è ciò che mi aspetto da pop(): comportamento comune in più linguaggi come JavaScript, PHP, Java, sebbene non tutti i linguaggi lo facciano, ad esempio C ++.
jave.web

27

Tante domande qui. Vedo almeno due, forse tre:

  • Cosa fa pop (a, b)? / Perché c'è un secondo argomento?
  • A cosa *argsserve?

La prima domanda trova una risposta banale nel riferimento alla libreria standard Python :

pop (tasto [, predefinito])

Se la chiave è nel dizionario, rimuoverla e restituirne il valore, altrimenti restituire il valore predefinito. Se non viene fornito il valore predefinito e la chiave non è nel dizionario, viene sollevata un'eccezione KeyError.


La seconda domanda è trattata nel Python Language Reference :

Se è presente la forma "* identificatore", viene inizializzata a una tupla che riceve eventuali parametri posizionali in eccesso, impostando di default la tupla vuota. Se è presente la forma "** identificatore", viene inizializzato su un nuovo dizionario che riceve eventuali argomenti di parole chiave in eccesso, impostando di default un nuovo dizionario vuoto.

In altre parole, la popfunzione accetta almeno due argomenti. Ai primi due vengono assegnati i nomi selfe key; e il resto viene inserito in una tupla chiamata args.

Quello che accade nella riga successiva quando *argsviene passato nella chiamata a self.data.popè il contrario di questo: la tupla *argsviene espansa a dei parametri posizionali che vengono passati. Questo è spiegato nella Guida di riferimento al linguaggio Python :

Se l'espressione della sintassi * appare nella chiamata di funzione, l'espressione deve restituire una sequenza. Gli elementi di questa sequenza vengono trattati come se fossero argomenti posizionali aggiuntivi

In breve, a.pop()vuole essere flessibile e accettare un numero qualsiasi di parametri posizionali, in modo che possa passare questo numero sconosciuto di parametri posizionali a self.data.pop().

Questo ti dà flessibilità; datasembra essere un in dictquesto momento, e quindi self.data.pop()richiede uno o due parametri; ma se cambiaste dataper essere un tipo che richiede 19 parametri per una chiamata a non self.data.pop()dovreste cambiare classe a. a.pop()Tuttavia, dovresti comunque modificare qualsiasi codice chiamato per passare i 19 parametri richiesti.


2
+1 per lo sforzo. Temo che l'inglese del PO non sia all'altezza del compito di leggere la tua risposta.
Mechanical_meat

L'ho scritto prima di leggere il profilo degli OP. Ora ho letto il suddetto profilo e ho visto molte altre domande dei PO. Ho appena fatto un altro tentativo, questa volta usando solo il codice :)
James Polley

6
def func(*args): 
    pass

Quando si definisce una funzione in questo modo, *argsverrà passato un array di argomenti alla funzione. Ciò consente alla funzione di funzionare senza sapere in anticipo quanti argomenti le verranno passati.

Lo fai anche con gli argomenti delle parole chiave, usando **kwargs:

def func2(**kwargs): 
    pass

Vedi: elenchi di argomenti arbitrari


Nel tuo caso, hai definito una classe che si comporta come un dizionario. Il dict.popmetodo è definito come pop(key[, default]).

Il tuo metodo non usa il defaultparametro. Tuttavia, definendo il metodo con *argse passando *argsa dict.pop(), si consente al chiamante di utilizzare il defaultparametro.

In altre parole, dovresti essere in grado di utilizzare il popmetodo della tua classe come 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
Ho letto diverse domande, come dettagliato nella mia altra risposta. Ho anche letto il profilo dell'OP e ho capito che l'altra mia risposta è inutile. Questa risposta dovrebbe dimostrare almeno parte di ciò che fa * args, che è ciò che immagino sia la vera confusione degli OP, nonostante l'argomento.
James Polley

@ James, +1 per lo sforzo extra. Ero giunto alla stessa conclusione riguardo alla vera domanda.
Peter Hansen
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.