Có cách nào để truyền tham số tùy chọn cho hàm không?


132

Có cách nào trong Python để truyền tham số tùy chọn cho hàm trong khi gọi hàm và trong định nghĩa hàm có một số mã dựa trên "chỉ khi tham số tùy chọn được truyền"

Câu trả lời:


114

Các Python 2 tài liệu, 7.6. Các định nghĩa hàm cung cấp cho bạn một vài cách để phát hiện xem người gọi có cung cấp tham số tùy chọn hay không.

Đầu tiên, bạn có thể sử dụng cú pháp tham số chính thức đặc biệt *. Nếu định nghĩa hàm có một tham số chính thức đứng trước một *, thì Python sẽ điền tham số đó với bất kỳ tham số vị trí nào không khớp với các tham số chính thức trước đó (dưới dạng một tuple). Nếu định nghĩa hàm có một tham số chính thức đi trước **, thì Python sẽ điền tham số đó với bất kỳ tham số từ khóa nào không khớp với các tham số chính thức trước đó (dưới dạng chính tả). Việc triển khai của hàm có thể kiểm tra nội dung của các tham số này xem có "tham số tùy chọn" nào của loại bạn muốn không.

Ví dụ, đây là một chức năng opt_funmà phải mất hai tham số vị trí x1x2, và ngoại hình cho một tham số từ khóa có tên là "bắt buộc".

>>> def opt_fun(x1, x2, *positional_parameters, **keyword_parameters):
...     if ('optional' in keyword_parameters):
...         print 'optional parameter found, it is ', keyword_parameters['optional']
...     else:
...         print 'no optional parameter, sorry'
... 
>>> opt_fun(1, 2)
no optional parameter, sorry
>>> opt_fun(1,2, optional="yes")
optional parameter found, it is  yes
>>> opt_fun(1,2, another="yes")
no optional parameter, sorry

Thứ hai, bạn có thể cung cấp một giá trị tham số mặc định của một số giá trị Nonemà người gọi sẽ không bao giờ sử dụng. Nếu tham số có giá trị mặc định này, bạn biết người gọi không chỉ định tham số. Nếu tham số có giá trị không mặc định, bạn biết nó đến từ người gọi.


7
positional_parameterslà một tuple, và keyword_parametersmột từ điển.
Cees Timmerman

Làm thế nào để trăn phân biệt formal parameters preceded by * (cái này được gọi là gì?) Từ a keyword parameter? Theo tôi hiểu, các tham số từ khóa được chỉ định bằng cách sử dụng =toán tử trong lệnh gọi hàm (do đó opt_fun(1,2, optional="yes")cung cấp một đối số từ khóa "có" cho một hàm dự đoán, nhưng không nhất thiết yêu cầu tham số option).
Minh Trần

Mặt khác, tôi hiểu formal parameters preceded by * đơn giản là "các đối số do người gọi cung cấp không tương ứng với các đối số vị trí đi trước bất kỳ đối số từ khóa nào". Ví dụ, trong opt_fun(1,2, "blah", 3.14, mykey="yes", myyear="2018"), "blah"3.14forma arguments preceded by *vì nó ở giữa hai đối số vị trí và lập luận rằng sử dụng các =dấu hiệu. Bộ dữ liệu kết quả positional_parametersẽ là bản sao : ("blah", 3.14). Điều này có đúng không?
Minh Trần

@MinhTran, câu hỏi trong nhận xét không phải là cách tốt nhất để có câu trả lời trong Stack Overflow. Tốt hơn hết là nhấp vào nút "Đặt câu hỏi" màu xanh lam lớn và viết yêu cầu của bạn dưới dạng "Câu hỏi" mà người khác có thể "Trả lời". Nhưng để giúp bạn, một) lưu ý tôi đã viết " parameter" không " parameters" cho " preceded by *". Ngôn ngữ chỉ cho phép một *identifiertrong danh sách tham số. b) đọc docs.python.org/2/reference/ , c) đọc docs.python.org/2/reference/expressions.html#calls . Xin lỗi, hết các ký tự được phép trong bình luận này.
Jim DeLaHunt

