2016-05-03 15 views
7

Stavo leggendo la 'risultato inatteso di operatore è' che avviene perché i numeri di cache Python tra -5 e 256.Python: Risultati diversi quando si usa PyCharm e IDLE/python

Questo è stato discusso qui: "is" operator behaves unexpectedly with integers

e qui: "is" and "id" in Python 3.5

Quando eseguo uno degli esempi riportati lì, ottengo risultati diversi tra Python stand-by e Python IDE (sto usando JetBrains PyCharm Professional edition - 5.0.4).

Quando si usa Python IDLE questo è il risultato:

a = 1000 
b = 1000 
print (a is b) # prints False 

quando si utilizza PyCharm 5.0.4 questo è il risultato:

a = 1000 
b = 1000 
print (a is b) # prints True 

come potrebbe essere? Ho ricontrollato, e Python-Interpreter del mio progetto è esattamente lo stesso in entrambi i casi (entrambi sono Python 3.5.1). Non sono sicuro che sia qualcosa che ho fatto di sbagliato, e speravo che qualcuno potesse spiegarlo.

Edit:

So 'a' è 'b' == true se e solo se id (a) == id (b), e che si può controllare come alcuni di voi menzionato nei commenti . Forse avrei dovuto essere più chiaro, quello che non capisco è come potrebbe essere che un IDE ha un comportamento diverso? Ho pensato (e per favore, correggimi, come mi sembra di essere sbagliato) che un IDE è solo un ambiente user-friendly che utilizza compilatori/interpreti esterni, ed è per questo che questi sono indipendenti da quegli IDE (per esempio, pycharm supporta non solo Python, e ho potuto eseguire Eclipse con compilatore C o Java, ecc (i quali non sono parti del IDE)

Grazie, Alon

risposta

4

Questo è a causa di come funziona LOAD_CONST bytecode:

Spinge co_consts[consti] nello stack.

Poiché interi sono memorizzati come costanti quindi assegnazioni per lo stesso numero intero nello stesso contesto produrrà esattamente lo stesso risultato, possiamo vedere che l'arguement a LOAD_CONST è 0 sia a e b:

>>> import dis 
>>> dis.dis("a = 1000 ; b = 1000")  
    1   0 LOAD_CONST    0 (1000) 
       3 STORE_NAME    0 (a) 
       6 LOAD_CONST    0 (1000) 
       9 STORE_NAME    1 (b) 
      12 LOAD_CONST    1 (None) 
      15 RETURN_VALUE 
             #^this is the argument 

dove come a una sessione interattiva ogni comando viene compilato separatamente (in modo che possano essere eseguite separatamente) così le costanti sarà diversa:

>>> code1 = compile("a = 1000","<dummy file>","exec") 
>>> code2 = compile("a = 1000","<dummy file>","exec") 
>>> code1.co_consts, code2.co_consts 
((1000, None), (1000, None)) 
>>> code1.co_consts[0] is code2.co_consts[0] 
False 

Analogamente la costante in funzione sarà sempre la stessa, ma sarà diversa dalla costante in altre funzioni:

def f(): 
    return 1000 
def g(): 
    return 1000 #different code object!! 

#these all work 
assert f() is f() 
assert g() is g() 
assert f() is not g() 
assert f() is not 1000 and g() is not 1000 

noti inoltre che, @AniMenon ha indicato i numeri da -5 a 256 sono single per l'ottimizzazione quindi lo stesso non vale per i numeri in quell'intervallo.

+0

Grazie! Questo è quello che mancava. – Alonbs

3

Dalla documentazione per il is operator:..

Gli operatori is e is not test per l'identità dell'oggetto: x is y è true se e solo se xey sono lo stesso oggetto.

Ora lascia controllo IDLE:

>>> a = 1000 
>>> b = 1000 
>>> print (a is b) 
False 
>>> 
>>> 
>>> id(a) 
35334812 
>>> id(b) 
35334800 

PyCharm:

>>> a = 1000 
b = 1000 
print (a is b) 
True 
>>> id(a) 
36079236 
>>> id(b) 
36079236 

In PyCharm sia a e b sono gli stessi oggetti quando in IDLE non lo sono.

Ora che cosa è instersting in PyCharm, che se si inserendo il tuo codice riga per riga, come in IDLE, si otterrà gli stessi risultati in IDLE:

>>> a = 1000 
>>> b = 1000 
>>> print (a is b) 
False 

La mia ipotesi, che

>>> a = 1000 
    b = 1000 

è ottimizzato per:

>>> a = b = 1000 
>>> print (a is b) 
True 

Quindi è per questo che hai stesso oggetto per a e b

+1

La tua ipotesi potrebbe essere supportata testando cose come 'a = 1000; b = 100 + 900' o altre operazioni che danno come risultato l'intero 1000. In questo modo non si dovrebbe ottimizzare il riferimento allo stesso oggetto, presumo. –

+0

sì, conosco la funzione id(), ma non è proprio quello che stavo chiedendo. per favore vedi il mio aggiornamento e grazie per la risposta a prescindere. – Alonbs

+0

questo è a causa dell'ottimizzazione ma non del tutto ciò che si pensava dato che 'a = 1000; b = Nessuno; c = 1000' rende anche 'a is c' Vero, potresti voler vedere [la mia risposta] (http://stackoverflow.com/a/37104846/5827215) –

0

is tornerà True se due variabili puntano allo stesso oggetto, == restituirà True se gli oggetti di cui dalle variabili sono uguali.

In Python,

>>> a = [1, 2, 3] 
>>> b = a 
>>> b is a 
True 
>>> b == a 
True 

>>> b = a[:] 
>>> b is a 
False 
>>> b == a 
True 

Ecco perché stiamo corrispondenti alla id (a) id (b).

Si consideri,

a = 1000 
b = 1000 
a is b 

a is b sarebbe falsa; le tue ipotesi sull'identità sono valide solo in CPython per i numeri compresi nell'intervallo -5 to 256, che sono singleton per ragioni di prestazioni, ma tutti gli altri sono ricreati secondo necessità e non singleton.

Sulla base: reference

Problemi correlati