Hmm....
LOL ... no exception was raised... and we know if the assertion Failed, an
exception ought to be raised:
The assertion did not fail. There are three parts, and as long as one
of them is true, the assertion will pass:

1) x isn't an instance of bool
2) x is the object known as True
3) x is the object known as False

You just gave an example of the first part of the invariant. That's an
instance of tuple, which is not a subclass of bool, ergo isinstance(x,
bool) returns False, negating that makes True, and the assertion
passes. [1]

Uh ... yeah... and so an assertion meant to test if something is or is not a bool let a non-bool pass the assertion. That seems rather ... silly, and useless, ... and so I really doubt the assertion -- based on it's behavior --can distinguish an actual bool from a subclassed one or a totally unrelated object ...

I mean, let's start by testing if x as an actual boolean will cause the assertion to act differently from a fake-non bool object which we already tried.

x=True
>>> x=True
>>> assert not isinstance(x, bool) or x is True or x is False
>>>
Wow. No difference in behavior.

So (as a test) it can't distinguish between an actual boolean and a faked one. They both pass the assertion. So -- What good is this assertion? It tells us nothing useful when executed.

Also what if we put in a subclass....

Instead of pretending what if -- let's actually REPLACE python's built in bool class with an emulation that ALLOWS subclassing and THEN let's TEST my hypothesis that the assert statement you gave me can't tell the difference between bools any anthing else by it's actions... ( ooooh ... another back-door that Guido forgot about... or perhaps purposely left open...)

class bool( int ):
def __new__(self,data): return super( bool, self).__new__(self, [0,1][data!=0] )
    def __repr__(self): return [ 'True', 'False' ][self>0]

__builtins__.bool=bool
__builtins__.True=bool( 1==1 )
__builtins__.False=bool( 1==0 )

And, running it in the python interpreter...

>>> class bool( int ):
... def __new__(self,data): return super( bool, self).__new__(self, [0,1][data!=0] )
...     def __repr__(self): return [ 'True', 'False' ][self>0]
...
>>> __builtins__.bool=bool
>>> __builtins__.True=bool( 1==1 )
>>> __builtins__.False=bool( 1==0 )
>>>
>>> type(True)
<class '__main__.bool'>

I now have proof that the replacement succeeded.
So let's subclass bool !!!

>>> class subBool(bool): pass
...
>>>

and now, let's see if your assertion believes a subclass of bool is a bool...
>>> x=subBool(0)
>>> assert not isinstance(x, bool) or x is True or x is False
>>>

Wow. No change.
So -- it doesn't fail when the object ISN'T a bool, it doesn't fail when the object IS a bool, and it doesn't fail when the object is a subclass of bool; and #1 matches that of a True bool! or if #1 doesn't match that of a true bool.

>>> isinstance( x, bool ) ,
True
>>> isinstance( True, bool )
True

Therefore, your explantion ( so far ) of how to interpret the invariant, is consistent with it explicitly and *precisely* 'passing' all possible instances of subclasses of bool, all instances of non-bools, and all instances of bools. Yes, the assertion you chose passes precisely ANYTHING! (facetous use of precise.).

It's a worthless assertion in the sense that it has no explicit logic to DISTINGUISH what Guido/Python does want a bool to be from what you have said and implied Guido doesn't want (even though I've never seen Guido agree with you on this assertion thing...) .
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.
It exactly defines the nature of Python's bool type: there are
precisely two instances of it.

ChrisA

[1] Which puts me in mind of https://www.youtube.com/watch?v=D0yYwBzKAyY

Uh, no, -- your assertion excludes nothing you've been telling me is not a bool by contract -- so it doesn't 'define' anything precisely because it's by definition inaccurate. it's simply an invariant form of spam with three terms you can interpret any way you like.

Where did you get that assertion from anyway and how is it related to Guido and formal definitions of the python language ??? Are you really trying to imply that Guido wrote that assertion ?

On Tue, Jan 13, 2015 at 12:59 PM, Andrew Robinson
<andr...@r3dsolutions.com>  wrote:
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 )
I don't understand. What do you expect this to be doing? Are you
trying to replace the original False with your new subclass?

No. I'm trying to make a subclass be a wrapper for an existing superclass's instance's data. It is creating something equivalent to a proxy object ; since singletons have no need of data, there is no reason to create a new instance; Therefore a fake instance will do. In C++ (Which Guido quoted in his reasoning though he was wrong about what it can do), a fake instance would generally be created by typecasting a base class instance as a subclass instance... but in python, a proxy object is generally used for the same task.

eg: when wanting to access super objects in C++, you could typecast a pointer to the subclass object as a pointer to the superclass object; but in python, typecasts don't exist so the same job is done -- via super(), by returning a proxy object.

To understand what a subclass of bool would do without an instance; Here is an example of a C-Python interpreter session after the python source code of the super() proxy type was modified to allow binding subclass methods to an existing superclass instance:

>>> x=myFalse( False )
>>> print x is False
>>> False
>>> print x==False
>>> True
>>> print isinstance( x, myFalse)
>>> True
>>> print isinstance( x, bool )
>>> True
>>> print isinstance( x, int )
>>> True
>>> print super( x, int ).__self__ # Revert the proxy object to the superclass instance,this is a kludge.
>>> False

Note: False is the actual False object being returned as __self__, because the instance False was chosen to be bound to the proxy object and I thought that __self__ degenerating to the bound instance would be a reasonable action; If I had set x=myFalse( True ), it should return the singleton 'True' instead.

>>> print x
>>> False
>>> print type(x) # This could return various things, depending on how the proxy is implemented...
>>> <super>

So, you see -- The subclass is implemented as a transparent proxy object to an instance of bool; it's NOT an instance of the subclass myFalse in reality -- but it acts 100% like an instance of myFalse would, except for '__self__' and type().

There are probably other ways to achieve this same goal, but one is enough for explanation. This is taking too much time...



--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to