2011-12-13 29 views
8

Tôi đọc các mã nguồn lanh lợi, và thấy như vậy một def func trong commands.py:python args vị trí và args từ khóa

def import_(ui, repo, patch1=None, *patches, **opts): 
    ... 

trong python, args postional phải được đặt trước args từ khóa. Nhưng ở đây, patch1 là một đối số từ khóa, theo sau là đối số vị trí *patches. tại sao điều này là OK?

+1

Bạn đã giải quyết vấn đề này chưa? Nếu bạn có, nó sẽ là tốt nếu bạn sẽ chọn câu trả lời mà làm cho bạn giải quyết vấn đề là "chấp nhận", và upvote tất cả những người hữu ích (nếu bạn đã không làm điều đó rồi!). :) – mac

+0

xin lỗi, tôi đã rất bận rộn tất cả những ngày này. Bây giờ tôi sẽ đọc về câu trả lời của bạn và chọn câu trả lời. Cảm ơn tất cả các bạn :) – guoqiao

Trả lời

8

Chỉ cần có một cái nhìn vào các PEP 3102 cũng có vẻ như nó bằng cách nào đó liên quan đến this.

Để tóm tắt, các bản vá và lựa chọn có sẵn để chấp nhận các đối số biến nhưng sau đó là chấp nhận các đối số từ khóa. Các đối số từ khóa được chuyển như một từ điển ở đó là variable positional arguments would be wrapped as tuples.

Từ ví dụ của bạn

def import_(ui, repo, patch1=None, *patches, **opts): 

Bất kỳ tham số vị trí sau u1,repo and patch1 sẽ được bao bọc như bản ghi trong các bản vá lỗi. Bất kỳ đối số từ khoá nào sau các đối số vị trí biến sẽ được bao bọc dưới dạng đối tượng Dictionary thông qua các opts.

Một điều quan trọng nữa là, onus nằm với người gọi để đảm bảo rằng điều kiện non-keyword arg after keyword arg không bị vi phạm.

Vì vậy, điều gì đó vi phạm điều này sẽ làm tăng lỗi cú pháp ..

Ví dụ

cuộc gọi như

import_(1,2,3,test="test") 
import_(1,2,3,4,test="test") 
import_(1,2,3,4,5) 
import_(1,2,patch1=3,test="test") 

là hợp lệ, nhưng

import_(1,2,3,patch1=4,5) 

sẽ nâng cao một lỗi cú pháp SyntaxError: non-keyword arg after keyword arg

Trong trường hợp hợp lệ đầu tiên import_(1,2,3,test="test")

u1 = 1, repo = 2, patch1 = 3, patches =() and opts={"test":"test"} 

Trong trường hợp giá trị thứ hai import_(1,2,3,patch1=4,test="test")

u1 = 1, repo = 2, patch1 = 3 , patches = (4) and opts={"test":"test"} 

Trong trường hợp giá trị thứ ba import_(1,2,3,4,5)

u1 = 1, repo = 2, patch1 = 3 , patches=(4,5), and opts={} 

Trong trường hợp giá trị thứ tư import_(1,2,patch1=3,test="test")

u1 = 1, repo = 2, patch1 = 3 , patches=(), and opts={"test":"test"} 
you can use patch1 as a keywords argument but doing so you cannot wrap any variable positional arguments within patches 
+0

Cảm ơn các ví dụ và tài liệu tham khảo của bạn, tôi nghĩ rằng tôi nhận được câu trả lời của tôi. python của đối số rất linh hoạt, tôi không biết về nó cũng đủ trước khi vấn đề này. – guoqiao

2

Vì việc chuyển khóa cho đối số từ khóa có thể là tùy chọn nếu vị trí của nó rõ ràng. Quan sát:

>>> def f(ui, patch1=None, *patches, **opts): 
...  print patch1 
... 
>>> f(1, 2) 
2 
>>> f(1, patch1='a', 3) 
    File "<stdin>", line 1 
SyntaxError: non-keyword arg after keyword arg 
>>> f(1, 'a', 3) 
a 

Như bạn thấy, bỏ chìa khóa của patch1 làm cho lập luận rằng một tổ chức phi từ khóa một, do đó không gây ra các SyntaxError ngoại lệ.


EDIT: moooeeeep trong câu trả lời của ông nói rằng

"patch1 được không phải là một arg từ khóa, đó là một arg vị trí với một giá trị tham số mặc định được giao."

Đây không phải là sai, nhưng các hợp cụ thể sau đây IMO, minh họa tại sao định nghĩa như là mơ hồ:

>>> def f(ui, p1=None, p2=None, *patches, **opts): 
... print p1, p2 
... 
>>> f(1, 'a', 'b', 3) #p2 is a positional argument with default value? 
a b 
>>> f(1, p2='b') #p2 is a keyword argument? 
None b 

