Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #17877 > unrolled thread

Test None for an object that does not implement ==

Started byGZ <zyzhu2000@gmail.com>
First post2011-12-24 23:09 -0800
Last post2011-12-26 09:14 -0800
Articles 20 on this page of 24 — 13 participants

Back to article view | Back to comp.lang.python


Contents

  Test None for an object that does not implement == GZ <zyzhu2000@gmail.com> - 2011-12-24 23:09 -0800
    Re: Test None for an object that does not implement == Paul Rubin <no.email@nospam.invalid> - 2011-12-24 23:28 -0800
    Re: Test None for an object that does not implement == Nobody <nobody@nowhere.com> - 2011-12-25 09:38 +0000
      Re: Test None for an object that does not implement == Lie Ryan <lie.1296@gmail.com> - 2011-12-25 22:10 +1100
        Re: Test None for an object that does not implement == Roy Smith <roy@panix.com> - 2011-12-25 08:17 -0500
          Re: Test None for an object that does not implement == Chris Angelico <rosuav@gmail.com> - 2011-12-26 00:35 +1100
            Re: Test None for an object that does not implement == Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-25 13:48 +0000
              Re: Test None for an object that does not implement == Chris Angelico <rosuav@gmail.com> - 2011-12-26 01:04 +1100
              Re: Test None for an object that does not implement == Christian Heimes <lists@cheimes.de> - 2011-12-26 01:37 +0100
            Re: Test None for an object that does not implement == Roy Smith <roy@panix.com> - 2011-12-25 09:13 -0500
              Re: Test None for an object that does not implement == Chris Angelico <rosuav@gmail.com> - 2011-12-26 01:23 +1100
              Re: Test None for an object that does not implement == Lie Ryan <lie.1296@gmail.com> - 2011-12-26 04:13 +1100
      Re: Test None for an object that does not implement == Ian Kelly <ian.g.kelly@gmail.com> - 2011-12-25 19:02 -0700
      Re: Test None for an object that does not implement == Ethan Furman <ethan@stoneleaf.us> - 2011-12-25 20:26 -0800
    Re: Test None for an object that does not implement == Larry Hudson <orgnut@yahoo.com> - 2011-12-25 15:45 -0800
      Re: Test None for an object that does not implement == Devin Jeanpierre <jeanpierreda@gmail.com> - 2011-12-25 19:06 -0500
        Re: Test None for an object that does not implement == Roy Smith <roy@panix.com> - 2011-12-25 19:27 -0500
          Re: Test None for an object that does not implement == Devin Jeanpierre <jeanpierreda@gmail.com> - 2011-12-25 19:58 -0500
      Re: Test None for an object that does not implement == Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-12-26 00:52 +0000
    Re: Test None for an object that does not implement == Ethan Furman <ethan@stoneleaf.us> - 2011-12-25 20:27 -0800
    Re: Test None for an object that does not implement == Devin Jeanpierre <jeanpierreda@gmail.com> - 2011-12-26 00:22 -0500
      Re: Test None for an object that does not implement == Roy Smith <roy@panix.com> - 2011-12-26 08:43 -0500
    Re: Test None for an object that does not implement == Paul Rudin <paul.nospam@rudin.co.uk> - 2011-12-26 14:33 +0000
    Re: Test None for an object that does not implement == Ethan Furman <ethan@stoneleaf.us> - 2011-12-26 09:14 -0800

Page 1 of 2  [1] 2  Next page →


#17877 — Test None for an object that does not implement ==

FromGZ <zyzhu2000@gmail.com>
Date2011-12-24 23:09 -0800
SubjectTest None for an object that does not implement ==
Message-ID<0d80ce25-9e65-4216-b26c-b8ee40f989a3@q9g2000yqe.googlegroups.com>
Hi,

I run into a weird problem. I have a piece of code that looks like the
following:

f(...., a=None, c=None):
    assert  (a==None)==(c==None)


