Comparisons and sorting of a numeric class....
Andrew Robinson
andrew3 at r3dsolutions.com
Mon Jan 12 17:27:48 EST 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....
https://mail.python.org/pipermail/python-dev/2002-March/020822.html
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 )
True
>>> a is bool
False
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
_op(super(ETuple,self).__cmp__,other)
Now, I can do:
>>> (False,) == False
True
and:
>>> (False,) is False
False
>>> PartFalse = (False,)
>>> PartFalse == False
True
>>> PartFalse == PartTrue
False
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: <http://mail.python.org/pipermail/python-list/attachments/20150112/741e1ed7/attachment.html>
More information about the Python-list
mailing list