HTH!

+0

vâng ... theo ý kiến ​​của tôi, đó là sự mơ hồ trong thời gian chạy, không phải là sự mơ hồ về thời gian. Vì OP có liên quan với định nghĩa hàm [Tôi đã mô tả định nghĩa hàm] (http://stackoverflow.com/a/8486166/1025391). Nhưng tôi thừa nhận, đây là một điểm đáng lưu ý. – moooeeeep

3

Có thể bạn đang bối rối định nghĩa hàm và cú pháp gọi hàm một chút.

patch1 không phải là từ khóa arg, đó là một vị trí arg có giá trị đối số mặc định được chỉ định.

*patches là danh sách đối số và không phải là đối số vị trí.


hãy có một cái nhìn tại phần này từ các hướng dẫn chính thức:

Bây giờ hãy để tôi tóm tắt những điểm chính sử dụng chức năng này là một ví dụ:

def f1(a1, a2, a3=None, *args, **kwargs): 
    print a1, a2, a3, args, kwargs 

Chức năng Định nghĩa

Bạn có một số các đối số được định nghĩa một cách rõ ràng theo tên (a1, a2a3), trong đó a3 sẽ mặc định khởi tạo bởi None nếu không được cung cấp trong suốt cuộc gọi. Các đối số a1a2 cần được cung cấp trong bất kỳ cuộc gọi hợp lệ nào của chức năng đó.

Chức năng có thể được gọi với các đối số bổ sung sẽ xuất hiện trong từ điển kwargs (khi được cung cấp theo từ khóa) hoặc trong danh sách args (khi không được cung cấp theo từ khóa). Nếu argskwargs sẽ không có mặt trong định nghĩa hàm, người gọi sẽ không được phép thêm đối số khác ngoài những đối số được đặt tên rõ ràng trong định nghĩa hàm cho lệnh gọi hàm.

Trong định nghĩa hàm bạn cần xác định các đối số rõ ràng không có trình khởi tạo mặc định trước tiên, thứ hai đối số rõ ràng với trình khởi tạo mặc định, danh sách đối số thứ ba, cuối cùng là từ điển đối số từ khóa.

Chức năng Gọi

Có nhiều cách khác nhau để gọi hàm. Ví dụ các cuộc gọi sau đây sẽ tạo ra kết quả như nhau:

f1(1, 2)  # pass a1 and a2 as positional arguments 
f1(a2=2, a1=1) # pass a1 and a2 as keyword arguments 
f1(1, a2=2) # pass a1 as positional argument, a2 as keyword argument 

Đó là, các đối số chức năng được giải quyết bằng cách vị trí của họ (vị trí, hoặc không khóa luận) hoặc bằng tên được chỉ định của họ (đối số từ khóa).

Khi gọi hàm bạn cần đặt đối số không phải từ khóa trước tiên và cuối cùng là đối số từ khóa, ví dụ:

# demonstrate how some additional positional and keyword arguments are passed 
f1(1, 2, 3, 4, 5, 6, 7, a4=8, a5=9, a6=10) 
# prints: 
# 1 2 3 (4, 5, 6, 7) {'a5': 9, 'a4': 8, 'a6': 10} 

Bây giờ, đối số vị trí không phù hợp với danh sách các đối số quy định trong định nghĩa chức năng sẽ được nối thêm vào danh sách đối số *args, và đối số từ khóa đó không phù hợp với danh sách các đối số quy định tại định nghĩa hàm sẽ được chèn vào từ khóa đối số từ khóa **kwargs.

+0

Tôi tìm thấy định nghĩa này hơi mơ hồ (mặc dù không chính xác). Xem chỉnh sửa trong câu trả lời của tôi về lý do. – mac

+0

cảm ơn! xem bình luận của tôi về câu trả lời của bạn:] – moooeeeep

+0

Xem ví dụ của tôi, bạn có thể sử dụng patch1 làm đối số từ khóa được cung cấp không có đối số vị trí nào sau nó. – Abhijit

2

Tôi tin rằng khi gọi một hàm với:

function(arg1="value") 

này sẽ được sử dụng một "từ khoá" cãi nhau, nhưng khi xác định giao diện một chức năng với:

def function(arg1="value"): 

bạn đang xác định một "giá trị mặc định" .()

Vì vậy, để trả lời câu hỏi của bạn; Việc có một giá trị mặc định sau một đối số vị trí là hoàn toàn bình thường, và do đó đang gọi một hàm có đối số không phải từ khóa trước một từ khóa.

Cũng lưu ý, khi gọi một hàm, bạn không thể có đối số không phải từ khóa sau từ khóa.

+0

cảm ơn câu trả lời của bạn. – guoqiao

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