Trong Python, dict.pop (a, b) có nghĩa là gì?


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) ← ------ tại sao lại có đối số thứ hai?


8
Hoặc nếu bạn thực sự lười biếng help(b.data.pop)trong REPL.
Michael Mior

Câu trả lời:


120

Các popphương pháp dicts (như self.data, ví dụ {'a':'aaa','b':'bbb','c':'ccc'}, ở đây) nhận hai đối số - xem các tài liệu

Đối số thứ hai default, là thứ poptrả về nếu đối số đầu tiên key, không có. (Nếu bạn gọi popchỉ với một đối số key, nó sẽ tạo ra một ngoại lệ nếu khóa đó vắng mặt).

Trong ví dụ của bạn print b.pop('a',{'b':'bbb'}), điều này không liên quan vì 'a' một chìa khóa trong b.data. Nhưng nếu bạn lặp lại dòng đó ...:

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

bạn sẽ thấy nó làm cho một sự khác biệt: người đầu tiên poploại bỏ các 'a'chìa khóa, vì vậy trong lần thứ hai popcác defaultlập luận là thực sự trả lại (kể từ 'a'giờ vắng mặt b.data).


3
Chỉ là một nhận xét nhỏ nhỏ mà tôi nghĩ rằng nó quan trọng trong một số tình huống mà người dùng cần popmột phần tử dictnhưng giữ lại giá trị của phần tử được bật lên. Vì vậy, dict.pop(key)loại bỏ keycùng với liên kết valuenhưng cũng trả lại valuecủa cái keyvừa bị loại bỏ. Tôi thấy nó hữu ích ...
Flamenco

@flamenco đó là những gì tôi mong đợi pop()- hành vi phổ biến trên nhiều ngôn ngữ hơn như JavaScript, PHP, Java, mặc dù không phải tất cả các ngôn ngữ đều làm được điều đó - ví dụ: C ++.
jave.web

27

Rất nhiều câu hỏi ở đây. Tôi thấy ít nhất hai, có thể ba:

  • Pop (a, b) làm gì? / Tại sao lại có đối số thứ hai?
  • Đang *argsđược sử dụng để làm gì?

Câu hỏi đầu tiên được trả lời nhỏ trong tài liệu tham khảo Thư viện chuẩn Python :

pop (phím [, mặc định])

Nếu khóa có trong từ điển, hãy xóa khóa đó và trả về giá trị của nó, nếu không thì trả về mặc định. Nếu mặc định không được cung cấp và khóa không có trong từ điển, lỗi KeyError sẽ xuất hiện.


Câu hỏi thứ hai được đề cập trong Tham khảo ngôn ngữ Python :

Nếu có dạng “* số nhận dạng”, nó sẽ được khởi tạo thành một bộ giá trị nhận bất kỳ tham số vị trí vượt quá nào, mặc định là bộ giá trị trống. Nếu có dạng “** IDfier”, nó sẽ được khởi tạo vào một từ điển mới nhận bất kỳ đối số từ khóa thừa nào, mặc định là một từ điển trống mới.

Nói cách khác, pophàm có ít nhất hai đối số. Hai phần đầu được gán tên selfkey; và phần còn lại được nhồi vào một tuple được gọi là args.

Điều gì đang xảy ra trên dòng tiếp theo khi *argsđược chuyển cùng trong lệnh gọi tới self.data.poplà nghịch đảo của điều này - bộ tuple *argsđược mở rộng thành các tham số vị trí được truyền cùng. Điều này được giải thích trong Tham chiếu ngôn ngữ Python :

Nếu biểu thức cú pháp * xuất hiện trong lệnh gọi hàm, biểu thức phải đánh giá thành một chuỗi. Các phần tử từ chuỗi này được coi như thể chúng là các đối số vị trí bổ sung

Tóm lại, a.pop()muốn linh hoạt và chấp nhận bất kỳ số lượng tham số vị trí nào, để nó có thể chuyển số lượng tham số vị trí chưa biết này vào self.data.pop().

Điều này mang lại cho bạn sự linh hoạt; dataxảy ra là một dictquyền ngay bây giờ, và do đó self.data.pop()có một hoặc hai tham số; nhưng nếu bạn thay đổi datathành một kiểu có 19 tham số cho một cuộc gọi đến, self.data.pop()bạn sẽ không phải thay đổi lớp nào acả. a.pop()Mặc dù vậy, bạn vẫn phải thay đổi bất kỳ mã nào được gọi để vượt qua 19 tham số bắt buộc.


2
+1 cho nỗ lực. Tôi e rằng tiếng Anh của OP không đáp ứng được nhiệm vụ đọc câu trả lời của bạn.
Mechanical_meat

Tôi đã viết điều đó trước khi tôi đọc hồ sơ OPs. Bây giờ tôi đã đọc hồ sơ nói trên và thấy một số câu hỏi khác của OP. Tôi vừa thực hiện một nỗ lực khác, lần này chỉ sử dụng mã :)
James Polley

6
def func(*args): 
    pass

Khi bạn định nghĩa một hàm theo cách này, *argssẽ là một mảng các đối số được truyền cho hàm. Điều này cho phép hàm của bạn hoạt động mà không cần biết trước có bao nhiêu đối số sẽ được chuyển cho nó.

Bạn cũng làm điều này với các đối số từ khóa, sử dụng **kwargs:

def func2(**kwargs): 
    pass

Xem: Danh sách lập luận tùy tiện


Trong trường hợp của bạn, bạn đã xác định một lớp hoạt động giống như một từ điển. Các dict.popphương pháp được định nghĩa là pop(key[, default]).

Phương thức của bạn không sử dụng defaulttham số. Tuy nhiên, bằng cách xác định phương thức của bạn với *argsvà chuyển *argstới dict.pop(), bạn đang cho phép người gọi sử dụng defaulttham số.

Nói cách khác, bạn sẽ có thể sử dụng popphương thức của lớp mình như 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
Tôi đã đọc một số câu hỏi, như được nêu chi tiết trong câu trả lời khác của tôi. Tôi cũng đã đọc hồ sơ OP và nhận ra rằng câu trả lời khác của tôi là vô ích. Câu trả lời này sẽ chứng minh ít nhất một phần những gì * args làm được, đó là điều tôi đoán là sự nhầm lẫn thực sự của OPs, bất chấp chủ đề.
James Polley

@James, +1 cho nỗ lực thêm. Tôi đã đi đến kết luận tương tự về câu hỏi thực sự.
Peter Hansen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.