Comparisons and sorting of a numeric class....
andrew3 at r3dsolutions.com
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.
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:
>>> 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.
except: return op((other,))
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)
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...
More information about the Python-list