2012-02-01 11 views
38

Ho bisogno di scrivere questi quattro if s in Python. Notate cosa fa, sta cambiando tra quattro possibili stati in un ciclo: 1,0 -> 0,1 -> -1,0 -> 0,-1 e ritorno al primo.C'è un modo per scrivere questi ifs più belli?

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 

Qualcuno può suggerirmi un modo migliore/più bello di scrivere questo?

+8

Non sono un esperto di python, ma sembra una tabella di transizione di stato, quindi li inserirò in un dict in cui la chiave è lo stato from e il valore è lo stato to. –

+9

Intendevi 'elif' sulle linee 3,5,7? Perché così com'è 1,0 sarebbe preso di nuovo su una caccia all'oca selvaggia di 1,0! – wim

+0

@wim: In realtà, '1, 0' diventerebbe' 0, 1' come previsto, poiché '[dx, dy] == 0, 1' è sempre falso. –

risposta

156
dx, dy = -dy, dx 

In caso di dubbio, applicare la matematica. ;)

+2

Ah, semplicità :-) – stiank81

55

suggerimento Magnus' è senza dubbio la risposta giusta alla tua domanda, come poste, ma in generale, si desidera utilizzare un dizionario per problemi come questo:

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

dx, dy = statemap[dx, dy] 

Anche in questo caso ho potuto argomentare usando un dizionario è meglio, dal momento che è chiaro che ci sono esattamente quattro stati e che ripetono, ma è difficile resistere alla bellezza pura di tutte le math.

Tra l'altro, il codice nella tua domanda ha un bug in esso, e, assumendo che i valori si prova per sono gli unici valori possibili, è equivalente a:

dx, dy = 1, 0 

Il bug è che hai bisogno di elif per la seconda e successive condizioni, altrimenti continuerai a testare dx e dy dopo averle modificate. Se sono 1 e 0, quindi tutte le tue condizioni saranno vere e finiranno allo stesso modo alla fine! Se iniziano come 0 e 1 allora la seconda e tutte le condizioni successive saranno vere, e si finisce nuovamente con 1, 0. E così via ...

6

Mentre vorrei andare con risposta Magnus', qui c'è ancora un altro approccio per la rotazione su un insieme di valori:

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 

noti che ci dovrebbe essere un break da qualche parte nel ciclo for dx, dy altrimenti è destinato a senza fine.

+4

['itertools.cycle (...)'] (http://docs.python.org/library/itertools.html#itertools.cycle), sebbene non sia un esatto drop-in per il tuo "ruotare", può risolvere lo stesso problema. –

+0

Infatti, ho dimenticato "ciclo". Grazie. – yak

18

I valori con cui stai lavorando sembrano essere un vettore unitario che ruota continuamente - in altre parole, un phasor. Complex numbers are coordinates, quindi:

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

Supponendo che la mia interpretazione del significato della dx, valori dy è corretta, questo ti dà maggiore flessibilità nel caso in cui si scopre più tardi che si desidera ruotare da qualche altra somma in ogni passaggio.

31

Basta estendere la risposta di Magnus. Se immagini [dx, dy] come un vettore, ciò che stai facendo in realtà è uno rotation di 90 gradi (o PI/2).

Per calcolare questo, è possibile utilizzare la seguente trasformazione:

two dimensional rotation

che nel tuo caso si traducono in:

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

Dal sin(90) = 1 e cos(90) = 0 semplifichiamo a:

x, y = -y, x 

E ce l'hai!

+5

Sebbene Magnus Hoff possa avere +1 per eleganza, credo che questo dovrebbe essere +1 per la derivazione dell'eleganza. – oaxacamatt

+0

Mostra anche la relazione tra la risposta di Magnus Hoff e la mia. –

Problemi correlati