double negation, anyone? · Mär 5, 16:29 von stargaming
While discussing the introduction of a bool keyword to Python because not is a keyword, too, we (you may consider this either as ‘we, our majesty’ or ‘we, the python folks’) came up with a funny observation: our getattribute-mechanism sucks.
Well, I just fooled you. Semantically and when in use, it’s pure ownage. But it’s speed — aww! Not as if python programmers were speed zealots (“If I uglify my source code enough, it’ll be 0.001ms faster, yeeha!”), but it’s an historic semi-issue that getattr is — because of the comfortability of python’s attribute mechanism — slow. But since no one addresses it, it’s not a real issue.
I will illustrate this with the example mentioned above, the bool discrimination and how to more or less solve it: Double negation. :-)
First, watch this:
- >>> import dis
- >>> def foo():
- ... not not 5
- ...
- >>> dis.dis(foo)
- 2 0 LOAD_CONST 1 (5)
- 3 UNARY_NOT
- 4 UNARY_NOT
- 5 POP_TOP
- 6 LOAD_CONST 0 (None)
- 9 RETURN_VALUE
- >>> def foo():
- ... bool(5)
- ...
- >>> dis.dis(foo)
- 2 0 LOAD_GLOBAL 0 (bool)
- 3 LOAD_CONST 1 (5)
- 6 CALL_FUNCTION 1
- 9 POP_TOP
- 10 LOAD_CONST 0 (None)
- 13 RETURN_VALUE
You can mostly ignore the two last lines of the disassembly because it’s just to return None — pretty interesting if you think about it. So, our first result is: Both operations take exactly the same number of opcodes (6, to be precise) to compute the same thing. bool() is getattr and call, not not is twice a unary not. Let’s go ahead.
- $ python -m timeit -n 10000000 "not not 5"
- 10000000 loops, best of 3: 0.149 usec per loop
- $ python -m timeit -n 10000000 "bool(5)"
- 10000000 loops, best of 3: 0.605 usec per loop
Oww, what’s that? Double negation is around four times faster than bool(). I’m proud to introduce the new boolean idiom to you: not not object