81
def my_func(mandatory_arg, optional_arg=100):
    print(mandatory_arg, optional_arg)

http://docs.python.org/2/tutorial/controlflow.html#default-argument-values

Tôi thấy điều này dễ đọc hơn sử dụng **kwargs.

Để xác định xem một đối số có được thông qua hay không, tôi sử dụng một đối tượng tiện ích tùy chỉnh làm giá trị mặc định:

MISSING = object()

def func(arg=MISSING):
    if arg is MISSING:
        ...

-Cảm ơn, có cách nào để xác định giá trị mặc định của tham số này là một biến khác trong mã không?
dùng1795998

Đúng. default_value=100; def my_func(mandatory_argument, optional_argument_with_default_value=default_value): ...
warvariuc

Điều này dường như cho thấy cách sử dụng các tham số tùy chọn, nhưng không phải cách kiểm tra nếu một thông số được thông qua, đó là những gì OP đang yêu cầu.
Mawg nói rằng phục hồi Monica

4
Trong hầu hết các trường hợp, đây là giải pháp đơn giản và đơn giản hơn Jim. Nếu bạn đặt giá trị mặc định thành Không thì bạn có thể kiểm tra xem tham số có được thông qua hay không. Trường hợp duy nhất mà giải pháp của Jim tốt hơn là nếu việc phân biệt giữa không có ai là đối số và không truyền đối số nào là quan trọng.
Arnon Axelrod

19
def op(a=4,b=6):
    add = a+b
    print add

i)op() [o/p: will be (4+6)=10]
ii)op(99) [o/p: will be (99+6)=105]
iii)op(1,1) [o/p: will be (1+1)=2]
Note:
 If none or one parameter is passed the default passed parameter will be considered for the function. 

1
Có cách nào để chỉ truyền tham số thứ hai (b) chứ không phải thông số thứ nhất (a) không?
Djidiouf

4
@Djidiouf Vâng, cóop(b=2)
Jürg Merlin Spaak

7

Nếu bạn muốn cung cấp một số giá trị mặc định cho một tham số gán giá trị trong (). thích (x = 10). Nhưng quan trọng là đầu tiên nên bắt buộc đối số sau đó giá trị mặc định.

ví dụ.

(y, x = 10)

nhưng

(x = 10, y) sai


Cảm ơn, có cách nào để xác định giá trị mặc định của tham số này là một biến khác trong mã không?
dùng1795998

Có, bạn có thể sử dụng một cái gì đó được gọi *arg **karglà đối số chức năng. tìm kiếm trên Google.
Djuzz

Điều này dường như cho thấy cách sử dụng các tham số tùy chọn, nhưng không phải cách kiểm tra nếu một thông số được thông qua, đó là những gì OP đang yêu cầu.
Mawg nói rằng phục hồi Monica

2

Bạn có thể chỉ định một giá trị mặc định cho đối số tùy chọn với thứ không bao giờ được truyền cho hàm và kiểm tra nó với istoán tử:

class _NO_DEFAULT:
    def __repr__(self):return "<no default>"
_NO_DEFAULT = _NO_DEFAULT()

def func(optional= _NO_DEFAULT):
    if optional is _NO_DEFAULT:
        print("the optional argument was not passed")
    else:
        print("the optional argument was:",optional)

sau đó miễn là bạn không làm được, func(_NO_DEFAULT)bạn có thể phát hiện chính xác liệu đối số có được thông qua hay không, và không giống như câu trả lời được chấp nhận, bạn không phải lo lắng về tác dụng phụ của ký hiệu **:

# these two work the same as using **
func()
func(optional=1)

# the optional argument can be positional or keyword unlike using **
func(1) 

#this correctly raises an error where as it would need to be explicitly checked when using **
func(invalid_arg=7)

Cứ làm đi _NO_DEFAULT = object().
Aran-Fey

2 dòng thêm để cung cấp nội tâm tốt hơn là giá trị nó. Với điều này nếu bạn chạy, help(func)bạn sẽ có được một ý tưởng rõ ràng hơn về cách đối số được diễn giải nếu không được thông qua rõ ràng.
Tadhg McDonald-Jensen
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.