Comparisons and sorting of a numeric class....

Andrew Robinson andrew3 at r3dsolutions.com
Tue Jan 13 02:59:42 CET 2015


On 01/12/2015 02:35 PM, Chris Angelico wrote:
> On Tue, Jan 13, 2015 at 9:27 AM, Andrew Robinson
> <andrew3 at r3dsolutions.com> wrote:
>> 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.
Hmmm....
That may be true in python, as it is now, but that doesn't mean that 
Guido had to leave it that way when he decided to change the language to 
single out bool, and make it's subclassing rules abnormal in the first 
place.
He was changing the language when he made the decision after all !!

What I am wanting to know is WHY did Guido think it so important to do 
that ?   Why was he so focused on a strict inability to have any 
instances of a bool subclass at all -- that he made a very arbitrary 
exception to the general rule that base types in Python can be subclassed ?

There's no reason in object oriented programming principles in general 
that requires a new subclass instance to be a COMPLETELY DISTINCT 
instance from an already existing superclass instance.... nor, have I 
ever seen Guido say that Python is designed intentionally to force this 
to always be the case... so I'm not sure that's its anything more than a 
non guaranteed implementation detail that Python acts the way you say it 
does....

I don't see, within Python, an intrinsic reason (other than lack of 
support/foresight in the historical evolution of Python to date), as to 
why a subclass couldn't be instanted with the data coming from an 
*already* existing instance of it's superclass.

There is no need to copy data from an initialized superclass instance 
into a subclass instance that has no new data, but only rebind -- or add 
a binding/proxy object -- to bind the superclass instance to the 
subclass methods.

eg: what is now standard practice to create a new copy of the superclass:

class myFalse( bool ): __new__( self, data ): return super( myFalse, 
self ).__new__(self,data)

Could be replaced by a general purpose proxy meant to handle singleton 
subclassing:

class myFalse( bool ):  __new__( self ): return 
bind_superinstance_to_subclass( False, myFalse )

> he Python bool type has the following
> invariant, for any object x:
>
> assert not isinstance(x, bool) or x is True or x is False
Really !???
Where, in the language definition, did Guido explicitly guarantee this 
invariant ?

> (You can fiddle with this in Py2 by rebinding the names True and
> False, but you could replace those names with (1==1) and (1==0) if you
> want to be completely safe. Likewise, the name "bool" could be
> replaced with (1==1).__class__ to avoid any stupidities there. But
> conceptually, that's the invariant.)
Interesting ... but rebinding True and False, won't extend the new 
capabilities to modules which are imported.  They will still, I think, 
be bound to the old True and False values.   I know, for example -- I 
can redefine the class bool altogether; although the type string becomes 
'main.bool' -- none the less, it does not exist in default scope when I 
switch namespaces; eg: in a module being imported 'bool' still means the 
old version of class bool.

I have to do something more drastic, like __builtins__.bool = class 
bool(int): ...  And then, even modules will recognize the changed class 
definition.

Hmmm.....
 >>> __builtins__.True='yes'
 >>> True
'yes'

However, such actions -- I think -- are rather drastic; because they 
produce situations where another third party library in competition with 
mine might also have need of subclassing 'bool' and then we are in a 
fight for a static binding name with winner takes all ... rather than 
sharing dynamically compatible definitions based on subclasses.

> Subclassing bool breaks this invariant, unless you never instantiate
> the subclass, in which case it's completely useless.

Well we can't subclass bool now -- and the language would have to change 
in order for us to be able to subclass it; So -- I don't think your 
assert statement guarantees anything if case the language changes... On 
the other hand, I also don't see that your assert statement would ever 
return False even as it is written --- even if the object (x) was 
sub-classed or a totally different object than True or False .... and so 
I *definitely* don't see why your assert statement would Fail if the 
language changed in one of several subtle ways I think it could.

I mean, even right now -- with the language as-is -- let's define 
something that blatantly creates a new instance of something neither an 
actual instance of True nor False, and make that x -- and see if your 
assertion catches it:

Python 2.7.5 (default, May 29 2013, 02:28:51)
[GCC 4.8.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
 >>> x=(False,)
 >>> assert not isinstance(x, bool) or x is True or x is False
 >>>

LOL ... no exception was raised... and we know if the assertion Failed, 
an exception ought to be raised:

 >>> assert False
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
AssertionError
 >>>

And I'll prove my object is neither the instance True nor False itself, 
but a tupple wrap of it:

 >>> (False,)==False
False
 >>>

So -- your assertion, at least as shown, is pretty useless in helping 
determine why subclassing is not allowed, or instances of subclasses 
that are not distinct from their superclasses existing instance.






More information about the Python-list mailing list