Là Sai == 0 và Đúng == 1 là chi tiết triển khai hay được đảm bảo bởi ngôn ngữ?


244

Có đảm bảo rằng False == 0True == 1, trong Python (giả sử rằng chúng không được người dùng gán lại)? Chẳng hạn, liệu có đảm bảo rằng đoạn mã sau sẽ luôn tạo ra kết quả giống nhau, bất kể phiên bản Python nào (cả hiện tại và có khả năng là tương lai) không?

0 == False  # True
1 == True   # True
['zero', 'one'][False]  # is 'zero'

Bất kỳ tài liệu tham khảo đến các tài liệu chính thức sẽ được nhiều đánh giá cao!

Chỉnh sửa : Như đã lưu ý trong nhiều câu trả lời, boolkế thừa từ int. Do đó, câu hỏi có thể được gọi lại là: "Tài liệu có chính thức nói rằng các lập trình viên có thể dựa vào booleans kế thừa từ các số nguyên, với các giá trị 01 không?". Câu hỏi này có liên quan để viết mã mạnh mẽ sẽ không thất bại vì chi tiết triển khai!


63
@ S.Lott: Có nhiều lý do để đặt câu hỏi ở trên. Vì vậy, có những trường hợp dựa vào booleans là số nguyên làm cho mã của bạn đơn giản hơn: bạn có phải thay đổi nó không? Hoặc, bạn có thể phát hiện các vị trí trong mã được viết bởi người khác dựa trên booleans là số nguyên: bạn có làm gián đoạn những gì bạn đang sửa đổi trong mã để "sửa" mã hiện tại không, hoặc bạn có thể yên tâm rằng mã hiện tại là âm thanh ? Có rất nhiều ví dụ khác. Tổng quát hơn, thật tốt khi biết các quy tắc của trò chơi, để bạn có thể chơi tốt và lập trình một cách hợp lý.
Eric O Lebigot

10
@ S.Lott: Bài đăng gốc phản ánh chính xác quan điểm của bạn: câu hỏi về cơ bản là "Đây có phải là chi tiết triển khai không?", Vì tôi hoàn toàn đồng ý với bạn về ý tưởng rằng người ta không nên phụ thuộc vào chi tiết thực hiện. Nếu booleans là số nguyên chính thức của các giá trị đã biết, thì mã trong câu hỏi không dựa vào chi tiết triển khai, điều này là tốt.
Eric O Lebigot

5
@S. Rất nhiều: Biết rằng Sai == 0 và Đúng == 1 giúp dễ dàng hơn để đếm có bao nhiêu bool trong chuỗi là đúng: Bạn chỉ có thể viết sum(bool_list). Nếu không, bạn sẽ phải viết sum(1 for x bool_list if x).
dan04

8
@dan: Đó là một cách đếm booleans. Tôi sẽ nói rằng bool_list.count(True)rõ ràng hơn; nó cũng nhanh hơn khoảng 3 lần so với :) :)
Eric O Lebigot

2
@akonsu Như câu trả lời hiển thị, Python boolean thực sự (một lớp con cụ thể của) các số nguyên. Hơn nữa, Python rõ ràng các loại; có lẽ bạn có nghĩa là nó "không được gõ tĩnh"? Ngoài ra, tôi không chắc ý của bạn là "Tôi sẽ không mắc lỗi trong mã". Bây giờ, tôi không bao giờ thích trộn booleans với số nguyên, vì chúng khác nhau về mặt khái niệm và tôi sẽ không phiền nếu booleans Python không phải là số nguyên, nhưng biết rằng chúng, với các giá trị 0 và 1, là hữu ích.
Eric O Lebigot

Câu trả lời:


183

Trong Python 2.x, điều này không được đảm bảo vì có thể TrueFalseđược chỉ định lại. Tuy nhiên, ngay cả khi điều này xảy ra, boolean True và boolean false vẫn được trả về đúng cách để so sánh.

Trong Python 3.x TrueFalselà các từ khóa và sẽ luôn bằng 10.

Trong các trường hợp thông thường trong Python 2 và luôn trong Python 3:

FalseĐối tượng thuộc loại boollà một lớp con của int:

object
   |
 int
   |
 bool

Đó là lý do duy nhất tại sao trong ví dụ của bạn, ['zero', 'one'][False]không hoạt động. Nó sẽ không hoạt động với một đối tượng không phải là một lớp con của số nguyên, bởi vì lập chỉ mục danh sách chỉ hoạt động với các số nguyên hoặc các đối tượng xác định một __index__phương thức (cảm ơn mark-Dickinson ).

