2010-07-25 26 views
8

I documenti Python dicono che * e/hanno la stessa precedenza.
So che le espressioni in python vengono valutate da sinistra a destra.Precisione operatore Python

posso usufruire in questo ed assumere che j j/m è sempre uguale a (j j)/m evitando le parentesi?
Se questo è il caso, posso supporre che ciò valga per gli operatori con la stessa precedenza in generale?


ps: La questione è bene per i miei scopi, sono venuto ad esso durante la lettura interi solo il codice (come nell'esempio sopra) senza parentesi, che all'epoca sembrava molto sospetto per me .

+7

"Esplicito è meglio di implicito.", "Di fronte all'ambiguità, rifiuta la tentazione di indovinare." - PEP 20 – msw

+0

british: Se stai leggendo "codice intero solo", hai un problema molto più grande: Quale versione di Python era destinata ad essere utilizzata per eseguirla? Il codice ha 'da __future__ import division' in primo piano? Dovrebbe questo '/' essere letto come e/o cambiato in '//'? –

+0

@John Machin:/significa divisione integer in questo caso, è python 2.6 senza le cose future, ho notato che i codici come j * j/m (j * j)/m erano uguali, ma avevo paura della coerenza se questo comportamento –

risposta

14

Sì - diversi operatori con la stessa precedenza sono associati a sinistra; cioè, verranno utilizzati i due elementi più a sinistra, quindi il risultato e il terzo elemento, e così via.

Un'eccezione è l'operatore di **:

>>> 2 ** 2 ** 3 
256 

Inoltre, gli operatori di confronto (==, >, eccetera) non si comportano in maniera associativa, ma invece di tradurre in x [cmp] y [cmp] z(x [cmp] y) and (y [cmp] z).

+6

L'assegnazione non è in realtà un'espressione in Python e '=' non è un operatore nel senso normale; la precedenza dell'operatore non si applica. L'assegnazione a più destinazioni è esplicitamente definita nella grammatica esattamente come quella: assegnazione dello stesso oggetto a più destinazioni. –

+2

Wrong about assignment, pls change example! L'unico operatore in Python associato a destra-sinistra è '**', come in '2 ** 3 ** 4' –

+0

@Amber: (1) come @Nas Banov ha detto,' ** 'è l'UNICO L'operatore Python che è right-associative (2) che è giusto-associativo con se stesso è il risultato insignificante di fatto [1] (3) gli operatori di confronto sono NON-associative ... 'a

3

Risposta breve: sì.

Gli Operatori Python documentation says the following:

nella stessa casella hanno la stessa precedenza. A meno che la sintassi non sia esplicitamente data, gli operatori sono binari. Gli operatori nello stesso gruppo si spostano da sinistra a destra (tranne per i confronti, inclusi i test, che hanno tutti la stessa precedenza e catena da sinistra a destra ... e l'esponenziazione, quali gruppi da destra a sinistra).

Quindi, in altre parole la risposta alla tua domanda è sì, gli operatori con la stessa priorità verranno gruppo da sinistra a destra a parte Comparisions which chain rather than group:

>>> x = 0 
>>> y = 0 
>>> x == y == True 
False 
>>> (x == y) == True 
True 
>>> x == (y == True) 
True 

e Exponentation:

>>> 2 ** 2 ** 3 
256 
>>> (2 ** 2) ** 3 
64 
>>> 2 ** (2 ** 3) 
256 

anche , in assegnazione il lato destro viene valutato prima sul lato sinistro:

>>> x = 1 
>>> y = x = 2 
>>> y 
2 
+3

L'assegnazione non è un operatore (vedere sopra), e gli obiettivi sono infatti * non * valutati da destra a sinistra.Il rhs dell'assegnazione viene valutato, quindi i target vengono valutati * da sinistra a destra * e assegnati a. Puoi vedere la distinzione quando controlli l'ordine dei functioncalls in per esempio 'a(). A, b(). B = c() .c': vedrai che' c() 'viene chiamato, poi il Viene richiamato l'attributo 'c', quindi viene chiamato' a() 'e viene assegnato l'attributo' a', e solo allora lo stesso per 'b()' –

+0

non intendevo implicitamente assegnare un operatore, questo è perché è l'ultimo Ho leggermente modificato il testo sull'assegnazione. –

+0

La tua formulazione implica ancora che l'ordine di valutazione di 'x' e' y' è importante per il risultato assegnato a 'y'. Non è così. I valori di 'x' e' y' non sono mai coinvolti nell'assegnazione. 'y = x = 2' significa strettamente" assegna '2' a' y' e a 'x'", non "assegna' 2' a 'x', quindi il valore risultante di' x' a 'y'" (che, ancora una volta, puoi vedere quando coinvolgi obiettivi di assegnazione più complessi, come quando usi proprietà che si impostano su valori diversi da quelli che assegni a loro. –

13

Ma, se è ambiguo per voi - il programmatore - e deve essere perché dovete chiedere, allora aspettatevi che sia almeno altrettanto ambiguo per il lettore e sprecate un paio di ottetti per chiarezza.

Affidarsi alle regole di precedenza è ottimo se si è un compilatore.

aggiunto risposte alle osservazioni:

Per la persona che legge il codice che incontra un'ambiguità che richiede la consultazione di fuori per la garanzia, si deve supporre che il prossimo lettore sarà meno esperti di te e salvare loro la fatica e errore umano evitabile di analizzare lo stesso costrutto e aggiungere la parentesi per loro.

In questo caso, anche la risposta accettata era errata (in logica, non in effetto, si veda il suo primo commento) di cui non ero a conoscenza e nemmeno una frazione di coloro che l'avevano svalutato.

Per quanto riguarda la descrizione dell'algebra di base, l'esempio particolare utilizzato nell'OP è istruttivo. Indipendentemente dalla precedenza dell'operatore, l'espressione j * (j/m) è algebricamente identica a (j * j)/m. Sfortunatamente, l'algebra di Python è solo un'approssimazione dell'algebra "platonica ideale" che potrebbe dare risposte sbagliate per entrambe le forme a seconda della magnitudine di j e m. Per esempio:

>>> m = 1e306 
>>> m 
1e+306 
>>> j = 1e307 
>>> j 
9.9999999999999999e+306 
>>> j/m 
10.0 
>>> j*j 
inf 
>>> j * (j/m) 
1e+308 
>>> (j * j)/m 
inf 
>>> ((j * j)/m) == (j * (j/m)) 
False 

così effettivamente la proprietà dell'identità di Python (e il mio FPU) quasi-algebra non regge. E questo può essere diverso sulla vostra macchina per le documentation notes: numeri in virgola

galleggianti sono implementati utilizzo di un doppio in C. Tutte le scommesse sul loro precisione sono fuori a meno che non vi capita di conoscere la macchina si sta lavorando .

si potrebbe affermare che non si ha affari di lavoro sul bordo pelosa di troppo pieno, e questo è vero in una certa misura, ma rimosso dal contesto l'espressione è indeterminato in un ordine delle operazioni e "corretta" sotto un'altra.

+0

Vorrei dare +10 a questa risposta se potessi. :) Questo è un punto molto importante. – EOL

+0

Per ottenere un acaro filosofico, la risposta accettata è davvero la risposta corretta alla domanda che è stata posta. Il che significa che la domanda è sbagliata, ed è al punto in cui si chiede di "evitare le parentesi". Avendo recentemente dovuto scavare una libreria funzionante ma tortuosamente illeggibile, sono diventato profondamente sensibile alla differenza negli standard espressivi di Python e al suo uso nella pratica comune. – msw

+2

perché pensi che sto provando a scrivere codice? cosa succede se ... sto cercando di leggere. –