The problem is that == is not implemented sometimes for values in a
and c, causing an exception NotImplementedError.

I ended up doing assert (not a)==(not c), but I think this code has
other issues, for example, when a=[] and c=['a'], the assertion will
fail, although a is not None.

So how do I reliably test if a value is None or not?

Thanks,
gz

[toc] | [next] | [standalone]


#17878

FromPaul Rubin <no.email@nospam.invalid>
Date2011-12-24 23:28 -0800
Message-ID<7xaa6h6rgf.fsf@ruckus.brouhaha.com>
In reply to#17877
GZ <zyzhu2000@gmail.com> writes:
>     assert  (a==None)==(c==None)...
> So how do I reliably test if a value is None or not?

Equality is the wrong comparison to start with.  Use "a is None".

[toc] | [prev] | [next] | [standalone]


#17879

FromNobody <nobody@nowhere.com>
Date2011-12-25 09:38 +0000
Message-ID<pan.2011.12.25.09.38.07.62000@nowhere.com>
In reply to#17877
On Sat, 24 Dec 2011 23:09:50 -0800, GZ wrote:

> I run into a weird problem. I have a piece of code that looks like the
> following:
> 
> f(...., a=None, c=None):
>     assert  (a==None)==(c==None)
> 
> 
> The problem is that == is not implemented sometimes for values in a
> and c, causing an exception NotImplementedError.

I have no idea how that can happen. If a.__eq__(None) returns
NotImplemented, the interpreter should flip the test and perform the
equivalent of None.__eq__(a), which will return False.

> So how do I reliably test if a value is None or not?

As Paul says, use "is" to check whether a value _is_ None. Checking for
equality is almost certainly the wrong thing to do; nothing should compare
equal to None except for None itself, so "x is None" and "x == None"
shouldn't produce different results unless there's a bug in the comparison
method.

[toc] | [prev] | [next] | [standalone]


#17880

FromLie Ryan <lie.1296@gmail.com>
Date2011-12-25 22:10 +1100
Message-ID<mailman.4061.1324811442.27778.python-list@python.org>
In reply to#17879
On 12/25/2011 08:38 PM, Nobody wrote:

> nothing should compare equal to None except for None itself, so "x is None"
 > and "x == None" shouldn't produce different results unless there's a
 > bug in the comparison method.

not necessarily, for example:

import random
class OddClass:
     def __eq__(self, other):
         return [True, False][random.randint(0, 1)]

x = OddClass()
print x == None
print x == None
print x == None
print x == None
print x == None


Now, whether doing something like that is advisable or not, that's a 
different question; however nothing in python states that you couldn't 
have something that compare equal to None whether there is a bug or not 
in the comparison method.

[toc] | [prev] | [next] | [standalone]


#17890

FromRoy Smith <roy@panix.com>
Date2011-12-25 08:17 -0500
Message-ID<roy-5C153F.08172825122011@news.panix.com>
In reply to#17880
In article <mailman.4061.1324811442.27778.python-list@python.org>,
 Lie Ryan <lie.1296@gmail.com> wrote:

> Now, whether doing something like that is advisable or not, that's a 
> different question; however nothing in python states that you couldn't 
> have something that compare equal to None whether there is a bug or not 
> in the comparison method.

Just for fun, I tried playing around with subclassing NoneType and 
writing an __eq__ for my subclass.  Turns out, you can't do that:

Traceback (most recent call last):
  File "./none.py", line 5, in <module>
    class Nihil(NoneType):
TypeError: Error when calling the metaclass bases
    type 'NoneType' is not an acceptable base type

[toc] | [prev] | [next] | [standalone]


#17893

