2016-05-03 20 views
7

Tôi chỉ đọc về 'kết quả bất ngờ là hành' mà xảy ra vì số bộ nhớ cache Python giữa -5 và 256.Python: kết quả khác nhau khi sử dụng PyCharm và IDLE/python

này đã được thảo luận ở đây: "is" operator behaves unexpectedly with integers

và ở đây: "is" and "id" in Python 3.5

Khi tôi chạy một trong những ví dụ được đưa ở đó, tôi nhận được kết quả khác nhau giữa Python Idle và Python IDE (tôi đang sử dụng chuyên nghiệp phiên bản Jetbrains Pycharm - 5.0.4).

Khi sử dụng Python IDLE đây là kết quả:

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

khi sử dụng Pycharm 5.0.4 đây là kết quả:

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

thế nào điều này có thể được? Tôi đã kiểm tra lại, và Python-Interpreter của dự án của tôi là giống hệt nhau trong cả hai trường hợp (cả hai đều là Python 3.5.1). Không chắc chắn nếu đây là điều tôi đã làm sai, và tôi đã hy vọng nếu ai đó có thể giải thích điều này.

Edit:

Tôi biết 'a' là 'b' == true iff id (a) == id (b), và bạn có thể kiểm tra xem nó như một số bạn đề cập trong các ý kiến . Có lẽ tôi nên rõ ràng hơn, những gì tôi không hiểu là làm thế nào nó có thể là một IDE có hành vi khác nhau? Tôi nghĩ (và làm ơn, sửa tôi, vì có vẻ như tôi sai) rằng IDE chỉ là một môi trường thân thiện với người sử dụng các trình biên dịch/biên dịch bên ngoài, và đây là lý do tại sao chúng độc lập với các IDE đó (ví dụ, pycharm hỗ trợ không chỉ Python, và tôi có thể chạy Eclipse với trình biên dịch C, hoặc Java vv (tất cả trong số đó là không phần của IDE)

Cảm ơn, Alon

Trả lời

4

này là vì cách LOAD_CONST mã byte hoạt động:

Đẩy co_consts[consti] vào stack.

Kể từ khi các số nguyên được lưu trữ như các hằng số sau đó nhiệm vụ cho những số nguyên tương tự trong bối cảnh tương tự sẽ mang lại kết quả chính xác cùng, chúng ta có thể thấy rằng các đối số để LOAD_CONST0 cho cả a và 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 

nơi như trong một phiên tương tác mỗi lệnh được biên soạn riêng (để họ có thể được thực thi riêng) nên hằng sẽ khác nhau:

>>> 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 

Tương tự, liên tục trong một hàm sẽ luôn luôn là giống nhau nhưng nó sẽ khác với hằng số trong các chức năng khác:

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 

Cũng lưu ý rằng như @AniMenon đã chỉ ra các số từ -5 đến 256 là độc thân để tối ưu hóa như vậy sẽ không giữ đúng cho các số trong phạm vi đó.

+0

Cảm ơn! Đó là những gì đã mất tích. – Alonbs

3

Từ các tài liệu cho is operator:..

Các toán tử isis not kiểm tra đối với nhận dạng đối tượng: x is y là true nếu và chỉ khi x và y là cùng một đối tượng.

Bây giờ cho phép kiểm tra 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 

Trong PyCharm cả abcùng đối tượng khi IDLE họ không.

Bây giờ những gì instersting trong PyCharm, rằng nếu bạn bước vào dòng mã của bạn bằng dòng, giống như trong IDLE, bạn sẽ nhận được kết quả tương tự như trong IDLE:

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

tôi đoán, rằng

>>> a = 1000 
    b = 1000 

được tối ưu hóa để:

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

vì vậy, đó là lý do tại sao bạn có cùng đối tượng cho ab

+1

Dự đoán của bạn có thể được hỗ trợ bằng cách thử nghiệm với những thứ như 'a = 1000; b = 100 + 900' hoặc các hoạt động khác dẫn đến số nguyên 1000. Bằng cách đó, không nên tối ưu hóa để tham chiếu cùng một đối tượng, tôi giả sử. –

+0

có, tôi biết về id() chức năng, nhưng điều này không phải là khá những gì tôi đã yêu cầu. xin vui lòng xem cập nhật của tôi. và cảm ơn câu trả lời bất kể. – Alonbs

+0

điều này là do tối ưu hóa nhưng không hoàn toàn những gì bạn nghĩ từ 'a = 1000; b = Không; c = 1000' cũng làm cho 'a là c' Đúng, bạn có thể muốn xem [câu trả lời của tôi] (http://stackoverflow.com/a/37104846/5827215) –

0

is sẽ trở lại True nếu hai biến trỏ đến cùng một đối tượng, == sẽ trở lại True nếu các đối tượng được gọi bằng các biến đều bình đẳng.

Trong python,

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

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

Đó là bởi vì chúng ta đang phù hợp với id (a) đến id (b).

xem xét,

a = 1000 
b = 1000 
a is b 

a is b sẽ là False; giả định của bạn về danh tính chỉ giữ trong CPython cho các số trong phạm vi -5 to 256 bao gồm, đó là singletons vì lý do hiệu suất, nhưng tất cả các int khác được tạo lại khi cần thiết, không phải đơn.

Dựa trên: reference

Các vấn đề liên quan