Есть ли способ написать эти, если лучше? - PullRequest
38 голосов
/ 02 февраля 2012

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

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

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

Ответы [ 5 ]

156 голосов
/ 02 февраля 2012
dx, dy = -dy, dx

Если сомневаешься, применяй математику. ;)

55 голосов
/ 02 февраля 2012

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

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

dx, dy = statemap[dx, dy]

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

dx, dy = 1, 0

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

31 голосов
/ 08 февраля 2012

Просто расширяю ответ Магнуса.Если вы представляете [dx, dy] как вектор, то, что вы на самом деле делаете, это вращение из 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

И вот оно у вас!

18 голосов
/ 02 февраля 2012

Значения, с которыми вы работаете, представляют собой единичный вектор, который непрерывно вращается - другими словами, вектор . Комплексные числа являются координатами , поэтому:

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

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

6 голосов
/ 02 февраля 2012

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

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

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

...