FromChris Angelico <rosuav@gmail.com>
Date2011-12-26 00:35 +1100
Message-ID<mailman.4066.1324820148.27778.python-list@python.org>
In reply to#17890
On Mon, Dec 26, 2011 at 12:17 AM, Roy Smith <roy@panix.com> wrote:
> Just for fun, I tried playing around with subclassing NoneType and
> writing an __eq__ for my subclass.  Turns out, you can't do that:
>
> Traceback (most recent call last):
>  File "./none.py", line 5, in <module>
>    class Nihil(NoneType):
> TypeError: Error when calling the metaclass bases
>    type 'NoneType' is not an acceptable base type

Yes; unfortunately quite a few Python built-in classes can't be
subclassed. It's an unfortunate fact of implementation, I think,
rather than a deliberate rule.

But then, what would you ever need to subclass None for, other than
toys and testing?

ChrisA

[toc] | [prev] | [next] | [standalone]


#17897

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-12-25 13:48 +0000
Message-ID<4ef729aa$0$29973$c3e8da3$5496439d@news.astraweb.com>
In reply to#17893
On Mon, 26 Dec 2011 00:35:46 +1100, Chris Angelico wrote:

[...]
>> TypeError: Error when calling the metaclass bases
>>    type 'NoneType' is not an acceptable base type
> 
> Yes; unfortunately quite a few Python built-in classes can't be
> subclassed.


I can't think of any other un-subclassable classes other than NoneType. 
Which ones are you thinking of?



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#17902

FromChris Angelico <rosuav@gmail.com>
Date2011-12-26 01:04 +1100
Message-ID<mailman.4072.1324821849.27778.python-list@python.org>
In reply to#17897
On Mon, Dec 26, 2011 at 12:48 AM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> I can't think of any other un-subclassable classes other than NoneType.
> Which ones are you thinking of?

I don't remember, but it was mentioned in a thread a little while ago.
Experimentation shows that 'bool' is one of them, though. This may
shed some light:

>>> class Foo(type(iter)):
	pass

Traceback (most recent call last):
  File "<pyshell#103>", line 1, in <module>
    class Foo(type(iter)):
TypeError: type 'builtin_function_or_method' is not an acceptable base type

I think there are certain types that are actually not implemented as
classes, and hence cannot be subclassed. This is almost certainly an
implementation detail though; my testing was done in Py3.2 (on Windows
fwiw).

ChrisA

[toc] | [prev] | [next] | [standalone]


#17933

FromChristian Heimes <lists@cheimes.de>
Date2011-12-26 01:37 +0100
Message-ID<mailman.4083.1324859838.27778.python-list@python.org>
In reply to#17897
Am 25.12.2011 15:04, schrieb Chris Angelico:
> I think there are certain types that are actually not implemented as
> classes, and hence cannot be subclassed. This is almost certainly an
> implementation detail though; my testing was done in Py3.2 (on Windows
> fwiw).

Some extension types are not subclass-able on purpose. The feature isn't
available to heap types.
http://docs.python.org/c-api/typeobj.html#Py_TPFLAGS_BASETYPE Most
people have never noticed the deliberate limitation because only a few
special types are sub-classable.

Christian

[toc] | [prev] | [next] | [standalone]


#17904

FromRoy Smith <roy@panix.com>
Date2011-12-25 09:13 -0500
Message-ID<roy-74051C.09130925122011@news.panix.com>
In reply to#17893
In article <mailman.4066.1324820148.27778.python-list@python.org>,
 Chris Angelico <rosuav@gmail.com> wrote:

> On Mon, Dec 26, 2011 at 12:17 AM, Roy Smith <roy@panix.com> wrote:
> > Just for fun, I tried playing around with subclassing NoneType and
> > writing an __eq__ for my subclass.  Turns out, you can't do that:
> >
> > Traceback (most recent call last):
> >  File "./none.py", line 5, in <module>
> >    class Nihil(NoneType):
> > TypeError: Error when calling the metaclass bases
> >    type 'NoneType' is not an acceptable base type
> 
> Yes; unfortunately quite a few Python built-in classes can't be
> subclassed. It's an unfortunate fact of implementation, I think,
> rather than a deliberate rule.
> 
> But then, what would you ever need to subclass None for, other than
> toys and testing?

