2012-02-01 6 views
38

Мне нужно написать эти четыре if s в Python. Обратите внимание, что он делает, меняется между четырьмя возможными состояниями в цикле: 1,0 -> 0,1 -> -1,0 -> 0,-1 и обратно.Есть ли способ написать эти ifs лучше?

if [dx, dy] == [1,0]: 
    dx, dy = 0, 1 
if [dx, dy] == 0, 1: 
    dx, dy = -1, 0 
if [dx, dy] == [-1, 0] 
    dx, dy = 0, -1 
if [dx, dy] == [0, -1]: 
    dx, dy = 1, 0 

Может ли кто-нибудь предложить мне лучший/лучший способ написать это?

+8

Я не эксперт по python, но он выглядит как таблица перехода состояния, поэтому я буду придерживаться их в dict, где ключ - это состояние from, а значение - состояние. –

+9

Вы имели в виду 'elif' на линиях 3,5,7? Потому что, поскольку он стоит 1,0, он будет снова отправлен на дикую охоту за гусями обратно в 1,0! – wim

+0

@wim: На самом деле '1, 0' станет' 0, 1', как и ожидалось, поскольку '[dx, dy] == 0, 1' всегда false. –

ответ

156
dx, dy = -dy, dx 

При возникновении сомнений применяйте математику. ;)

+2

А, простота :-) – stiank81

55

предложение Магнуса, несомненно, правильный ответ на ваш вопрос, как корректно, но вообще говоря, вы хотите использовать словарь для проблем, как это:

statemap = {(1, 0): (0, 1), (0, 1): (-1, 0), (-1, 0): (0, -1), (0, -1): (1, 0)} 

dx, dy = statemap[dx, dy] 

Даже в этом случае я мог спорить с помощью словаря лучше, так как ясно, что есть ровно четыре состояния и они повторяются, но трудно противостоять чистой красоте все математические.

Кстати, код в вашем вопросе есть ошибка в нем, и, предполагая, что значения, проверяют на единственно возможные значения, это эквивалентно:

dx, dy = 1, 0 

Исправлена ​​ошибка в том, что вам понадобится elif для второго и последующих условий, в противном случае вы продолжите тестирование dx и dy после их замены. Если они 1 и 0, то все ваши условия будут истинными, и они заканчиваются тем же самым в конце! Если они начинаются как 0 и 1, тогда второе и все последующие условия будут истинными, и вы снова получите 1, 0. И так далее ...

6

Хотя я бы с ответом Магнуса, вот еще один подход для вращения над множеством значений:

def rotate(*states): 
    while 1: 
     for state in states: 
      yield state 

for dx, dy in rotate((1, 0), (0, 1), (-1, 0), (0, -1)): 
    pass 

Обратите внимание, что там должно быть break где-то в цикле for dx, dy или иначе это будет Никогда не кончается.

+4

['itertools.cycle (...)'] (http://docs.python.org/library/itertools.html#itertools.cycle), в то время как не точное вхождение для ваш 'rotate', может решить ту же проблему. –

+0

Действительно, забыли про 'цикл'. Благодарю. – yak

18

Значения, с которыми вы работаете, кажутся единичным вектором, который непрерывно вращается - другими словами, phasor. Complex numbers are coordinates, так:

# at initialization 
phase = 1 
# at the point of modification 
phase *= 1j 
dx, dy = phase.real, phase.imag 

Предполагая, что мое толкование смысла ого, значение д правильно, это дает вам дополнительную гибкость в случае, если выяснится позже, что вы хотите, чтобы повернуть какую-либо другая суммой в каждом шаге.

31

Просто протягивая Магнус ответ. Если вы представляете [dx, dy] как вектор, то, что вы на самом деле делаете, это rotation из 90 градусов (или PI/2).

Чтобы вычислить это, вы можете использовать следующее преобразование:

two dimensional rotation

Что в вашем случае перевести:

x = x * cos(90) - y * sin(90) 
y = x * sin(90) + y * cos(90) 

С sin(90) = 1 и cos(90) = 0 упростим его:

x, y = -y, x 

И вот оно!

+5

Хотя у Magnus Hoff может быть +1 для элегантности, я считаю, что это должно быть +1 для получения элегантности. – oaxacamatt

+0

Он также показывает связь между ответом Магнуса Хоффа и моей. –

Смежные вопросы