2017-07-03 19 views
6

Tôi có bộ giá trị mà tôi muốn áp dụng như tham số cho một hàm:Execute chức năng trên tất cả các kết hợp có thể các thông số

params = { 
    'a': [1, 2, 3], 
    'b': [5, 6, 7], 
    'x': [None, 'eleven', 'f'], 
    # et cetera 
} 

Tôi muốn chạy myfunc() với tất cả các kết hợp có thể, vì vậy myfunc(a=1, b=5, x=None ...), myfunc(a=2, b=5, x=None ...) .. myfunc(a=3, b=7, x='f' ...). Có điều gì đó không (ví dụ: itertools) có thể trợ giúp? Tôi nghĩ về việc sử dụng itertools.product() nhưng điều đó không giữ tên của các tham số và chỉ cung cấp cho tôi bộ dữ liệu kết hợp.

Trả lời

5

Bạn có thể sử dụng itertools.product để có được tất cả các kết hợp của đối số:

>>> import itertools 
>>> for xs in itertools.product([1,2], [5,6], ['eleven', 'f']): 
...  print(xs) 
... 
(1, 5, 'eleven') 
(1, 5, 'f') 
(1, 6, 'eleven') 
(1, 6, 'f') 
(2, 5, 'eleven') 
(2, 5, 'f') 
(2, 6, 'eleven') 
(2, 6, 'f') 

Với Argument list unpacking, bạn có thể gọi myfunc với tất cả các kết hợp của các đối số từ khóa:

params = { 
    'a': [1, 2, 3], 
    'b': [5, 6, 7], 
    'x': [None, 'eleven', 'f'], 
} 

def myfunc(**args): 
    print(args) 

import itertools 
keys = list(params) 
for values in itertools.product(*map(params.get, keys)): 
    myfunc(**dict(zip(keys, values))) 

đầu ra:

{'a': 1, 'x': None, 'b': 5} 
{'a': 1, 'x': None, 'b': 6} 
{'a': 1, 'x': None, 'b': 7} 
{'a': 1, 'x': 'eleven', 'b': 5} 
{'a': 1, 'x': 'eleven', 'b': 6} 
{'a': 1, 'x': 'eleven', 'b': 7} 
{'a': 1, 'x': 'f', 'b': 5} 
... 
+0

Đó là rất gọn gàng! Tôi lo lắng về thứ tự đang được tắt mặc dù, vì dicts là không có thứ tự (phải không?). Điều đó có nghĩa là 'itertools.product()' trả về các tham số theo thứ tự khác hơn là bạn có các khóa, điều này sẽ dẫn đến sự không khớp. – Bluefire

+0

@Bluefire, 'myfunc (a = 1, b = 2, c = 3)', 'myfunc (b = 2, c = 3, a = 1)' cả hai đều ổn. – falsetru

+2

'map (params.get, keys)' là một cách viết không cần thiết để viết 'params.values ​​()' tại đây; nó được đảm bảo rằng '.keys()' và '.values ​​()' sẽ căn chỉnh trừ khi từ điển được sửa đổi. – DSM

3

Đặt hàng của .keys.valuesđảm bảo trên tất cả các phiên bản Python (trừ khi dict bị thay đổi mà không xảy ra ở đây), vì vậy đây có thể là một chút không đáng kể:

from itertools import product 

for vals in product(*params.values()): 
    myfunc(**dict(zip(params, vals))) 

Bạn có thể tìm ra bảo lãnh trong docs:

Nếu chế độ xem khóa, giá trị và mục được lặp lại mà không có sự sửa đổi sửa đổi đối với từ điển, thứ tự của các mục sẽ trực tiếp tương ứng.


Demo:

for vals in product(*params.values()): 
    print(dict(zip(params, vals))) 

{'a': 1, 'x': None, 'b': 5} 
{'a': 1, 'x': None, 'b': 6} 
{'a': 1, 'x': None, 'b': 7} 
{'a': 1, 'x': 'eleven', 'b': 5} 
{'a': 1, 'x': 'eleven', 'b': 6} 
{'a': 1, 'x': 'eleven', 'b': 7} 
{'a': 1, 'x': 'f', 'b': 5} 
{'a': 1, 'x': 'f', 'b': 6} 
{'a': 1, 'x': 'f', 'b': 7} 
... 
+2

Có thể thêm liên kết vào [đảm bảo] (https://docs.python.org/3/library/stdtypes.html # dictionary-view-objects)? – DSM

+2

@DSM Có thưa ông, bao gồm. Cảm ơn. –

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