You might be to differentiate between temporary and permanent failures.  
Let's say you have a WidgetPool, containing Widgets of various classes.

class WidgetPool:
   def get_widget(class_name):
      """Return a Widget of a given class.  If there are no such
      Widgets available, returns None."""
      [...]

You might want to return a None subclass to signify, "No such Widgets 
are currently available, but they might be if you try again in a little 
while", as opposed to "No such Widgets will ever be available".

If you were designing the interface from scratch, you would probably 
represent that with an exception hierarchy.  However, if this was an old 
interface that you were modifying, this might be a way to return a 
richer failure indication for new clients without breaking backwards 
compatibility for existing code.

Of course, the existing code would probably be using "is None" tests, 
and break anyway.  But at least that's a plausible scenario for None 
subclasses.

[toc] | [prev] | [next] | [standalone]


#17906

FromChris Angelico <rosuav@gmail.com>
Date2011-12-26 01:23 +1100
Message-ID<mailman.4073.1324823012.27778.python-list@python.org>
In reply to#17904
On Mon, Dec 26, 2011 at 1:13 AM, Roy Smith <roy@panix.com> wrote:
> If you were designing the interface from scratch, you would probably
> represent that with an exception hierarchy

Or possibly with "returns a False value", giving the option of None
for none available, False for none will ever be available. Of course,
you then have to guarantee that your live return values will always
boolify as True.

ChrisA

[toc] | [prev] | [next] | [standalone]


#17922

FromLie Ryan <lie.1296@gmail.com>
Date2011-12-26 04:13 +1100
Message-ID<mailman.4079.1324833250.27778.python-list@python.org>
In reply to#17904
On 12/26/2011 01:13 AM, Roy Smith wrote:
> In article<mailman.4066.1324820148.27778.python-list@python.org>,
>   Chris Angelico<rosuav@gmail.com>  wrote:
>
>> On Mon, Dec 26, 2011 at 12:17 AM, Roy Smith<roy@panix.com>  wrote:
>>> Just for fun, I tried playing around with subclassing NoneType and
>>> writing an __eq__ for my subclass.  Turns out, you can't do that:
>>>
>>> Traceback (most recent call last):
>>>   File "./none.py", line 5, in<module>
>>>     class Nihil(NoneType):
>>> TypeError: Error when calling the metaclass bases
>>>     type 'NoneType' is not an acceptable base type
>>
>> Yes; unfortunately quite a few Python built-in classes can't be
>> subclassed. It's an unfortunate fact of implementation, I think,
>> rather than a deliberate rule.
>>
>> But then, what would you ever need to subclass None for, other than
>> toys and testing?
>
> You might be to differentiate between temporary and permanent failures.
> Let's say you have a WidgetPool, containing Widgets of various classes.
>
> class WidgetPool:
>     def get_widget(class_name):
>        """Return a Widget of a given class.  If there are no such
>        Widgets available, returns None."""
>        [...]
>
> You might want to return a None subclass to signify, "No such Widgets
> are currently available, but they might be if you try again in a little
> while", as opposed to "No such Widgets will ever be available".
>
> If you were designing the interface from scratch, you would probably
> represent that with an exception hierarchy.  However, if this was an old
> interface that you were modifying, this might be a way to return a
> richer failure indication for new clients without breaking backwards
> compatibility for existing code.
>
> Of course, the existing code would probably be using "is None" tests,
> and break anyway.  But at least that's a plausible scenario for None
> subclasses.

That scenario doesn't actually need subclassing if you duck type.

[toc] | [prev] | [next] | [standalone]


#17940

