Comparisons and sorting of a numeric class....

Dave Angel davea at davea.name
Tue Jan 6 09:02:01 EST 2015


On 01/06/2015 08:30 AM, Andrew Robinson wrote:
>
>>> So, I'm not sure I can subclass boolean either because that too is a
>>> built in class ...  but I'm not sure how else to make an object that
>>> acts as boolean False, but can be differentiated from false by the 'is'
>>> operator.  It's frustrating -- what good is subclassing, if one cant
>>> subclass all the base classes the language has?

I said earlier that I don't think it's possible to do what you're doing 
without your users code being somewhat aware of your changes.

But as long as the user doesn't check for the subclass-ness of your 
bool-like function, you should manage.  In Python, duck-typing is 
encouraged, unlike java or C++, where the only substitutable classes are 
subclasses.

>>
>> As I said above, make sure you have a constructor.  If you still get
>> an error, post a message that shows exactly what you did, and what
>> exception you saw.
>>
>
> OK.
> I tried to subclass bool, using __new__ just to see if it would even
> accept the definition... eg: python 2.7.5
>
>  >>> class UBool( bool ):
> ...     def __new__( self, default ): return bool.__new__( self, default )
> ...
> Traceback (most recent call last):
>    File "<stdin>", line 1, in <module>
> TypeError: Error when calling the metaclass bases
>      type 'bool' is not an acceptable base type
>
> I also tried using return int.__new__( self, bool(default) ) but that
> too failed the exact same way.
>
>
> I came across this in my searches, perhaps it has something to do with
> why I can't do this?
> https://mail.python.org/pipermail/python-dev/2002-March/020822.html
>
> I thought about this last night, and realized that you shouldn't be
> allowed to subclass bool at all!  A subclass would only be useful when
> it has instances, but the mere existance of an instance of a subclass
> of bool would break the invariant that True and False are the only
> instances of bool!  (An instance of a subclass of C is also an
> instance of C.)  I think it's important not to provide a backdoor to
> create additional bool instances, so I think bool should not be
> subclassable.
>
> ...
>
> --Guido van Rossum
>
> So, I think Guido may have done something so that there are only two
> instances of bool, ever.
> eg: False and True, which aren't truly singletons -- but follow the
> singleton restrictive idea of making a single instance of an object do
> the work for everyone; eg: of False being the only instance of bool
> returning False, and True being the only instance of bool returning True.
>
> Why this is so important to Guido, I don't know ... but it's making it
> VERY difficult to add named aliases of False which will still be
> detected as False and type-checkable as a bool.  If my objects don't
> type check right -- they will likely break some people's legacy code...
> and I really don't even care to create a new instance of the bool object
> in memory which is what Guido seems worried about, rather I'm really
> only after the ability to detect the subclass wrapper name as distinct
> from bool False or bool True with the 'is' operator.  If there were a

There's already a contradiction in what you want.  You say you don't 
want to create a new bool object (distinct from True and False), but you 
have to create an instance of your class.  If it WERE a subclass of 
bool, it'd be a bool, and break singleton.

If you ignore your subclass "requirement,"  'is' should do the right 
thing.  Whatever your class instance is, it won't be the same object as 
True or as False.

> way to get the typecheck to match,

That's a piece of legacy code which you won't be able to support, as far 
as I can see.

> I wouldn't mind making a totally
> separate class which returned the False instance; eg: something like an
> example I modified from searching on the web:
>
> class UBool():
>      def __nonzero__(self): return self.default
>      def __init__( self, default=False ): self.default = bool(default)
>      def default( self, default=False ): self.defualt = bool(default)
>
> but, saying:
>  >>> error=UBool(False)
>  >>> if error is False: print "type and value match"
> ...
>  >>>
>
> Failed to have type and value match, and suggests that 'is' tests the
> type before expanding the value.

Not at all.  It doesn't check the type or the value.  It checks whether 
it's the SAME object.

> It's rather non intuitive, and will break code -- for clearly error
> expands to 'False' when evaluated without comparison functions like ==.
>
>  >>> if not error: print "yes it is false"
> ...
> yes it is false

No, the object False is not referenced in the above expression. You're 
checking the "falseness" of the expression.  Same as if you say
       if not 0
       if not mylist

>  >>> print error.__nonzero__()
> False
>  >>> if error==False: print "It compares to False properly"
> ...

You control this one by your __eq__ method.

>  >>>
>
> So, both 'is' and == seems to compare the type before attempting to
> expand the value.
> As a simple cross check, I tried to make a one valued tuple.
>
>  >>> a=(False,None)
>  >>> print a
> (False, None)
>  >>> a=(False,)
>  >>> if a is False: print "yes!!!"
> ...
>  >>>
>  >>> if not a: print "a is False"
> ...
>  >>> if a == False: print "a is False"
>
> but that obviously failed, too; and if == fails to say False==False ...
> well, it's just to sensitive for wrapper classes to be involved unless
> they are a subclass of bool...
>

1)  read up more closely on special methods, and on the meanings of id() 
and 'is'

2) And don't expect that any change you make at this level could be 
transparent to all existing applications.  It's a contradiction in terms.


-- 
DaveA



More information about the Python-list mailing list