Comparisons and sorting of a numeric class....

Ian Kelly ian.g.kelly at gmail.com
Thu Jan 15 00:26:27 EST 2015


On Wed, Jan 14, 2015 at 8:00 PM, Andrew Robinson
<andrew3 at r3dsolutions.com> wrote:
> Hi Ian,
> On 01/14/2015 12:31 AM, Ian Kelly wrote:
>
> On Tue, Jan 13, 2015 at 5:12 PM, Andrew Robinson
> <andrew3 at r3dsolutions.com> wrote:
>
> So -- even a cursory thought shows that the information could be encoded in
> a very few lines even without an instance of a subclass:
>
> class CAllFalse():
>     @classmethod
>     def __nonzero__(Kls): return False
>
> class CPartFalse():
>     @classmethod
>     def __nonzero__(Kls): return False
>
> This doesn't actually work.
>
> class CAllFalse(object):
>
> ...   @classmethod
> ...   def __nonzero__(cls): return False
> ...
>
> bool(CAllFalse)
>
> True
>
> Yes, but I never used it that way.
> If I had not put the classmethod on there, I could not have used it with a
> class name in lieu of an instance...
>
> eg:
> class Dummy():
>     def __nonzero__(self): return False
>
> bool( Dummy.__nonzero__() )
>>>> bool( Dummy.__nonzero__() )
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: unbound method __nonzero__() must be called with Dummy instance
> as first argument (got nothing instead)
>
> When Python evaluates the "truthiness" of an object, it looks up the
> __nonzero__ method on the object's class, not on the object itself
>
> Unless I call the __nonzero__ method using the underscores as I did...

So are you always going to call __nonzero__ then?  When you have an
uncertain boolean that you want to use in an if expression, are you
going to write:

    if value.__nonzero__():

every single time? Or is it possible that client code that isn't aware
of the extended bool might occasionally just use:

    if value:

and thus interpret CAllFalse as True? The entire point of the
__nonzero__ method is to specify for the Python *interpreter* whether
it should treat the object as truish or falsish. If you're not
interested in overriding that, then __nonzero__ is the wrong name for
the method. Dunder names are reserved for use by Python, and when you
use one, it signals that this method has a special meaning to the
interpreter. If the interpreter doesn't actually use that, then you're
just sending a confusing signal to readers of your code.  Call your
method nonzero() or bool() or is_true() or whatever you want, but
don't call it __nonzero__ because that's not what it is.

> Here's a clue:
>
> It may be easier to understand my example if you take something into
> account:  D'Aprano at the end of his email reply quoted to me a page from
> the Python online manuals and called it a "Promise", rather than telling me
> why Guido made a choice in denying subclassing of bool in the first
> place.... (which is what I asked about...)

It seems to me the answer to that has been given to you several times
already in this thread, but you don't seem to want to accept it for
some reason. You can't subclass bool because instances of the subclass
would be new instances of bool, which would break the class invariant.
Without instances all you're left with are static methods, at which
point there is no particular reason to host them on a subclass.

> So -- If you will now notice, I
> specifically  went out of my way to use __cmp__ and __nonzero__ methods in
> my limited example and they are both methods which have been discontinued in
> Python 3 in favor of more boolean friendly versions...

That would seem like all the less reason to use them, if you have any
interest in Python 3 compatibility.

> Given that Van Rosen

You mean Van Rossum?

> said that he denied subclassing of bool to prevent
> instances of bool, (eg: as a means to an end, not the end itself...)  I can
> see working up an example with no instances as a proposal that might make
> Guido happy and allow me to work around Guido's objections; but on the other
> hand -- I don't see putting a lot of effort into it until all other
> reasonable options have been exhausted... becase I can't subclass bool, he
> has effectively made the approach as defective as all others... ( eg: Threw
> the baby out with the bath water... though he may have had a good reason to
> do it... )

It would also be pointless, as I noted above. If the subclass only
exists to host static methods, then why is it important that they be
on a subclass?

> It's because Guido van Rosen said that there should never be another
> *instance* of a bool.   Now, I'm really agreeing with you -- that I would
> really like to subclass bool, and simply make an instance out of it -- even
> if a limited singleton type ; but Guido said No.  And Guido also objected to
> any kind of duck type, although he didn't specifically change the language
> to prevent them ... yet ...

When did Guido ever object to duck typing?

> And most of this thread has been nothing more than me asking "why" did Guido
> say to do that -- and people avoiding answering the question.

Wait, are you actually asking why bool is a doubleton? If nobody has
answered that, I think probably nobody understood you were asking it,
because it shouldn't need to be explained.

Boolean algebra has two values: true and false, or 1 and 0, or humpty
and dumpty, or whatever you like to call them.  The bool class
represents the values of boolean algebra. Therefore, there are two of
them. If I have an object that I know is an instance of bool, the
implication is that it is one of those two values, not something
potentially completely different.

Can you name any other language that *does* allow subclassing of
booleans or creation of new boolean values?

> [1] Actually, its metaclass is only type if you inherit from object,
> which you didn't do, although in Python 2.x it must be done
> explicitly. If you don't inherit from object, you get what is known as
> a "classic class" instead of a new-style class. There is no reason to
> use the old-style classes unless you really know what you are doing.
>
> It wastes less memory and invokes less overhead to use the old style
> classes.  Since I was making a class with a very narrow purpose, I saw no
> reason to go to the extra work of subclassing from object or type when I
> wasn't going to use the mechanisms from them anyway.

That sounds like premature optimization to me. Always subclassing
object when no more specific class is available would be a good habit
to get into. The savings you're talking about are not that great, it
will save you surprises when an old-style class doesn't do what you
expect, and it will produce code that is more compatible with and more
easily ported to Python 3.

> This seems fine, but I don't get why you're messing around with
> subclassing tuples. Do you really want to have boolean values that are
> iterable, indexable, etc. for no reason? Just create a normal class
> (or maybe subclass int, to match the normal bool class) and let your
> instances contain a tuple instead of being one.
>
> Sorting traditionally allows and uses rich compares when sorting complex
> data.  (cf. the email's name)  This point was examined  earlier in the
> thread by another poster, who suggested I wrap my values in a list to allow
> sort() functions to do a hierarchical compare.
>
> Although I couldn't implement the sort in the way that poster recommended
> for various technical reasons -- none the less, their suggestion led to a
> fruitful study of how and when sort algorithms do comparisons and what they
> expect from them.
>
> The tuple, then, is a natural object to contain an actual instance of bool
> (as opposed to a subclass) and work seamlessly with sorting algorithms
> already available in python.

Which doesn't answer my question at all: why inherit from tuple when
composition would suffice? A boolean is not a tuple, so a boolean
class should not subclass tuple. It sounds to me like you turn to
subclassing as a solution much more quickly than is wise.

As a final note, please only post plain text messages to this
newsgroup, not html. Not everybody can easily read html messages, and
as you can probably see from this post it can mess up things like
reply quoting.



More information about the Python-list mailing list