Biên tập:

Nó đúng với phiên bản python hiện tại và của Python 3. Các tài liệu cho python 2.6 và các tài liệu cho Python 3 đều nói:

Có hai loại số nguyên: [...] Số nguyên (int) [...] Booleans (bool)

và trong tiểu mục boolean:

Booleans: Chúng đại diện cho các giá trị thật Sai và Đúng [...] Các giá trị Boolean tương ứng với các giá trị 0 và 1, trong hầu hết tất cả các bối cảnh, ngoại lệ là khi được chuyển đổi thành một chuỗi, các chuỗi "Sai" hoặc "Đúng "Được trả lại, tương ứng.

Ngoài ra, đối với Python 2 :

Trong ngữ cảnh số (ví dụ: khi được sử dụng làm đối số cho toán tử số học), chúng [Sai và Đúng] hoạt động giống như các số nguyên 0 và 1, tương ứng.

Vì vậy, booleans được coi rõ ràng là số nguyên trong Python 2.6 và 3.

Vì vậy, bạn an toàn cho đến khi Python 4 xuất hiện. ;-)


2
0 == 0,0 trả về Đúng trong khi ['zero', 'one'] [0.0] không thành công. ['zero', 'one'] [Sai] hoạt động vì bool là lớp con của int. (int .__ lớp con __ () trả về [<type 'bool'>])
luc

20
Nitpick: bất kỳ đối tượng nào cung cấp một __index__phương thức đều có thể được sử dụng làm chỉ mục danh sách; không chỉ các lớp con của inthoặc long.
Đánh dấu Dickinson

À đúng rồi, nó cũng ở đó. Nhưng sẽ tốt hơn nếu không liên kết đến tài liệu Python 3.0: 3.0 đã chết. :)
Đánh dấu Dickinson

4
Re: "Trong Python 2.x, điều này không được đảm bảo vì có thể được gán lại đúng và sai". IMHO, trong khi điều này là đúng, bất kỳ ai gán lại Đúng hay Sai đều xứng đáng nhận bất kỳ hậu quả kỳ lạ nào họ nhận được. Cụ thể, lưu trữ True trước khi gán lại và sau đó so sánh kết quả với True sau khi gán lại sẽ bị hỏng. a = True; True = 'i am an idiot'; a == True=> Sai. Khác với việc gán lại như vậy, các giá trị mặc định được tiêu chuẩn hóa thành 0 và 1, và tôi tin rằng việc phụ thuộc vào điều đó là thông lệ; ví dụ: lập chỉ mục vào một mảng hai phần tử, trong đó [0] giữ trường hợp sai, [1] đúng.
ToolmakerSteve

Tôi vừa nhận thấy một xác nhận chính thức khác về thực tế là True có thể được coi là 1 và Sai 0: docs.python.org/2/l Library / stdtypes.html#boolean-value . Tôi đang thêm điều này vào câu trả lời này.
Eric O Lebigot

77

Liên kết với PEP thảo luận về loại bool mới trong Python 2.3: http://www.python.org/dev/peps/pep-0285/ .

Khi chuyển đổi một bool thành một int, giá trị nguyên luôn là 0 hoặc 1, nhưng khi chuyển đổi một int thành một bool, giá trị boolean là True cho tất cả các số nguyên trừ 0.

>>> int(False)
0
>>> int(True)
1
>>> bool(5)
True
>>> bool(-5)
True
>>> bool(0)
False

22

Trong Python 2.x, nó hoàn toàn không được đảm bảo:

>>> False = 5
>>> 0 == False
False

Vì vậy, nó có thể thay đổi. Trong Python 3.x, True, false và none là các từ dành riêng , vì vậy đoạn mã trên sẽ không hoạt động.

Nói chung, với booleans, bạn nên giả sử rằng trong khi Sai sẽ luôn có giá trị nguyên là 0 (miễn là bạn không thay đổi nó, như trên), True có thể có bất kỳ giá trị nào khác. Tôi không nhất thiết phải dựa vào bất kỳ sự đảm bảo nào True==1, nhưng trên Python 3.x, điều này sẽ luôn luôn như vậy, bất kể là gì.


