Использование словарей в Python вместо оператора Case/Switch
Я хочу рандомизировать кубик Рубика, который инициализируется как завершенный (все цвета на правильных сторонах). У меня есть функции перемещения, которые вращают куб. Я хочу случайным образом выбрать 50 функций подряд, чтобы правильно их рандомизировать.
Я делаю этот проект, чтобы узнать немного больше о Python, так как в основном я делаю C++ и вижу, что для Python нет регистра / переключателя, поэтому я пробую словарь. Когда я создаю словарь, кажется, что код выполняется по какой-то причине:
def random_cube(self):
scramble = { 0 : self.up_turn(),
1 : self.down_turn(),
2 : self.left_turn(),
3 : self.right_turn(),
4 : self.front_turn(),
5 : self.back_turn(),
6 : self.up_turn("inverted"),
7 : self.down_turn("inverted"),
8 : self.left_turn("inverted"),
9 : self.right_turn("inverted"),
10: self.front_turn("inverted"),
11: self.back_turn("inverted")
}
for x in range(50):
i = random.randint(0,11)
scramble[i]
Поэтому, когда я делаю этот словарь, он почему-то просматривает и выполняет все 11 записей (я думаю). Кажется, я не могу найти лучшего способа, по крайней мере, более элегантного, чем длинная строка утверждений if/elif.
! РЕДАКТИРОВАТЬ: При реализации обоих предложений флаг ("инвертированный") для функций не устанавливается ни одним предложением. Например, вызовы 1 и 7 дают мне down_turn, но вывод показывает, что флаг не был установлен, когда он должен был быть на номер 7.
Есть идеи?
2 ответа
Когда вы определяете dict, он фактически вызывает функции и сохраняет возвращаемое значение в словаре. Чтобы в словаре хранилась ссылка на функции, вам нужно удалить завершающие скобки. Так что-то вроде:
scramble = { 0: self.up_turn,
1: self.down_turn,
etc.
Затем в нижней части позвоните scramble[i]()
,
Это вызовет функцию без аргументов. Чтобы обработать случай, когда вы передаете "инвертированный" в качестве аргумента, вы можете либо определить отдельные функции, такие как up_turn_inverted() и т. Д., Либо вы можете иметь словарь для хранения 2-х элементов, состоящих из функции и аргумента, а затем вызвать что-то нравится scramble[i][0](scramble[i][1])
Обновление от предложения в комментариях: Вы также можете использовать лямбда-выражения для определения функций, особенно тех, которые требуют аргумента. Это в основном эквивалентно определению функции up_turn_inverted, но выполняется на месте как анонимная функция. Это будет выглядеть так:
6: lambda: self.up_turn("inverted")
7: lambda: self.down_turn("inverted")
и т.п.
Я полагаю, что это называется "функции как первоклассные значения", подразумевая, что самое важное, вы можете передавать идентификаторы, относящиеся к функциям, в качестве параметров другим функциям.
Когда вы определяете свой словарь, интерпретатор Python оценивает функции и сохраняет значения в словаре. Чтобы отложить это до тех пор, пока вы не сгенерируете свои случайные числа, попробуйте вместо этого сохранить ссылки на сами функции в вашем словаре, оставив скобки:
def random_cube(self):
scramble = { 0 : self.up_turn,
1 : self.down_turn,
2 : self.left_turn,
3 : self.right_turn,
4 : self.front_turn,
5 : self.back_turn,
6 : self.up_turn,
7 : self.down_turn,
8 : self.left_turn,
9 : self.right_turn,
10: self.front_turn,
11: self.back_turn
}
Затем при вызове ваших функций в цикле for вам нужно будет различать ваши обычные и инвертированные случаи, по которым передаются параметры:
for x in range(50):
i = random.randint(0,11)
if i <= 5:
scramble[i]()
else:
scramble[i]("inverted")
или проще:
for x in range(50):
i = random.randint(0,11)
scramble[i]( () if i < 6 else ("inverted"))