Comparisons and sorting of a numeric class....

Andrew Robinson andrew3 at
Mon Jan 12 23:27:48 CET 2015

On 01/07/2015 04:04 PM, Ethan Furman wrote:
> On 01/06/2015 07:37 PM, Andrew Robinson wrote:
>> Explain; How does mere subclassing of bool break the contract that bool has?
>> eg: What method or data would the superclass have that my subclass would not?
> bool's contract is that there are only two values (True and False) and only one instance each of those two values (True
> and False).  If bool were subclassable, new values could be added with either completely different values (PartTrue) or
> with more of the same value (True, ReallyTrue, AbsolutelyTrue) -- hence, broken contract.
> --
> ~Ethan~
Huh? I'm not adding any values when I merely subclass bool ; and even if 
the subclass could be instantiated -- that's doesn't mean a new value or 
instance of the base class (bool) must exist.  For I could happily work 
with a new subclass that contains no new data, but only an already 
_existing instance_ of 'True' or 'False_'_ as its value source.   That 
means there is no new value...  but at most (and even that could be 
worked around) a new instance of a subclass containing an existing 
instance of it's base class.

Note:  Guido only mentioned that he didn't want multiple instances of 
the base class bool -- But that's not technically the same as objecting 
to a subclass having an instance which CONTAINS an original bool 
instance and not a new one.

There are other ways Guido could have modified the Python language to 
prevent creation of new values without preventing the creation of a 
subclass --  if that's what he was really after....    So -- no -- I 
disagree with you.

Subclassing is allowed in many other OOP languages (not just C++) when 
working with singletons, and dualtons, n-tons... and the very PURPOSE of 
those objects is to prevent multiple instances, or spreading of 
control.  BUT -- Most object oriented languages I know of -- allow as 
standard practice, subclassing of n-tons -- while (often) simultaneously 
controlling or even eliminating the number of instances a subclass may 
have / and or the values it may take.  eg: depending on how flexible the 
type/class definition of a language is -- languages handle sub-classing 
of singletons differently.

Besides, a contract for a class can only be assumed to be valid for code 
designed for that specific class -- not code made for a subclass;  The 
contract for bool simply says nothing about programs designed for any 
other classes that bool is found inside of -- either as a subclass or a 
subelement;  eg:  I can still put bool inside another object with 
different methods: eg: I just write: (False,) as proof -- so Guido 
couldn't possibly have been trying to limit the methods which can 
operate on bool or the number of links to bool.

So I don't understand why Guido cared to restrict subclassing of bool -- 
and what the contract you mention has to do with it --  eg: what was his 
actual goal ?  Was it memory conservation, or compatability of built-in 
return types -- or what ?  There is no written 'contract' saying exactly 
what Guido's design objectives were in detail and more importantly 
'WHY';  but Guido only said that subclassing instances allowed a 'back 
door' (not that subclassiing itself was bad, just that it allowed some 
side effect...) to whatever Guido really didn't want to happen.

Python generally allows subclassing of singleton instances; so that 
makes 'bool' is an arbitrary exception to the general rule which Guido 
decided  to make... and he did so without any very clear explanation as 
to why.  eg: he cited what C/C++ *must *do as part of his reasoning -- 
but C/C++ can apparently do something that Guido  thought it couldn't 
(Guido was flat wrong).... and for that reason, I really wonder if 
Guido's decision was some kind of spur of the moment erroneous epiphany 
-- bolstered by the fact that he said "I realized last night..." like 
something he had never thought of before, or thought through carefully....

And worse, Guido's problem even apparently extends to making 'duck 
types' which other writers in this thread have been proposing I do. eg: 
They, too, are going against canonical Guido's epiphany night...

Of course, you can define your own subclass of int similar to the bool
class I show in the PEP, and you can give it any semantics you want --
but that_would also defeat the purpose of having a standard bool_.