3
Re "True có thể có bất kỳ giá trị nào khác. Tôi không nhất thiết phải dựa vào bất kỳ sự đảm bảo nào rằng True == 1". Trên thực tế, bạn CÓ THỂ dựa vào True == 1, theo python.org/dev/peps/pep-0285 và spec docs.python.org/2/reference/iêu "Các giá trị Boolean tương ứng như các giá trị 0 và 1 , trong hầu hết tất cả các bối cảnh ... "Tôi không nói rằng không thể ghi đè điều này trong Py 2 bằng cách gán lại Đúng hoặc Sai, nhưng tôi nói rằng trừ khi một số lập trình viên trong dự án của bạn là một kẻ ngốc và thực hiện việc tái chỉ định như vậy, hành vi được đảm bảo.
ToolmakerSteve

-2

Rất đơn giản. Vì bool liên quan đến việc đánh giá một số nguyên dưới dạng bool, CHỈ zero cho câu trả lời sai. TẤT CẢ các giá trị khác không, số float, số nguyên, bao gồm cả số âm hoặc những gì có bạn, sẽ trả về giá trị true.

Một ví dụ hay về lý do tại sao điều này hữu ích là xác định trạng thái nguồn của thiết bị. Bật là bất kỳ giá trị khác không, tắt là không. Nói điện tử điều này có ý nghĩa.

Để xác định đúng hoặc sai tương đối giữa các giá trị, bạn phải có một cái gì đó để so sánh nó với. Này áp dụng cho chuỗi giá trị và số lượng, sử dụng ==hay !=hay <, > >=, <=vv

Bạn có thể gán một số nguyên cho một biến và sau đó nhận đúng hoặc sai dựa trên giá trị biến đó.


1
Câu hỏi là về việc True == 1 có được đảm bảo bởi Python không chứ không phải về giá trị boolean của các số nguyên.
Eric O Lebigot

-3

Chỉ cần viết int(False)và bạn sẽ nhận được 0, nếu bạn gõ int(True)nó sẽ xuất1


4
Điều này chỉ có nghĩa là Sai và Đúng là các đầu vào hợp lệ int(), với ý nghĩa số đơn giản, không phải là chúng giống hệt 0 và 1.
Eric O Lebigot

-5

Sai là một bool. Nó có một loại khác nhau. Nó là một đối tượng khác từ 0 là một số nguyên.

0 == Falsetrả về True vì false được chuyển thành một số nguyên. int (Sai) trả về 0

Tài liệu python của toán tử == nói (help ('==')):

Các nhà khai thác <, >, ==, >=, <=, và !=so sánh giá trị của hai đối tượng. Các đối tượng không cần phải có cùng loại. Nếu cả hai đều là số, chúng được chuyển đổi thành một loại phổ biến.

Kết quả là Sai được chuyển đổi thành một số nguyên cho nhu cầu so sánh. Nhưng nó khác 0.

>>> 0 is False
False

26
Điều này không hoàn toàn đúng: boollà một lớp con của int, vì vậy theo nghĩa rất thực, bool một số nguyên. Ví dụ, isinstance(True, int)trả về True. Và kiểm tra đẳng thức không chuyển đổi bool thành int, vì không cần chuyển đổi: nó chỉ đơn giản gọi int.__cmp__trực tiếp. Lưu ý rằng bool.__cmp__ is int.__cmp__cũng đánh giá True.
Đánh dấu Dickinson

3
-1 cho câu trả lời này. Mô tả không chính xác về mối quan hệ giữa bool và int (trong Python 2). isinstance(True, int)=> Đúng. Đó là, True IS là một số nguyên và không yêu cầu chuyển đổi.
ToolmakerSteve

Tôi đã có một tập lệnh trả về Sai hoặc một ... sử dụng while response is Falseđã hoạt động và while response == Falsekhông .. Cảm ơn!
xoăn_brackets

5
Đó 0 is Falselà sai cho bạn không có gì. Trong trình thông dịch tương tác của bạn, nhập x = -10, sau đó y = -10, x is yvà đó cũng sẽ là sai. Chỉ vì có các tối ưu hóa tại nơi trình thông dịch Python sử dụng lại cùng một đối tượng số nguyên trong một số trường hợp nhất định (lưu trữ số nguyên dưới dạng hằng, thực hiện các số nguyên nhỏ) không có nghĩa là isnên được sử dụng khi bạn muốn kiểm tra tính bằng giá trị nguyên .
Martijn Pieters
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.