2011-01-12 26 views
8

Có thể chuyển số lượng tùy ý các đối số mặc định được đặt tên cho hàm Python có điều kiện không?Điều kiện chuyển số tùy ý các đối số mặc định được đặt tên cho hàm

Ví dụ: có một chức năng:

def func(arg, arg2='', arg3='def') 

Bây giờ logic là rằng tôi có một tình trạng mà quyết định nếu arg3 cần phải được thông qua, tôi có thể làm điều đó như thế này:

if condition == True: 
    func('arg', arg2='arg2', arg3='some value') 
else: 
    func('arg', arg2='arg2') 

Câu hỏi là, tôi có thể có một cách viết tắt như:

func('arg', 'arg2', 'some value' if condition == True else # nothing so default gets picked 
) 

Trả lời

5

cách duy nhất tôi có thể nghĩ đến sẽ là

func("arg", "arg2", **({"arg3": "some value"} if condition == True else {})) 

hoặc

func("arg", "arg2", *(("some value",) if condition == True else())) 

nhưng xin đừng làm điều này. Sử dụng đoạn mã mà bạn cung cấp cho mình, hoặc một cái gì đó như thế này:

if condition: 
    arg3 = "some value", 
else: 
    arg3 =() 
func("arg", "arg2", *arg3) 
+2

Bạn có gì chống lại ** và *? – Erin

+2

Không có gì chống lại '*' và '**'. Tôi chỉ nghĩ rằng mã ban đầu là dễ đọc hơn. Tôi nghĩ tôi không thích 'a if c else b'. –

+0

Ngoài ra, một số logic có điều kiện có thể được sử dụng (bên ngoài cuộc gọi hàm) để xây dựng một từ điển các đối số.Sau đó, chúng có thể được thông qua với '**'. Điều này vẫn có thể đọc được với số lượng đối số lớn hơn. – Wilduck

8

Đó sẽ không phải là cú pháp hợp lệ Python bạn cần phải có một cái gì đó sau khi else. Những gì được thực hiện thường là:

func('arg', 'arg2', 'some value' if condition else None) 

và định nghĩa hàm được thay đổi cho phù hợp:

def func(arg, arg2='', arg3=None): 
    arg3 = 'def' if arg3 is None else arg3 
1

Nếu bạn có một hàm có nhiều đối số mặc định

def lots_of_defaults(arg1 = "foo", arg2 = "bar", arg3 = "baz", arg4 = "blah"): 
    pass 

và bạn muốn chuyển các giá trị khác nhau cho một số trong số này, dựa trên điều gì đó khác đang diễn ra trong chương trình của bạn, cách đơn giản là sử dụng ** để giải nén từ điển tên và giá trị đối số mà bạn đã tạo ed trên logic chương trình của bạn.

different_than_defaults = {} 
if foobar: 
    different_than_defaults["arg1"] = "baaaz" 
if barblah: 
    different_than_defaults["arg4"] = "bleck" 

lots_of_defaults(**different_than_defaults) 

Điều này có lợi ích không làm tắc nghẽn mã của bạn tại thời điểm gọi chức năng của bạn, nếu có rất nhiều logic xác định những gì đi vào cuộc gọi của bạn. Bạn sẽ cần phải cẩn thận nếu bạn có bất kỳ đối số nào không có mặc định, để bao gồm các giá trị bạn đang chuyển cho những giá trị trước khi chuyển từ điển của bạn.

0

Bạn có thể viết một hàm helper

def caller(func, *args, **kwargs): 
    return func(*args, **{k:v for k,v in kwargs.items() if v != caller.DONT_PASS}) 
caller.DONT_PASS = object() 

Sử dụng chức năng này để gọi chức năng khác và sử dụng caller.DONT_PASS để xác định lập luận rằng bạn không muốn để vượt qua.

caller(func, 'arg', 'arg2', arg3 = 'some value' if condition else caller.DONT_PASS) 

Lưu ý rằng điều này caller() chỉ hỗ trợ các đối số từ khóa có điều kiện. Để hỗ trợ các đối số vị trí, bạn có thể cần sử dụng mô-đun inspect để kiểm tra chức năng.

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