Скажите, у меня есть список списков. Каждый ключ представляет переменную, а каждый список представляет возможные значения, которые может иметь переменная.
myBools = [ True, False ]
myInts = [ -3, 0, 4 ]
myFloats = [ -2.2, 0.0, 1.1 ]
myDict = {
'aBool': myBools,
'bInt': myInts,
'cFloat': myFloats,
}
Теперь, как мне получить список диктов для всех перестановок aBool, bInt и cFloat? Каждая запись в списке будет диктовать. Каждый dict будет иметь уникальный набор значений, представляющих одну перестановку.
Ожидаемое:
myPermList = [
{ 'aBool': True, 'bInt': -3, 'cFloat': -2.2 },
{ 'aBool': True, 'bInt': -3, 'cFloat': 0.0 },
{ 'aBool': True, 'bInt': -3, 'cFloat': 1.1 },
# ...
{ 'aBool': False, 'bInt': 4, 'cFloat': -2.2 },
{ 'aBool': False, 'bInt': 4, 'cFloat': 0.0 },
{ 'aBool': False, 'bInt': 4, 'cFloat': 1.1 },
]
У меня возникли проблемы при попытке выяснить, могут ли мне помочь здесь itertools.permutations и, если да, то как настроить вызов.
Предполагаемое использование такого метода состоит в том, чтобы помочь автоматизировать тестирование некоторых других функций всеобъемлющим и систематическим образом, чтобы я мог расширять списки для включения как хороших, так и плохих данных, чтобы проверять как правильную функциональность в случае хороших данных и правильная обработка ошибок в случае неверных данных.
myBools, myInts и myFloats будут представлять тесты для различных типов данных, которые можно использовать повторно. Они могут быть смешаны в будущем (то есть проверить данные int и float). Но написанный код представляет собой простейшую и наиболее общую структуру входных и выходных данных, о которой я только мог подумать.
Редактировать примечание 1:
Я обнаружил ограничение в первоначальной постановке задачи, которая не позволяла достичь уровня автоматизации, который я планировал. Первоначальное определение повторно используемых наборов оставляло имена наборов как переменные. Тем не менее, это может быть уместным метаданными в будущем, и к ним будет проще обращаться, если они хранятся в виде ключей словаря, а не пытаться извлекать их с использованием методов анализа кода или метапрограммирования.
Впоследствии я выбираю более описательное имя для myDict, например, myOptions. Затем я более явно продемонстрирую намерение с помощью дополнительных наборов и опций. Теперь, если я хочу проанализировать параметры с помощью дополнительного кода, это намного проще. Это на самом деле не меняет исходную проблему, просто включает дополнительные манипуляции для настройки функции itertools (продукта или перестановки), которая будет использоваться.
Наконец, так как я, очевидно, ищу не перестановку, а декартово произведение (спасибо за исправление!), Я буду хранить результат более точно и просто с именем myOptsList.
mySets = {
'myBools1': [ True, False ],
'myInts1': [ -3, 0, 4 ],
'myFloats1': [ -2.2, 0.0, 1.1 ],
'myInts2': [ -500, -250, 0, 250, 500 ],
'myFloats2': [ -88.8, -44.4, -0.0, +0.0, 44.4, 88.8 ],
# ... arbitrary number of sets
}
myOptions = {
'aBool': mySets[ 'myBools1' ],
'bInt': mySets[ 'myInts1' ],
'cFloat': mySets[ 'myFloats1' ],
'dInt': mySets[ 'myInts1' ],
'eInt': mySets[ 'myInts2' ],
'fInt': mySets[ 'myInts1' ],
'gFloat': mySets[ 'myFloats2' ],
# ... arbitary number of options,
# potentially reusing sets
}
# Set up parameters and find Cartesian product
myOptsList = [
{ 'aBool': True, 'bInt': -3, 'cFloat': -2.2, 'dInt': -3, 'eInt': -500, 'fInt': -3, 'gFloat': -88.8 },
# ...
{ 'aBool': False, 'bInt': 4, 'cFloat': 1.1, 'dInt': 4, 'eInt': 500, 'fInt': 4, 'gFloat': 88.8 },
]