Not to mention, that Charles Bool's two initial values True and False 
are NOT the only ones used in computer engineering and science; for 
boolean logic only became useful at a time when engineers and 
mathematicians realized that at least a third type, AKA: 'Don't care' -- 
was necessary for doing correctness testing of logic in a tractable 
way.   So -- Guido arbitrarily chose to make bool based on a historical 
curiosity that never has been mainstream in logic analysis.  eg: He 
based it on a beta quality revision of boolean theory....    Look at any 
logic design and testing package -- such as silos Three, or verilog, or 
VHDL, UHDL, etc.  and all of them support tri-state logic with at least 
one 'don't care' state for boolean logic.

But setting that all aside....

I've already said that I don't actually need an instance of the 
subclass... but you (and others) repeatedly ignore what I'm saying. So, 
let me try to give a crude example of alternative routes an OOP language 
like Python COULD take....

Consider -- There are generic alternatives to class instances in many 
OOP languages; eg: making proxy or wrapper objects.

These are not foreign ideas in Python; though it implements them too 
crudely for my use or else there is a trick to the Python versions I 
haven't figured out yet -- but none the less, Python already creates 
proxy objects ( CF: super() ) ; so it's not a foreign idea.

For my purposes;  At minimum I need a wrapper and proxy object (both) 
which can be passed in lieu of a an actual bool or subclass of bool; eg: 
it holds an actual False or True object (the super), and can pass the 
test whenever a user attempts an 'isinstance( mybinding, bool )' for 
type checking; but fails whenever it is examined by  'is' True or 'is' 
False;  Python can almost do what I want -- but not quite -- because the 
existing proxys are not quite as transparent as they need to be; but 
it's very close:

 >>> a=super(True,int)
 >>> isinstance( a.__self__, bool )
 >>> a is bool

So -- since it can't be done, the next best thing is some kind of 
wrapper object acting as a proxy;
As a first attempt -- I'll override the comparison operators in a 
generic way to 'make' a more generic proxy:

def _op(op,other): # Call an operation, insuring iterable is second arg.
         try: other[0]
         except: return op((other,))
         return op(other)

class ETuple(tuple):
     Enhanced Tuple.
     A tuple which does rich comparisons even when the item being
     compared against is not an iterable by converting non iterables to
     tuples of length, exactly one.
     def __new__(cls, data):return super(ETuple,cls).__new__(cls,data)
     def __eq__(self,other):return _op(super(ETuple,self).__eq__,other)
     def __ne__(self,other):return _op(super(ETuple,self).__ne__,other)
     def __lt__(self,other):return _op(super(ETuple,self).__lt__,other)
     def __le__(self,other):return _op(super(ETuple,self).__le__,other)
     def __gt__(self,other):return _op(super(ETuple,self).__gt__,other)
     def __ge__(self,other):return _op(super(ETuple,self).__ge__,other)
     def __cmp__(self,other):return _op(super(ETuple,self).__cmp__,other)
     def __nonzero__(self,other):return 

Now, I can do:
 >>> (False,) == False
 >>> (False,) is False
 >>> PartFalse = (False,)
 >>> PartFalse == False
 >>> PartFalse == PartTrue

and, it's clear that I am not creating a new instance of 'bool;' -- for 
PartFalse is not a new instance of bool, it is (under rich comparison), 
exactly equivalent to a bool.  eg: a duck type under rich comparison.
Therefore, RBool acts exactly like a bool for traditional code in a 
nearly transparent way (proxy idea) -- but still allows detection of the 
wrapper by 'is' so that newer code can take advantage of a refined 
definition of falseness...

So,  If Etuple was a subclass of 'bool', instead of just tuple -- and 
was restricted to wrap ONLY an existing bool (perhaps as an enhancement 
to the class definition...) -- it would achieve all my design goals;  so 
your objection that it is a new value would simply be false.  It would 
merely be a wrapper of an existing bool that passes the type check 
isinstance( bool, ETuple(False) ) --> True .

Why was it so important to Guido to make this impossible???
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the Python-list mailing list