[MERGE] remove has_key() usage

John Arbash Meinel john at arbash-meinel.com
Tue Aug 29 22:54:41 BST 2006


Brian Harring wrote:
> On Tue, Aug 29, 2006 at 04:35:05PM -0500, John Arbash Meinel wrote:
>> Robey Pointer wrote:
>>> I've posted a branch at:
>>>
>>>     http://www.lag.net/~robey/code/bzr.dev.no_has_key/
>>>
>>> which removes the remaining usage of [dict].has_key() that I found in
>>> bzr.dev.  No new features were added, no bugs were fixed, and nothing
>>> really was accomplished except housekeeping.  It just kept me busy on
>>> the train.  :)
>>>
>>> Patch attached for review.
>>>
>>> robey
>>>
>>>
>> Is there any particular reason why 'x in foo' is better than
>> 'foo.has_key(x)'? I suppose 'in' is supported by more than just dicts
>> (sets, lists, etc).
>> Just wondering if there is some python advice that I haven't heard of.
> 
> 1) slightly faster
> $ python -m timeit -s 'd=dict([(x,None) for x in xrange(1000)]);' 'd.has_key(500)'
> 1000000 loops, best of 3: 1.48 usec per loop
> $ python -m timeit -s 'd=dict([(x,None) for x in xrange(1000)]);' '500 in d'
> 1000000 loops, best of 3: 1.02 usec per loop
> 
> Why that's faster, as far as I know it comes down to the fact the 
> interpretter does the __contains__ getattr rather then the python code 
> triggering it itself; might just be that it is less opcodes; either 
> way, consistantly faster in my experience.


Actually, I think this is exactly it. When a class is defined it must
have __len__ and __contains__ defined, they can't be added later. They
can be changed later, but at one point I was writing a wrapper class
that did:

class Foo(object):

  def __init__(self, wrap):
    self._wrap = wrap
    self.__len__ == wrap.__len__
    ...

And then if I tried to call 'len(foo)' it would tell me it was an
unsized object. I had to change it to:

  def __len__(self):
    return len(self._wrap)

So you are probably right. dict.has_key() has to look up the 'has_key'
function in the __dict__ member, in case you overwrite it. While 'foo in
dict' actually uses a compiled member, that has to exist at the time of
class definition.


> 
> 2) it relies on the general containment protocol rather then a dict 
> specific method; code can work with any sequence without having to be 
> changed if it relies on __contains__ instead of the dict specific 
> containment method.

Sure.

> 
> Most sane code just sets has_key for dicts to
> def has_key(self, key):
>   return key in self
> 
> rather then maintaining anyways. :)
> 
> ~brian
> 

:)

So overall, I think I'm happy with Robey's changes. +1 from me.

John
=:->

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 254 bytes
Desc: OpenPGP digital signature
Url : https://lists.ubuntu.com/archives/bazaar/attachments/20060829/c2d0a588/attachment.pgp 


More information about the bazaar mailing list