Python'da dict.pop (a, b) ne anlama geliyor?


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) ← ------ neden ikinci bir tartışma var?


8
Veya help(b.data.pop)REPL'de gerçekten tembelseniz.
Michael Mior

Yanıtlar:


121

popDicts yöntemi (gibi self.data, yani {'a':'aaa','b':'bbb','c':'ccc'}, burada) iki argüman alır - bkz docs

İkinci argüman, ilk argüman yoksa geri dönen defaultşeydir . (Tek bir argümanla çağırırsanız , o anahtar yoksa bir istisna ortaya çıkar).popkeypopkey

Örnekte, print b.pop('a',{'b':'bbb'})çünkü bu alakasız 'a' olduğu anahtar b.data. Ama bu satırı tekrar ederseniz ...:

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

Eğer bir fark yaratır göreceksiniz: İlk popsilen 'a'anahtar, böylece ikinci argüman aslında döndürülür (çünkü artık yoktur ).popdefault'a'b.data


3
Kullanıcının popbir öğeye ihtiyaç duyduğu dictancak patlayan öğenin değerini koruduğu bazı durumlarda önemli olduğunu düşündüğüm küçük bir yorum . Böylece, ilişkili dict.pop(key)olanla keybirlikte kaldırılır, valueancak aynı zamanda yeni kaldırılmış valueolanı da döndürür key. Faydalı buldum ...
flamenko

@flamenco'dan beklediğim pop()şey bu - JavaScript, PHP, Java gibi daha fazla dilde ortak davranış, ancak tüm diller bunu yapmıyor - örneğin C ++.
jave.web

27

Burada pek çok soru var. En az iki, belki üç görüyorum:

  • Pop (a, b) ne yapar? / Neden ikinci bir tartışma var?
  • Ne *argsiçin kullanılıyor?

İlk soru Python Standart Kitaplığı referansında önemsiz bir şekilde yanıtlanır :

pop (anahtar [, varsayılan])

Anahtar sözlükte ise, onu kaldırın ve değerini döndürün, aksi takdirde varsayılana dönün. Varsayılan belirtilmezse ve sözlükte anahtar yoksa, bir KeyError oluşturulur.


İkinci soru Python Dil Referansında ele alınmıştır :

"* Tanımlayıcı" formu mevcutsa, herhangi bir fazla konumsal parametre alan bir demet olarak başlatılır, varsayılan olarak boş demete ayarlanır. "** tanımlayıcı" formu mevcutsa, fazla anahtar kelime argümanlarını alan yeni bir sözlüğe başlatılır, varsayılan olarak yeni bir boş sözlüğe geçer.

Başka bir deyişle, popişlev en az iki argüman alır. İlk ikisine isimler verilir selfve key; ve geri kalanı adı verilen bir demete doldurulur args.

*argsÇağrıda iletildiğinde bir sonraki satırda olan self.data.popşey bunun tersidir - tuple *args, iletilen konumsal parametrelere genişletilir. Bu, Python Dil Referansında açıklanmıştır :

Sözdizimi * ifadesi işlev çağrısında görünürse, ifade bir sıra olarak değerlendirilmelidir. Bu dizideki öğeler, ek konumsal bağımsız değişkenlermiş gibi ele alınır.

Kısacası, a.pop()esnek olmak ve herhangi bir sayıda konumsal parametreyi kabul etmek ister, böylece bu bilinmeyen konumsal parametreleri üzerine geçirebilir self.data.pop().

Bu size esneklik sağlar; şu anda dataolur dictve bu nedenle self.data.pop()bir veya iki parametre alır; ancak data, bir çağrı için 19 parametre alan bir tür self.data.pop()olarak değiştirirseniz, sınıfınızı ahiç değiştirmeniz gerekmez . Yine de a.pop()gerekli 19 parametreyi geçmek için çağrılan herhangi bir kodu değiştirmeniz gerekir.


2
Çaba için +1. OP'nin İngilizcesinin cevabınızı okuma görevi olmadığından korkuyorum.
mechanical_meat

Bunu OP'nin profilini okumadan önce yazdım. Şimdi adı geçen profili okudum ve diğer birkaç OP sorusunu gördüm. Az önce başka bir girişimde bulundum, bu sefer sadece kodu kullanarak :)
James Polley

7
def func(*args): 
    pass

Bir işlevi bu şekilde tanımladığınızda, işleve *argsaktarılan argümanlar dizisi olacaktır. Bu, işlevinizin kendisine kaç argüman aktarılacağını önceden bilmeden çalışmasına izin verir.

Bunu anahtar kelime argümanlarıyla da yaparsınız **kwargs:

def func2(**kwargs): 
    pass

Bakınız: Keyfi argüman listeleri


Sizin durumunuzda, sözlük gibi davranan bir sınıf tanımladınız. dict.popYöntem olarak tanımlanır pop(key[, default]).

Yönteminiz defaultparametreyi kullanmıyor . Fakat, ile yöntemini tanımlayarak *argsve geçen *argsetmek dict.pop(), arayan kullanmasına izin vardır defaultparametreyi.

Başka bir deyişle, sınıfınızın aşağıdaki popgibi yöntemini kullanabilmelisiniz 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
Diğer cevabımda detaylandırıldığı üzere birkaç soru okudum. Ayrıca OP'nin profilini okudum ve diğer cevabımın faydasız olduğunu anladım. Bu cevap, * args'ın ne yaptığını en azından bir kısmını göstermelidir, ki bu konuya rağmen, OP'lerin gerçek kafa karışıklığı olduğunu tahmin ediyorum.
James Polley

@ James, ekstra çaba için +1. Asıl soru hakkında aynı sonuca varmıştım.
Peter Hansen
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.