FromIan Kelly <ian.g.kelly@gmail.com>
Date2011-12-25 19:02 -0700
Message-ID<mailman.4090.1324864969.27778.python-list@python.org>
In reply to#17879
On Sun, Dec 25, 2011 at 2:38 AM, Nobody <nobody@nowhere.com> wrote:
> On Sat, 24 Dec 2011 23:09:50 -0800, GZ wrote:
>
>> I run into a weird problem. I have a piece of code that looks like the
>> following:
>>
>> f(...., a=None, c=None):
>>     assert  (a==None)==(c==None)
>>
>>
>> The problem is that == is not implemented sometimes for values in a
>> and c, causing an exception NotImplementedError.
>
> I have no idea how that can happen. If a.__eq__(None) returns
> NotImplemented, the interpreter should flip the test and perform the
> equivalent of None.__eq__(a), which will return False.

Maybe the class has a misbehaved __eq__ that raises
NotImplementedError directly instead of returning NotImplemented.

[toc] | [prev] | [next] | [standalone]


#17948

FromEthan Furman <ethan@stoneleaf.us>
Date2011-12-25 20:26 -0800
Message-ID<mailman.4096.1324875078.27778.python-list@python.org>
In reply to#17879
Nobody wrote:
> nothing should compare
> equal to None except for None itself, so "x is None" and "x == None"
> shouldn't produce different results unless there's a bug in the comparison
> method.
> 

Why wouldn't you want other types that can compare equal to None?  It 
could be useful for a Null type to == None.

~Ethan~

[toc] | [prev] | [next] | [standalone]


#17930

FromLarry Hudson <orgnut@yahoo.com>
Date2011-12-25 15:45 -0800
Message-ID<rPmdnSvo4MEbKGrTnZ2dnUVZ5g-dnZ2d@giganews.com>
In reply to#17877
On 12/24/2011 11:09 PM, GZ wrote:
> Hi,
>
> I run into a weird problem. I have a piece of code that looks like the
> following:
>
> f(...., a=None, c=None):
>      assert  (a==None)==(c==None)
>
<...>

At first glance this looked like it should be a simple boolean "and", but then I realized that 
when a and c are both unequal to None, the result would also be True.  This implies the logical 
approach would be exclusive-or (^).  Try this expression:

      not ((a==None) ^ (c==None))

OTOH, if what you really want is simply to check that both are None (my first impression), then 
it's simply:

      (a==None) and (c==None)

Most of the replies you're getting here seem unnecessarily complicated.

> Thanks,
> gz

     -=- Larry -=-

[toc] | [prev] | [next] | [standalone]


#17931

FromDevin Jeanpierre <jeanpierreda@gmail.com>
Date2011-12-25 19:06 -0500
Message-ID<mailman.4082.1324858055.27778.python-list@python.org>
In reply to#17930
> At first glance this looked like it should be a simple boolean "and", but
> then I realized that when a and c are both unequal to None, the result would
> also be True.  This implies the logical approach would be exclusive-or (^).

Among booleans, "!=" is exclusive or and "==" is its negation. I don't
see the point of complicating the formula to use ^.

(related: <= is implication. Which is sad, because the arrow points
the wrong way!)

The issue here is that "== None" is being used instead of "is None",
but I believe that's been covered. Your response doesn't include it,
so maybe it's worth restating.

-- Devin

On Sun, Dec 25, 2011 at 6:45 PM, Larry Hudson <orgnut@yahoo.com> wrote:
> On 12/24/2011 11:09 PM, GZ wrote:
>>
>> Hi,
>>
>> I run into a weird problem. I have a piece of code that looks like the
>> following:
>>
>> f(...., a=None, c=None):
>>     assert  (a==None)==(c==None)
>>
> <...>
>
> At first glance this looked like it should be a simple boolean "and", but
> then I realized that when a and c are both unequal to None, the result would
> also be True.  This implies the logical approach would be exclusive-or (^).
>  Try this expression:
>
>     not ((a==None) ^ (c==None))
>
> OTOH, if what you really want is simply to check that both are None (my
> first impression), then it's simply:
>
>     (a==None) and (c==None)
>
> Most of the replies you're getting here seem unnecessarily complicated.
>
>> Thanks,
>> gz
>
>
>    -=- Larry -=-
> --
> http://mail.python.org/mailman/listinfo/python-list

