has_key or in

I wonder what is better to do:

d = {'a': 1, 'b': 2}
'a' in d
True

or:

d = {'a': 1, 'b': 2}
d.has_key('a')
True
share improve this question
 

11 Answers

up vote 546 down vote accepted

in is definitely more pythonic.

In fact has_key() was removed in Python 3.x.

share improve this answer
 
2 
As an addition, in Python 3, to check for the existence in values, instead of the keys, try >>> 1 in d.values() –  riza  Aug 24 '09 at 18:12
76 
One semi-gotcha to avoid though is to make sure you do: "key in some_dict" rather than "key in some_dict.keys()". Both are equivalent semantically, but performance-wise the latter is much slower (O(n) vs O(1)). I've seen people do the "in dict.keys()" thinking it's more explicit & therefore better. –  Adam Parkin  Nov 9 '11 at 20:55
1 
in works with 2.6 too right? –  Logan  Jan 17 '13 at 4:07
 
@Logan yes it does –  Wax Cage  Jul 3 '15 at 13:10
1 
@BenjaminSchollnick what's the result? –  DerekY  Dec 14 '15 at 10:01

in wins hands-down, not just in elegance (and not being deprecated;-) but also in performance, e.g.:

$ python -mtimeit -s'd=dict.fromkeys(range(99))' '12 in d'
10000000 loops, best of 3: 0.0983 usec per loop
$ python -mtimeit -s'd=dict.fromkeys(range(99))' 'd.has_key(12)'
1000000 loops, best of 3: 0.21 usec per loop

While the following observation is not always true, you'll notice that usually, in Python, the faster solution is more elegant and Pythonic; that's why -mtimeit is SO helpful -- it's not just about saving a hundred nanoseconds here and there!-)

share improve this answer
 
2 
thanks a lot, good to know, now I'm changing my code to use 'in' instead of has_key() ;) –  igorgue  Aug 24 '09 at 18:56
3 
Thanks for this, made verifying that "in some_dict" is in fact O(1) much easier (try increasing the 99 to say 1999, and you'll find the runtime is about the same). –  Adam Parkin  Nov 9 '11 at 21:00
 
has_key appears to be O(1) too. –  dan-gph  Jan 6 '15 at 4:11

According to python docs:

has_key() is deprecated in favor of key in d.

share improve this answer
 
 
thanks a lot, it really helped! –  Aaron Socurites  Aug 19 '15 at 7:17

Use dict.has_key() if (and only if) your code is required to be runnable by Python versions earlier than 2.3 (when key in dict was introduced). 

share improve this answer
 
6 
While one would hope no one is using a Python earlier than 2.3 (released in 2003), I'm quite confident there are still some holdouts. So this answer is a valuable footnote to all the "use in of course, duh" answers. –  John Y  Aug 3 '11 at 21:07
2 
@JohnY This really comes into play with the embedded linux variants. I'm currently stuck using 2.3 on two projects :( –  Adam Lewis  Feb 23 '13 at 23:37
1 
The WebSphere update in 2013 uses Jython 2.1 as its main scripting language. So this is unfortunately still a useful thing to note, five years after you noted it. –  ArtOfWarfare  Sep 24 '14 at 11:49

There is one example where in actually kills your performance.

If you use in on a O(1) container that only implements __getitem__ and has_key() but not __contains__ you will turn an O(1) search into an O(N) search (as in falls back to a linear search via __getitem__).

Fix is obviously trivial:

def __contains__(self, x):
    return self.has_key(x)
share improve this answer
 

has_key is a dictionary method, but in will work on any collection, and even when __contains__ is missing, in will use any other method to iterate the collection to find out.

share improve this answer
解释下面代码的作用“class Dataset(object): def __init__(self, mixture_reader, targets_reader_list): self.mixture_reader = mixture_reader self.keys_list = mixture_reader.wave_keys self.targets_reader_list = targets_reader_list def __len__(self): return len(self.keys_list) def _has_target(self, key): for targets_reader in self.targets_reader_list: if key not in targets_reader: return False return True def _index_by_key(self, key): """ Return a tuple like (matrix, [matrix, ...]) """ if key not in self.mixture_reader or not self._has_target(key): raise KeyError("Missing targets or mixture") target_list = [reader[key] for reader in self.targets_reader_list] return (self.mixture_reader[key], target_list) def _index_by_num(self, num): """ Return a tuple like (matrix, [matrix, ...]) """ if num >= len(self.keys_list): raise IndexError("Index out of dataset, {} vs {}".format( num, len(self.keys_list))) key = self.keys_list[num] return self._index_by_key(key) def _index_by_list(self, list_idx): """ Returns a list of tuple like [ (matrix, [matrix, ...]), (matrix, [matrix, ...]), ... ] """ if max(list_idx) >= len(self.keys_list): raise IndexError("Index list contains index out of dataset") return [self._index_by_num(index) for index in list_idx] def __getitem__(self, index): """ Implement to support multi-type index: by key, number or list """ if type(index) == int: return self._index_by_num(index) elif type(index) == str: return self._index_by_key(index) elif type(index) == list: return self._index_by_list(index) else: raise KeyError("Unsupported index type(int/str/list)")”
03-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值