Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > is None or == None ?

Reply
Thread Tools

is None or == None ?

 
 
Raymond Hettinger
Guest
Posts: n/a
 
      11-06-2009
On Nov 6, 5:20*am, mk <(E-Mail Removed)> wrote:
> Some claim that one should test for None using:
>
> if x is None:
>
> ..but the standard equality which is theoretically safer works as well:
>
> if x == None:
>
> So, which one is recommended?


In the standard library, we use "x is None".

The official recommendation in PEP 8 reads:
'''
Comparisons to singletons like None should always be done with
'is' or 'is not', never the equality operators.

Also, beware of writing "if x" when you really mean "if x is not
None"
-- e.g. when testing whether a variable or argument that
defaults to
None was set to some other value. The other value might have a
type
(such as a container) that could be false in a boolean context!
'''


Raymond
 
Reply With Quote
 
 
 
 
Hrvoje Niksic
Guest
Posts: n/a
 
      11-06-2009
"Alf P. Steinbach" <(E-Mail Removed)> writes:

> But wow. That's pretty hare-brained: dynamic allocation for every
> stored value outside the cache range, needless extra indirection for
> every operation.
>
> Even Microsoft COM managed to get this right.
>
> On the positive side, except that it would probably break every C
> module (I don't know), in consultant speak that's definitely a
> potential for improvement. :-p


Tagged integers have been tried, shown not really worth it, and
ultimately rejected by the BDFL:

http://mail.python.org/pipermail/pyt...ead.html#46139
 
Reply With Quote
 
 
 
 
Alf P. Steinbach
Guest
Posts: n/a
 
      11-06-2009
* Rami Chowdhury:
> On Fri, 06 Nov 2009 08:54:53 -0800, Alf P. Steinbach <(E-Mail Removed)>
> wrote:
>
>> But wow. That's pretty hare-brained: dynamic allocation for every
>> stored value outside the cache range, needless extra indirection for
>> every operation.
>>

>
> Perhaps I'm not understanding this thread at all but how is dynamic
> allocation hare-brained, and what's the 'needless extra indirection'?


Dynamic allocation isn't hare-brained, but doing it for every stored integer
value outside a very small range is, because dynamic allocation is (relatively
speaking, in the context of integer operations) very costly even with a
(relatively speaking, in the context of general dynamic allocation) very
efficient small-objects allocator - here talking order(s) of magnitude.

A typical scheme for representing dynamically typed objects goes like, in C++,

enum TypeId { int_type_id, dyn_object_type_id };

struct Object
{
int type_id;
union
{
void* p;
int i;
// Perhaps other special cased type's values in this union.
};
};

This would then be the memory layout of what's regarded as a variable at the
script language level.

Then getting the integer value reduces to

int intValueOf( Object const& o )
{
if( o.type_id != int_type_id ) { throw TypeError(); }
return o.i;
}

If on the other hand int (and perhaps floating point type, whatever) isn't
special-cased, then it goes like

int intValueOf( Object const& o )
{
if( o.type_id != int_type_id ) { throw TypeError(); }
return static_cast<IntType*>( o.p )->value; // Extra indirection
}

and depending on where the basic type id is stored it may be more extra
indirection, and worse, creating that value then involves a dynamic allocation.


Cheers & hth.

- Alf
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      11-06-2009
* Hrvoje Niksic:
> "Alf P. Steinbach" <(E-Mail Removed)> writes:
>
>> But wow. That's pretty hare-brained: dynamic allocation for every
>> stored value outside the cache range, needless extra indirection for
>> every operation.
>>
>> Even Microsoft COM managed to get this right.
>>
>> On the positive side, except that it would probably break every C
>> module (I don't know), in consultant speak that's definitely a
>> potential for improvement. :-p

>
> Tagged integers have been tried, shown not really worth it, and
> ultimately rejected by the BDFL:
>
> http://mail.python.org/pipermail/pyt...ead.html#46139


Yah, as I suspected. I looked at the first few postings in that thread and it
seems an inefficient baroque implementation was created and tested, not
realizing more than 50% speedup in a test not particularly much exercising its
savings, and against that counts as mentioned in the thread and as I mentioned
in quoted material above, breaking lots of existing C code.

Speedup would likely be more realistic with normal implementation (not fiddling
with bit-fields and stuff) not to mention when removing other inefficiencies
that likely dwarf and hide the low-level performance increase, but still I agree
wholeheartedly with those who argue compatibility, not breaking code.

As long as it Works, don't fix it...


Cheers, (still amazed, though)

- Alf
 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      11-06-2009
On Nov 6, 9:28*am, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
> * Rami Chowdhury:
>
> > On Fri, 06 Nov 2009 08:54:53 -0800, Alf P. Steinbach <(E-Mail Removed)>
> > wrote:

>
> >> But wow. That's pretty hare-brained: dynamic allocation for every
> >> stored value outside the cache range, needless extra indirection for
> >> every operation.

>
> > Perhaps I'm not understanding this thread at all but how is dynamic
> > allocation hare-brained, and what's the 'needless extra indirection'?

>
> Dynamic allocation isn't hare-brained, but doing it for every stored integer
> value outside a very small range is, because dynamic allocation is (relatively
> speaking, in the context of integer operations) very costly even with a
> (relatively speaking, in the context of general dynamic allocation) very
> efficient small-objects allocator - here talking order(s) of magnitude.



Python made a design trade-off, it chose a simpler implementation and
uniform object semantic behavior, at a cost of speed. C# made a
different trade-off, choosing a more complex implementation, a
language with two starkly different object semantic behaviors, so as
to allow better performance.

You don't have to like the decision Python made, but I don't think
it's fair to call a deliberate design trade-off hare-brained.


Carl Banks
 
Reply With Quote
 
Rami Chowdhury
Guest
Posts: n/a
 
      11-06-2009
On Fri, 06 Nov 2009 09:28:08 -0800, Alf P. Steinbach <(E-Mail Removed)>
wrote:

> * Rami Chowdhury:
>> On Fri, 06 Nov 2009 08:54:53 -0800, Alf P. Steinbach <(E-Mail Removed)>
>> wrote:
>>
>>> But wow. That's pretty hare-brained: dynamic allocation for every
>>> stored value outside the cache range, needless extra indirection for
>>> every operation.
>>>

>> Perhaps I'm not understanding this thread at all but how is dynamic
>> allocation hare-brained, and what's the 'needless extra indirection'?

>
> Dynamic allocation isn't hare-brained, but doing it for every stored
> integer value outside a very small range is, because dynamic allocation
> is (relatively speaking, in the context of integer operations) very
> costly even with a (relatively speaking, in the context of general
> dynamic allocation) very efficient small-objects allocator - here
> talking order(s) of magnitude.


Well, sure, it may seem that way. But how large a cache would you want to
preallocate? I can't see the average Python program needing to use the
integers from -10000 to 10000, for instance. In my (admittedly limited)
experience Python programs typically deal with rather more complex objects
than plain integers.

> int intValueOf( Object const& o )
> {
> if( o.type_id != int_type_id ) { throw TypeError(); }
> return static_cast<IntType*>( o.p )->value; // Extra
> indirection
> }


If a large cache were created and maintained, would it not be equally
indirect to check for the presence of a value in the cache, and return
that value if it's present?

> creating that value then involves a dynamic allocation.


Creating which value, sorry -- the type object?


--
Rami Chowdhury
"Never attribute to malice that which can be attributed to stupidity" --
Hanlon's Razor
408-597-7068 (US) / 07875-841-046 (UK) / 0189-245544 (BD)
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      11-06-2009
* Carl Banks:
> On Nov 6, 9:28 am, "Alf P. Steinbach" <(E-Mail Removed)> wrote:
>> * Rami Chowdhury:
>>
>>> On Fri, 06 Nov 2009 08:54:53 -0800, Alf P. Steinbach <(E-Mail Removed)>
>>> wrote:
>>>> But wow. That's pretty hare-brained: dynamic allocation for every
>>>> stored value outside the cache range, needless extra indirection for
>>>> every operation.
>>> Perhaps I'm not understanding this thread at all but how is dynamic
>>> allocation hare-brained, and what's the 'needless extra indirection'?

>> Dynamic allocation isn't hare-brained, but doing it for every stored integer
>> value outside a very small range is, because dynamic allocation is (relatively
>> speaking, in the context of integer operations) very costly even with a
>> (relatively speaking, in the context of general dynamic allocation) very
>> efficient small-objects allocator - here talking order(s) of magnitude.

>
>
> Python made a design trade-off, it chose a simpler implementation


Note that the object implementation's complexity doesn't have to affect to any
other code since it's trivial to provide abstract accessors (even macros), i.e.,
this isn't part of a trade-off except if the original developer(s) had limited
resources -- and if so then it wasn't a trade-off at the language design level
but a trade-off of getting things done then and there.


> and uniform object semantic behavior,


Also note that the script language level semantics of objects is /unaffected/ by
the implementation, except for speed, i.e., this isn't part of a trade-off
either.


> at a cost of speed.


In summary, the trade-off, if any, couldn't as I see it be what you describe,
but there could have been a different kind of getting-it-done trade-off.

It is usually better with Something Usable than waiting forever (or too long)
for the Perfect...

Or, it could be that things just evolved, constrained by frozen earlier
decisions. That's the main reason for the many quirks in C++. Not unlikely that
it's also that way for Python.


> C# made a
> different trade-off, choosing a more complex implementation, a
> language with two starkly different object semantic behaviors, so as
> to allow better performance.


Don't know about the implementation of C#, but whatever it is, if it's bad in
some respect then that has nothing to do with Python.


> You don't have to like the decision Python made, but I don't think
> it's fair to call a deliberate design trade-off hare-brained.


OK.


Cheers,

- Alf
 
Reply With Quote
 
Mel
Guest
Posts: n/a
 
      11-06-2009
Alf P. Steinbach wrote:
> Note that the object implementation's complexity doesn't have to affect to
> any other code since it's trivial to provide abstract accessors (even
> macros), i.e., this isn't part of a trade-off except if the original
> developer(s) had limited
> resources -- and if so then it wasn't a trade-off at the language design
> level but a trade-off of getting things done then and there.


But remember what got us in here: your belief (which followed from your
assumptions) that computing `is` required testing the object types. You
might optimize out the "extra indirection" to get an object's value, but
you'd need the "extra indirection" anyway to find out what type it was
before you could use it.

Mel.


 
Reply With Quote
 
Rami Chowdhury
Guest
Posts: n/a
 
      11-06-2009
On Fri, 06 Nov 2009 11:50:33 -0800, Alf P. Steinbach <(E-Mail Removed)>
wrote:

> * Rami Chowdhury:
>> On Fri, 06 Nov 2009 09:28:08 -0800, Alf P. Steinbach <(E-Mail Removed)>
>> wrote:
>>
>>> * Rami Chowdhury:
>>>> On Fri, 06 Nov 2009 08:54:53 -0800, Alf P. Steinbach <(E-Mail Removed)>
>>>> wrote:
>>>>
>>>>> But wow. That's pretty hare-brained: dynamic allocation for every
>>>>> stored value outside the cache range, needless extra indirection for
>>>>> every operation.
>>>>>
>>>> Perhaps I'm not understanding this thread at all but how is dynamic
>>>> allocation hare-brained, and what's the 'needless extra indirection'?
>>>
>>> Dynamic allocation isn't hare-brained, but doing it for every stored
>>> integer value outside a very small range is, because dynamic
>>> allocation is (relatively speaking, in the context of integer
>>> operations) very costly even with a (relatively speaking, in the
>>> context of general dynamic allocation) very efficient small-objects
>>> allocator - here talking order(s) of magnitude.

>> Well, sure, it may seem that way. But how large a cache would you want
>> to preallocate? I can't see the average Python program needing to use
>> the integers from -10000 to 10000, for instance. In my (admittedly
>> limited) experience Python programs typically deal with rather more
>> complex objects than plain integers.

>
> Uhm, you've misunderstood or failed to understand something basic, but
> what?


Oh, I see, you were referring to a tagging scheme as an alternative. Sorry
for the misunderstanding.

>
> Well it's an out-of-context quote, but t'was about creating the value
> object that a variable contains a pointer to with the current CPython
> implementation.
>


Again, perhaps I'm just misunderstanding what you're saying, but as I
understand it, in CPython if you're looking for the value of a
PyIntObject, that's stored right there in the structure, so no value
object needs to be created...



--
Rami Chowdhury
"Never attribute to malice that which can be attributed to stupidity" --
Hanlon's Razor
408-597-7068 (US) / 07875-841-046 (UK) / 0189-245544 (BD)
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      11-06-2009
* Mel:
> Alf P. Steinbach wrote:
>> Note that the object implementation's complexity doesn't have to affect to
>> any other code since it's trivial to provide abstract accessors (even
>> macros), i.e., this isn't part of a trade-off except if the original
>> developer(s) had limited
>> resources -- and if so then it wasn't a trade-off at the language design
>> level but a trade-off of getting things done then and there.

