Quantcast
Channel: CodeSection,代码区,Python开发技术文章_教程 - CodeSec
Viewing all articles
Browse latest Browse all 9596

Marcos Dione: the-truth-about-bool-in-Python

$
0
0
I was trying to modify ayrton so we could really have sh [1]-style file tests. In sh , they're defined as unary operators in the -X form[2], where X is a letter. For instance, -f foo returns true ( 0 in sh-peak) if foo is some kind of file. In ayrton I defined them as functions you could use, but the names sucked a little. -f was called _f() and so on. Part of the reason is, I think, that both python-sh and ayrton already do some - / _ manipulations in executable names, and part because I thought that -True didn't make any sense.

A couple of days ago I came with the idea that I could symply call the function f() and (ab)use the fact that - is a unary operator. The only detail was to make sure that - didn't change the truthiness of bool s. In fact, it doesn't, but this surprised me a little, although it shouldn't have:

In [1]: -True Out[1]: -1 In [2]: -False Out[2]: 0 In [3]: if -True: print ('yes!') yes! In [4]: if -False: print ('yes!')

You see, the bool type was introduced in Python-2.3 all the way back in 2003. Before that, the concept of true was represented by any 'true' object, and most of the time as the integer 1 ; false was mostly 0 . In Python-2.2.1, True and False were added to the builtins, but only as other names for 1 and 0 . According the that page and the PEP , bool is a subtype of int so you could still do arithmetic operations like True+1 (!!!), but I'm pretty sure deep down below the just wanted to be retro compatible.

I have to be honest, I don't like that, or the fact that applying - to bool s convert them to int s, so I decided to subclass bool and implement __neg__() in such a way that it returns the original value. And that's when I got the real surprise:

In [5]: class FalseBool (bool): ...: pass ...: TypeError: type 'bool' is not an acceptable base type

Probably you didn't know (I didn't), but Python has such a thing as a 'final class' flag . It can only be used while defining classes in a C extension. It's a strange flag, because most of the classes have to declare it just to be subclassable; it's not even part of the default flags . Even more surprising, is that there are a lot of classes that are not subclassable: around 124 in Python-3.6, and only 84 that are subclassable.

So there you go. You learn something new every day. If you're curious, here's the final implementation of FalseBool :

class FalseBool: def __init__ (self, value): if not isinstance (value, bool): raise ValueError self.value= value def __bool__ (self): return self.value def __neg__ (self): return self.value

This will go in ayrton 's next release, which I hope will be soon. I'm also working in implementing all of the different styles of expansion found in bash . I even seem to have found some bugs in it.

python ayrton

[1] I'm talking about the shell, not to confuse with python-sh . [2] Well, there are a couple of infix binary operands in the form -XY .

Viewing all articles
Browse latest Browse all 9596

Trending Articles