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.