2012-11-30 35 views
55

Toán tử is không khớp với giá trị của các biến, nhưng bản thân các trường hợp .Tìm hiểu toán tử "is" của Python

Điều đó thực sự có ý nghĩa gì?

Tôi đã khai báo hai biến có tên là xy gán cùng giá trị trong cả hai biến, nhưng nó trả về false khi tôi sử dụng toán tử is.

Tôi cần làm rõ. Đây là mã của tôi.

x = [1, 2, 3] 
y = [1, 2, 3] 

print x is y #It prints false! 
+0

Câu hỏi liên quan http://stackoverflow.com/questions/38189660/two-variables-in-python-have-same-id-but-not-lists-or-tuples-why/38189759#38189759 – Kasramvd

Trả lời

102

Bạn hiểu sai về kiểm tra của nhà điều hành is. Nó kiểm tra xem hai biến có trỏ cùng một đối tượng không, nếu hai biến có cùng giá trị.

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

Các nhà khai thác isis not thử nghiệm cho nhận dạng đối tượng: x is y là đúng nếu và chỉ nếu xy là cùng một đối tượng.

Sử dụng các nhà điều hành == thay vì:

print x == y 

này in True. xy hai riêng danh sách:

x[0] = 4 
print y # prints [1, 2, 3] 
print x == y # prints False 

Nếu bạn sử dụng id() function bạn sẽ thấy rằng xy có định danh khác nhau:

>>> id(x) 
4401064560 
>>> id(y) 
4401098192 

nhưng nếu bạn đã gán y-x sau đó cả hai trỏ đến cùng một đối tượng:

>>> x = y 
>>> id(x) 
4401064560 
>>> id(y) 
4401064560 
>>> x is y 
True 

is cho thấy cả hai đều là cùng một đối tượng, nó trả về True.

+2

Vì vậy, ' A là B' giống với 'id (A) == id (B)'. – imallett

+1

@imallett: đó là một proxy cho cùng một thử nghiệm, miễn là bạn không lưu trữ 'id (A)' trong một biến và sau đó mong đợi 'biến == id (B)' vẫn hoạt động; nếu 'A' bị xóa trong khi chờ đợi thì' B' có thể đã được đặt cùng một vị trí bộ nhớ. –

+0

Làm cho tinh thần, và nó cũng là điều đúng; 'biến' đang lưu trữ một thuộc tính của một cái gì đó mà trước đây tồn tại. Không có cách nào cho thời gian chạy để phát hiện rằng việc sử dụng sau này là sai. Phần chính của tiêu chuẩn là "[id()] được đảm bảo là duy nhất và không đổi đối với đối tượng này _trong cả đời của nó. Hai đối tượng có thời gian tồn tại không chồng chéo có thể có cùng giá trị id()." – imallett

2

X chỉ vào một mảng, Y trỏ đến một mảng khác. Những mảng giống hệt nhau, nhưng toán tử is sẽ xem xét các con trỏ đó, không giống nhau.

+4

Python không có con trỏ. Bạn cần phải thắt chặt thuật ngữ của bạn. –

+2

Nó thực hiện nội bộ, giống như Java và rất nhiều ngôn ngữ khác. Thực tế, chức năng của toán tử 'is' hiển thị điều này. – Neko

+4

Chi tiết triển khai không phải là vấn đề quan trọng. Tài liệu sử dụng thuật ngữ "nhận diện đối tượng". Vậy bạn nên. "Các toán tử là và không phải là kiểm tra đối với nhận dạng đối tượng: x là y là true nếu và chỉ khi x và y là cùng một đối tượng. X không phải là y mang lại giá trị true true." –

1

Nó so sánh danh tính đối tượng, nghĩa là, liệu các biến có liên quan đến cùng một đối tượng trong bộ nhớ hay không. Nó giống như == trong Java hoặc C (khi so sánh con trỏ).

2

Vì bạn có thể kiểm tra ở đây thành một số nguyên nhỏ. Các số trên 257 không phải là một ints nhỏ, do đó, nó được tính như một đối tượng khác nhau.

Tốt hơn nên sử dụng == thay thế trong trường hợp này.