>
> But remember what got us in here: your belief (which followed from your
> assumptions) that computing `is` required testing the object types.


Yes, I couldn't believe what I've now been hearing. Uh, reading.


> You
> might optimize out the "extra indirection" to get an object's value, but
> you'd need the "extra indirection" anyway to find out what type it was
> before you could use it.


No, that type checking is limited (it just checks whether the type is special
cased), doesn't involve indirection, and is there anyway except for 'is'. It can
be moved around but it's there, or something more costly is there. 'is' is about
the only operation you /can/ do without checking the type, but I don't see the
point in optimizing 'is' at cost of all other operations on basic types.


Cheers & hth.,

- Alf
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
DataGrid - BorderStyle="None" and BorderWidth="None" doesn't work for Firefox David Freeman ASP .Net 8 02-16-2011 11:03 AM
Re: <var> is None vs. <var> == None Steve Holden Python 9 01-26-2009 09:10 PM
<var> is None vs. <var> == None Gerald Britton Python 7 01-24-2009 09:02 AM
testing for valid reference: obj vs. None!=obs vs. obj is not None alf Python 9 12-09-2006 05:00 AM
Is there a built-in method for transforming (1,None,"Hello!") to 1,None,"Hello!"? Daniel Crespo Python 5 11-13-2005 12:52 PM



Advertisments