Co w Pythonie oznacza 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) ← ------ dlaczego jest drugi argument?


8
Lub jeśli jesteś naprawdę leniwy help(b.data.pop)w REPL.
Michael Mior

Odpowiedzi:


121

popMetoda dicts (jak self.data, to znaczy {'a':'aaa','b':'bbb','c':'ccc'}, tutaj) pobiera dwa argumenty - patrz docs

Drugi argument,, defaultjest tym, co popzwraca, jeśli nie ma pierwszego argumentu key,. (Jeśli wywołasz poptylko z jednym argumentem, keyzgłosi wyjątek, jeśli nie ma tego klucza).

W twoim przykładzie print b.pop('a',{'b':'bbb'})nie ma to znaczenia, ponieważ 'a' jest to klucz b.data. Ale jeśli powtórzysz tę linię ...:

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

zobaczysz to robi różnicę: pierwsze popUsuwa 'a'klucz, więc w drugim argument rzeczywiście zwrócony (ponieważ jest teraz nieobecny ).popdefault'a'b.data


3
Tylko mały mały komentarz, który moim zdaniem jest ważny w niektórych sytuacjach, gdy użytkownik potrzebuje popelementu, dictale zachować wartość elementu popped. Tak więc, dict.pop(key)usuwa keyrazem ze skojarzonym, valueale także zwraca valuewartość, keyktóra została właśnie usunięta. Przydało mi się ...
flamenco

Od @flamenco tego oczekuję pop()- wspólne zachowanie w innych językach, takich jak JavaScript, PHP, Java, chociaż nie wszystkie języki to robią - np. C ++.
jave.web

27

Tak wiele pytań tutaj. Widzę co najmniej dwa, może trzy:

  • Co robi pop (a, b)? / Dlaczego jest drugi argument?
  • Do czego *argssłuży?

Na pierwsze pytanie można znaleźć trywialną odpowiedź w dokumentacji Python Standard Library :

pop (klawisz [, domyślny])

Jeśli klucz znajduje się w słowniku, usuń go i zwróć jego wartość, w przeciwnym razie zwróć wartość domyślną. Jeśli nie podano wartości domyślnej, a klucza nie ma w słowniku, generowany jest błąd KeyError.


Drugie pytanie jest omówione w Python Language Reference :

Jeśli występuje postać „* identifier”, jest ona inicjowana w postaci krotki otrzymującej wszelkie nadmiarowe parametry pozycyjne, domyślnie pustej krotki. Jeśli występuje postać „** identyfikator”, jest on inicjowany w nowym słowniku, który otrzymuje nadmiarowe argumenty słów kluczowych, domyślnie nowy pusty słownik.

Innymi słowy, popfunkcja przyjmuje co najmniej dwa argumenty. Pierwsze dwa otrzymują nazwy selfi key; a reszta jest umieszczana w krotce o nazwie args.

To, co dzieje się w następnej linii, gdy *argsjest przekazywane w wywołaniu, self.data.popjest odwrotnością tego - krotka *argsjest rozwijana do parametrów pozycyjnych, które są przekazywane dalej. Jest to wyjaśnione w dokumencie Python Language Reference :

Jeśli wyrażenie składni * pojawia się w wywołaniu funkcji, wyrażenie musi wyliczać na sekwencję. Elementy z tej sekwencji są traktowane tak, jakby były dodatkowymi argumentami pozycyjnymi

Krótko mówiąc, a.pop()chce być elastyczny i akceptować dowolną liczbę parametrów pozycyjnych, aby mógł przekazać tę nieznaną liczbę parametrów pozycyjnych do self.data.pop().

Daje to elastyczność; datatak się składa, że ​​jest to dictteraz, więc self.data.pop()przyjmuje jeden lub dwa parametry; ale jeśli zmieniłeś datasię na typ, który wymagał 19 parametrów dla wywołania self.data.pop(), nie musiałbyś w ogóle zmieniać klasy a. Nadal musiałbyś jednak zmienić dowolny kod, który wywołałby a.pop()przekazanie wymaganych 19 parametrów.


2
+1 za wysiłek. Obawiam się, że angielski OP nie jest w stanie odczytać pańskiej odpowiedzi.
Mechanical_meat

Napisałem to zanim przeczytałem profil PO. Przeczytałem teraz wspomniany profil i widziałem kilka innych pytań dotyczących PO. Właśnie podjąłem kolejną próbę, tym razem używając tylko kodu :)
James Polley

7
def func(*args): 
    pass

Gdy zdefiniujesz funkcję w ten sposób, *argszostanie przekazana tablica argumentów do funkcji. Dzięki temu Twoja funkcja będzie działać bez wcześniejszej wiedzy, ile argumentów zostanie do niej przekazanych.

Robisz to również z argumentami słów kluczowych, używając **kwargs:

def func2(**kwargs): 
    pass

Zobacz: Dowolne listy argumentów


W twoim przypadku zdefiniowałeś klasę, która działa jak słownik. dict.popSposób jest zdefiniowany jako pop(key[, default]).

Twoja metoda nie używa tego defaultparametru. Ale definiując metodę *argszi *argsdo niej dict.pop(), zezwalasz obiektowi wywołującemu na użycie defaultparametru.

Innymi słowy, powinieneś być w stanie użyć popmetody swojej klasy, takiej jak 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
Przeczytałem kilka pytań opisanych szczegółowo w mojej drugiej odpowiedzi. Przeczytałem również profil PO i zdałem sobie sprawę, że moja druga odpowiedź jest bezużyteczna. Ta odpowiedź powinna pokazać przynajmniej część tego, co robi * args, co, jak sądzę, jest prawdziwym zamętem w PO, pomimo tematu.
James Polley,

@James, +1 za dodatkowy wysiłek. Doszedłem do tego samego wniosku co do prawdziwego pytania.
Peter Hansen,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.