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???
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to