[toc] | [prev] | [next] | [standalone]


#17932

FromRoy Smith <roy@panix.com>
Date2011-12-25 19:27 -0500
Message-ID<roy-4FD036.19273525122011@news.panix.com>
In reply to#17931
In article <mailman.4082.1324858055.27778.python-list@python.org>,
 Devin Jeanpierre <jeanpierreda@gmail.com> wrote:

> The issue here is that "== None" is being used instead of "is None",
> but I believe that's been covered. Your response doesn't include it,
> so maybe it's worth restating.

Which of course leads to a SillyPEP for a new keyword, "are", which 
would allow you to write:

>>> a and c are None

instead of the much more verbose

>>> a is None and c is None

[toc] | [prev] | [next] | [standalone]


#17935

FromDevin Jeanpierre <jeanpierreda@gmail.com>
Date2011-12-25 19:58 -0500
Message-ID<mailman.4085.1324861144.27778.python-list@python.org>
In reply to#17932
> Which of course leads to a SillyPEP for a new keyword, "are", which
> would allow you to write:
>
>>>> a and c are None
>
> instead of the much more verbose
>
>>>> a is None and c is None

How about:

    >>> a is b is None

;)

-- Devin

On Sun, Dec 25, 2011 at 7:27 PM, Roy Smith <roy@panix.com> wrote:
> In article <mailman.4082.1324858055.27778.python-list@python.org>,
>  Devin Jeanpierre <jeanpierreda@gmail.com> wrote:
>
>> The issue here is that "== None" is being used instead of "is None",
>> but I believe that's been covered. Your response doesn't include it,
>> so maybe it's worth restating.
>
> Which of course leads to a SillyPEP for a new keyword, "are", which
> would allow you to write:
>
>>>> a and c are None
>
> instead of the much more verbose
>
>>>> a is None and c is None
> --
> http://mail.python.org/mailman/listinfo/python-list

[toc] | [prev] | [next] | [standalone]


#17934

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-12-26 00:52 +0000
Message-ID<4ef7c540$0$29973$c3e8da3$5496439d@news.astraweb.com>
In reply to#17930
On Sun, 25 Dec 2011 15:45:10 -0800, Larry Hudson wrote:

> On 12/24/2011 11:09 PM, GZ wrote:
>> Hi,
>>
>> I run into a weird problem. I have a piece of code that looks like the
>> following:
>>
>> f(...., a=None, c=None):
>>      assert  (a==None)==(c==None)
>>
> <...>
> 
> At first glance this looked like it should be a simple boolean "and",
> but then I realized that when a and c are both unequal to None, the
> result would also be True.  This implies the logical approach would be
> exclusive-or (^).  Try this expression:
> 
>       not ((a==None) ^ (c==None))

^ is *bitwise* xor, not boolean xor. Python doesn't offer boolean xor 
directly, although != comes close.


> OTOH, if what you really want is simply to check that both are None (my
> first impression), then it's simply:
> 
>       (a==None) and (c==None)

Replace == with 'is'.

> Most of the replies you're getting here seem unnecessarily complicated.

== is a more complicated operator than the 'is' operator. That's why the 
is operator is to be preferred when testing for None -- it is guaranteed 
to do the right thing, while == is not.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#17947

FromEthan Furman <ethan@stoneleaf.us>
Date2011-12-25 20:27 -0800
Message-ID<mailman.4095.1324875073.27778.python-list@python.org>
In reply to#17877
GZ wrote:
> Hi,
> 
> I run into a weird problem. I have a piece of code that looks like the
> following:
> 
> f(...., a=None, c=None):
>     assert  (a==None)==(c==None)


Um -- if you don't want a and c being passed in, why put them in the 
function signature?

~Ethan~

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.python


csiph-web