Thông tin thêm là ở đây: http://docs.python.org/2/c-api/int.html

6

is chỉ trả về true nếu họ thực sự đang ở cùng một đối tượng. Nếu chúng giống nhau, một sự thay đổi thành một cũng sẽ xuất hiện ở cái kia. Đây là một ví dụ về sự khác biệt.

>>> x = [1, 2, 3] 
>>> y = [1, 2, 3] 
>>> print x is y 
False 
>>> z = y 
>>> print y is z 
True 
>>> print x is z 
False 
>>> y[0] = 5 
>>> print z 
[5, 2, 3] 
6

Xuất phát từ một duplicate question, tương tự này có thể làm việc:

# - Darling, I want some pudding! 
# - There is some in the fridge. 

pudding_to_eat = fridge_pudding 
pudding_to_eat is fridge_pudding 
# => True 

# - Honey, what's with all the dirty dishes? 
# - I wanted to eat pudding so I made some. Sorry about the mess, Darling. 
# - But there was already some in the fridge. 

pudding_to_eat = make_pudding(ingredients) 
pudding_to_eat is fridge_pudding 
# => False 
+2

Có thể chỉ là sở thích cá nhân (không có ý định chơi chữ) nhưng tôi thấy sự tương tự khó hiểu hơn là hữu ích và khiến tôi muốn ăn bánh pudding khi tôi không có trong tủ lạnh của mình :( Tôi nghĩ câu trả lời của Mark Ransom nhàm chán, có lẽ là nhiều hơn hướng dẫn –

+1

@TomClose: Có rất nhiều câu trả lời tốt về câu hỏi này, đủ để có không gian cho levity.Ngoài ra, tôi muốn pudding quá – Amadan

23

Another duplicate đã hỏi tại sao hai chuỗi bằng nói chung là không giống nhau, đó là không thực sự trả lời ở đây:

>>> x = 'a' 
>>> x += 'bc' 
>>> y = 'abc' 
>>> x == y 
True 
>>> x is y 
False 

Vì vậy, tại sao chúng không phải là cùng một chuỗi? Đặc biệt trong bối này:

>>> z = 'abc' 
>>> w = 'abc' 
>>> z is w 
True 

Hãy trì hoãn phần thứ hai cho một chút. Làm sao người đầu tiên có thể đúng?

Trình thông dịch sẽ phải có "bảng interning", bảng ánh xạ chuỗi giá trị đối tượng chuỗi, vì vậy mỗi khi bạn cố gắng tạo chuỗi mới với nội dung 'abc', bạn sẽ lấy lại cùng một đối tượng. Wikipedia có một cuộc thảo luận chi tiết hơn về cách thức hoạt động của interning.

Và Python bảng chuỗi ký tự; bạn có thể thực hiện chuỗi theo cách thủ công bằng phương pháp sys.intern.

Thực tế, Python được cho phép tự động thực hiện bất kỳ loại bất biến nào, nhưng không phải yêu cầu để làm như vậy. Các triển khai khác nhau sẽ tập trung các giá trị khác nhau.

CPython (triển khai bạn đang sử dụng nếu bạn không biết bạn đang sử dụng triển khai nào) tự động thực tập số nguyên nhỏ và một số đơn đặc biệt như False, chứ không phải chuỗi (hoặc số nguyên lớn hoặc tuple nhỏ hoặc còn gì nữa không). Bạn có thể thấy điều này khá dễ dàng:

>>> a = 0 
>>> a += 1 
>>> b = 1 
>>> a is b 
True 
>>> a = False 
>>> a = not a 
>>> b = True 
a is b 
True 
>>> a = 1000 
>>> a += 1 
>>> b = 1001 
>>> a is b 
False 

OK, nhưng tại sao là zw giống hệt nhau?

Đó không phải là trình thông dịch tự động thực hiện, đó là giá trị gấp của trình biên dịch.

Nếu cùng một chuỗi thời gian biên dịch xuất hiện hai lần trong cùng một module (những gì chính xác điều này có nghĩa là khó có thể xác định-nó không phải là điều tương tự như một chuỗi chữ, vì r'abc', 'abc', và 'a' 'b' 'c' là literals tất cả khác nhau nhưng cùng một chuỗi - nhưng dễ hiểu trực giác), trình biên dịch sẽ chỉ tạo một thể hiện của chuỗi, với hai tham chiếu.

Trong thực tế, trình biên dịch có thể đi xa hơn nữa: 'ab' + 'c' có thể được chuyển đổi sang 'abc' bởi tôi ưu hoa, trong trường hợp nó có thể được gấp lại với nhau với một 'abc' liên tục trong các mô-đun tương tự.

Một lần nữa, đây là điều mà Python được phép nhưng không bắt buộc phải làm. Nhưng trong trường hợp này, CPython luôn gấp các chuỗi nhỏ (và cũng có thể, ví dụ, các bộ dữ liệu nhỏ). (Mặc dù tuyên bố theo tuyên bố biên dịch các thông dịch viên tương tác của không chạy tối ưu hóa tương tự như trình biên dịch module-at-a-thời gian, vì vậy bạn sẽ không nhìn thấy chính xác những kết quả tương tự tương tác.)


Vì vậy, , bạn nên làm gì với tư cách là một lập trình viên?

Chà ... không có gì. Bạn hầu như không bao giờ có bất kỳ lý do gì để quan tâm nếu hai giá trị bất biến là giống hệt nhau. Nếu bạn muốn biết khi nào bạn có thể sử dụng a is b thay vì a == b, bạn đang đặt câu hỏi sai. Chỉ cần luôn luôn sử dụng a == b trừ hai trường hợp:

  • Để so sánh dễ đọc hơn với các giá trị singleton như x is None.
  • Đối với các giá trị có thể thay đổi, khi bạn cần biết liệu có đột biến x hay không sẽ ảnh hưởng đến y.
3

isis not là hai toán tử nhận dạng bằng Python. Toán tử is không so sánh giá trị của các biến, nhưng so sánh danh tính của các biến. Xem xét việc này:

>>> a = [1,2,3] 
>>> b = [1,2,3] 
>>> hex(id(a)) 
'0x1079b1440' 
>>> hex(id(b)) 
'0x107960878' 
>>> a is b 
False 
>>> a == b 
True 
>>> 

Ví dụ trên cho bạn thấy rằng bản sắc (cũng có thể là địa chỉ bộ nhớ trong CPython) là khác nhau cho cả ab (mặc dù giá trị của họ đều giống nhau). Đó là lý do tại sao khi bạn nói a is b nó trả về false do sự không khớp trong danh tính của cả hai toán hạng. Tuy nhiên, khi bạn nói a == b, nó trả về true vì thao tác == chỉ xác minh nếu cả hai toán hạng có cùng giá trị được gán cho chúng.

Thú vị dụ (đối với cấp thêm):

>>> del a 
>>> del b 
>>> a = 132 
>>> b = 132 
>>> hex(id(a)) 
'0x7faa2b609738' 
>>> hex(id(b)) 
'0x7faa2b609738' 
>>> a is b 
True 
>>> a == b 
True 
>>> 

Trong ví dụ trên, mặc dù ab là hai biến khác nhau, a is b trở True. Điều này là do loại aint là một đối tượng bất biến. Vì vậy, python (tôi đoán để tiết kiệm bộ nhớ) phân bổ cùng một đối tượng để b khi nó được tạo ra với cùng một giá trị. Vì vậy, trong trường hợp này, danh tính của các biến phù hợp và a is b hóa ra là True.

này sẽ áp dụng cho tất cả các đối tượng bất biến:

>>> del a 
>>> del b 
>>> a = "asd" 
>>> b = "asd" 
>>> hex(id(a)) 
'0x1079b05a8' 
>>> hex(id(b)) 
'0x1079b05a8' 
>>> a is b 
True 
>>> a == b 
True 
>>> 

Hy vọng rằng sẽ giúp.

+0

đây là ví dụ thực sự tốt đẹp.thông tin chi tiết.Thông tin chi tiết – Haranadh

+0

Nhưng hãy thử a = 123456789 b = 123456789 – user2183078

3

x is y giống với id(x) == id(y), so sánh danh tính của đối tượng.

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