2010-07-08 41 views
5

Câu hỏi này sẽ khá dài, vì vậy tôi xin lỗi trước.đối số vị trí dư thừa, giải nén danh sách đối số hoặc tuples và mở rộng lặp lại giải nén

Trong Python chúng ta có thể sử dụng * trong ba trường hợp sau:

I. Khi xác định một chức năng mà chúng ta muốn trở thành callable với một số tùy ý của các đối số, chẳng hạn như in this example:

def write_multiple_items(file, separator, *args): 
    file.write(separator.join(args)) 

Trong trường hợp này, các đối số vị trí dư thừa được thu thập thành tuple.

II. Trường hợp ngược lại là khi các đối số đã có trong cả hai danh sách hoặc một tuple và chúng tôi muốn giải nén chúng cho một cuộc gọi chức năng yêu cầu đối số vị trí riêng biệt, chẳng hạn như in this example:

>>> range(3, 6)    # normal call with separate arguments 
[3, 4, 5] 
>>> args = [3, 6] 
>>> range(*args)   # call with arguments unpacked from a list 
[3, 4, 5] 

III. Bắt đầu với Python 3, * cũng được sử dụng trong bối cảnh mở rộng danh sách hoặc tuple giải nén, chẳng hạn như in this example cho các bộ:

>>> a, *b, c = range(5) 
>>> b 
[1, 2, 3] 

hoặc cho các danh sách:

>>> [a, *b, c] = range(5) 
>>> b 
[1, 2, 3] 

Trong cả hai trường hợp, tất cả các mục từ lặp lại được giải nén không được gán cho bất kỳ biểu thức bắt buộc nào được gán cho một danh sách .

Vì vậy, đây là câu hỏi: trong trường hợp tôi args thêm được thu thập vào một tuple, trong khi trong trường hợp III các mục thêm được gán cho một danh sách . Rằng sự khác biệt này? Lời giải thích duy nhất tôi có thể tìm được trong PEP 3132 mà nói rằng:

thay đổi có thể xảy ra thảo luận là:

[...]

Làm cho mục tiêu được đánh dấu sao một tuple thay vì một danh sách . Điều này sẽ là phù hợp với chức năng * args, nhưng xử lý thêm kết quả khó hơn.

Tuy nhiên, từ góc độ sư phạm sự thiếu nhất quán là có vấn đề, đặc biệt là cho rằng nếu bạn muốn để xử lý kết quả, bạn luôn có thể nói danh sách (b) (giả sử b trong ví dụ trên là một tuple). Tui bỏ lỡ điều gì vậy?

Trả lời

7

Trong Python chúng ta có thể sử dụng * trong sau ba trường hợp:

Bạn có nghĩa tiền tố*, tất nhiên - ghi vào* được sử dụng để nhân giống.

Tuy nhiên, từ góc độ sư phạm sự thiếu nhất quán là có vấn đề, đặc biệt là cho rằng nếu bạn muốn để xử lý kết quả, bạn có thể luôn luôn nói danh sách (b) (giả sử b trong các ví dụ trên là một tuple). Tôi có thiếu gì đó không?

Tôi sẽ nói rằng vấn đề thiết kế (cũ và rất dài trong răng!) Là với thực tế là khi bạn nhận được các đối số tùy ý, bạn sẽ nhận được chúng dưới dạng bộ tuple, khi danh sách sẽ nhiều hơn hữu ích trong nhiều trường hợp không có nhược điểm thực sự (số lượng nhỏ xử lý bổ sung và bộ nhớ có thể cần thiết để tạo danh sách thay vì một bộ tuple là không đáng kể trong ngữ cảnh gọi hàm trên không - hoặc giải nén chuỗi, cho vấn đề đó; việc xử lý thêm và bộ nhớ cần thiết để tạo danh sách cũng như một bộ dữ liệu thực sự gây khó chịu hơn). Có rất ít việc bạn có thể làm với một bộ dữ liệu nhưng không phải là danh sách - về cơ bản, chỉ cần băm nhỏ (để sử dụng như một mục được đặt hoặc khóa dict) - trong khi danh sách cung cấp thêm nhiều chức năng hơn, chứ không phải chỉ cho mục đích thay đổi nó ... các phương pháp như countindex cũng hữu ích.

+0

Cảm ơn câu trả lời. Tóm lại những gì tôi nghe là trường hợp đó ** I ** nên được thiết kế để đưa ra một danh sách. –

+0

@ Alexandros, đó thực sự là ý kiến ​​của tôi - nhưng tất nhiên là trở ngại là 20/20, và quyết định đó đã được đưa ra ... Tôi không chắc chắn khi nào, nhưng nó đã có trong Python 1.5.2, cách đây hơn 11 năm. –

8

Bạn đã bỏ lỡ một.

IV. Ngoài ra, trong Python 3, một số * trống trong danh sách đối số đánh dấu kết thúc đối số vị trí, cho phép keyword-only arguments.

def foo(a, b, *, key = None): 
    pass 

Điều này có thể được gọi là foo(1, 2, key = 3) nhưng không được foo(1, 2, 3).

+0

Cảm ơn. Mặc dù không thực sự là một câu trả lời cho câu hỏi của tôi, nó là tốt đẹp để có tất cả các trường hợp thu thập được trong một chủ đề. –

Các vấn đề liên quan