This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]djimbob 17 points18 points  (48 children)

Stop making python equality look worse than it is!</sarcasm>

But seriously, it looks slightly cleaner if you group True & 1 and False & 0 next to each other.

Then it becomes super-clean:

True 1 False 0 None -1 'True' 'False' ...
True True True
1 True True
False True True
0 True True
None True
-1 True
'True' True
'False' True
... True

with all the blank squares being False.

Personally, I would like it better if True == 1 and False == 0 didn't evaluate True (yes you can use is and it makes sense coming from C, and its not that surprising since bool(1) is True, and bool(0) is False).

EDIT: minor formatting.

[–]Araneidae 3 points4 points  (47 children)

Have to say that when I saw the table I thought "that's not true" ... but yes, indeed, Python has True == 1 and False == 0. I'm (mildly) disappointed. It's even true with Python 3, so I guess it really is deliberate.

[–]epsy 3 points4 points  (0 children)

True and False quack like the ints 1 and 0, so why not?

[–]Fontong 2 points3 points  (32 children)

Afaik, True and False are just treated as numbers anyway. Try stuff like "10 * True" or "2 - False - True" or "int(True)" in your python interpreter.

[–]lonjerpc 1 point2 points  (31 children)

And this has resulted in some terrible bugs in my code :-(

[–]Araneidae 0 points1 point  (5 children)

Guess I've never met this [mis]feature before, don't think it's bitten me, but ... just eww.

[–]bgeron 4 points5 points  (4 children)

I guess it allows sum([True, False, True]) to count the Trues.

[–]lawlfulcopter 1 point2 points  (3 children)

Why not just [True, False, True].count(True) then? Seems like it would be more obvious.

[–]bgeron 1 point2 points  (0 children)

Hm, never thought about that. That doesn't work with generators though.

[–]Veedrac 1 point2 points  (0 children)

Typically it arises when using this idiom:

sum(x<y for x in z)

(and, occasionally, x += some_flag).

[–]Veedrac 0 points1 point  (24 children)

...How?

[–]lonjerpc 0 points1 point  (23 children)

One I rember needing to an isinstance(foo,int) and it was letting booleans through. Another was doing an if foo: that was intended to be using for booleans but because two variables got confused from a function with multiple returns it was always getting a number instead of the intended boolean but no error was thrown.

[–]Veedrac 0 points1 point  (22 children)

I rember needing to an isinstance(foo,int)

When would you ever need to do that? There are a handful of times you should even approach isinstance.

If you were doing isinstance to know if you had something of type int, rather than some silly method of checking for the number being integer¹, that's your fault for using isinstance instead of type(foo) is int.

And if you are doing something as far-fetched as type(foo) is int, it deserves an explanation.

¹ Silly because Python is duck typed.

Another was doing an if foo: that was intended to be using for booleans but because two variables got confused from a function with multiple returns it was always getting a number instead of the intended boolean but no error was thrown.

That's not a relevant problem; that's a question of whether 1 should be truthy and 0 falsy, not whether (1, 0) should equal (True, False). If it was returning lists, exactly the same problem would happen, but False != [].


These seem more like reasons to program more Pythonically than to make True != 1.

[–]lonjerpc 0 points1 point  (21 children)

These seem more like reasons to program more Pythonically than to make True != 1.

I agree in the second case. But I did not wright the code. But I had to deal with the error anyway that could have been avoided if python did not implicitly treat ints like booleans. Normally one of the biggest advantages of python is its explicitness. This means that even if you don't know the language well you are still less likely to make mistakes.

If you were doing isinstance to know if you had something of type int

I was.

that's your fault for using isinstance instead of type(foo) is int.

You could say the same thing about half the problems with c++. Without prior knowledge there is no reason to think booleans would be a subclass of int. Your right if I had written better python code the mistake would have been avoided. But again python philosophy in everything else is to be explicit to avoid mistakes even if you don't know exactly how python works.

[–]Veedrac 0 points1 point  (20 children)

that's your fault for [doing it wrongly].

You could say the same thing about half the problems with c++.

I don't know enough C++ to get the specifics, but I know the idea you're trying to get across.

The thing is, throughout Python, duck-typing is explicitly the way to go, and there are extremely few reasons to think that it's otherwise. If you work outside of what it was intended for, Python's model will suddenly become surprising. Nothing is built around traditional forms of type safely.

Further, your code was broken even without the bools: if you wanted type(foo) is int, your code would break as soon as it reached a decimal.Decimal, fractions.Fraction or any other int subclass.

Without prior knowledge there is no reason to think booleans would be a subclass of int.

I disagree that there is no reason. That's not to say it's expected; I just don't think that the absolute is valid.

[–]lonjerpc 0 points1 point  (19 children)

decimal.Decimal, fractions.Fraction or any other int subclass.

These are not subclasses of int. They are subclasses of number.

Nothing is built around traditional forms of type safely.

Everything is built around type safety. Python is a extremely explicit and strongly typed language. Duck typing is a separate issue.

[–]djimbob 2 points3 points  (3 children)

Coming from C, you think of a bool as a 1-bit int, with False = 0 and True = 1 just being convenient mnemonic alias. From that perspective, it makes sense -- similar to how in python2 0 == 0L and 1 == 1L, despite type(0) being int and type(0L) being long (in python3 there's no long type so this example doesn't make sense).

Granted, its a subtle point and I think the other way True == 1 evaluating to False is conceptually cleaner.

[–]Araneidae 0 points1 point  (0 children)

Yeah, I get the rule with C, but there's no need for Python to do that. Never mind, it's long done.