has_key or in

本文讨论了在Python中检查字典键存在的两种方法:使用'in'关键字和'dict.has_key()'方法,并强调了Python 3.x中推荐的做法。

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
word_index = imdb.get_word_index() reverse_word_index = {value + 3: key for key, value in word_index.items()} reverse_word_index[0] = '<PAD>' reverse_word_index[1] = '<START>' reverse_word_index[2] = '<UNK>' reverse_word_index[3] = '<UNUSED>' def decode_review(encoded_seq): """将整数序列还原为原始文本(保留大小写)""" decoded = [] for i in encoded_seq: if i >= 4: word = reverse_word_index.get(i, '<UNK>') else: word = reverse_word_index[i] decoded.append(word) return ' '.join(decoded) # 查找长且可能包含混合情感的评论 positive_words = {'good', 'great', 'excellent', 'amazing', 'love', 'fantastic', 'best', 'wonderful'} negative_words = {'bad', 'terrible', 'waste', 'awful', 'hate', 'worst', 'boring', 'disappointing'} complex_candidates = [] for i, seq in enumerate(X_test): raw_text = decode_review(seq.tolist()) # 保留原始大小写 text = raw_text.lower() words = text.split() # 筛选较长的评论 if len(words) < 200: continue mid = len(words) // 2 first_half = ' '.join(words[:mid]) second_half = ' '.join(words[mid:]) has_pos_in_first = any(p in first_half for p in positive_words) has_neg_in_second = any(n in second_half for n in negative_words) has_neg_in_first = any(n in first_half for n in negative_words) has_pos_in_second = any(p in second_half for p in positive_words) # 类型:前好后坏 或 前坏后好 if (has_pos_in_first and has_neg_in_second) or (has_neg_in_first and has_pos_in_second): complex_candidates.append((i, raw_text, seq)) # 存储原始文本 if complex_candidates: idx, raw_text, encoded = complex_candidates[0] print(f"\n 找到一条情感复杂的评论(索引 {idx}),共 {len(raw_text.split())} 个词") print("前50词:", ' '.join(raw_text.split()[:50])) print("后50词:", ' '.join(raw_text.split()[-50:])) # 预测 rnn_model.eval() lstm_model.eval() encoded_tensor = encoded.unsqueeze(0).to(device) with torch.no_grad(): rnn_pred = rnn_model(encoded_tensor).argmax().item() lstm_pred = lstm_model(encoded_tensor).argmax().item() sentiment_map = {0: "负面", 1: "正面"} print(f" RNN 预测: {sentiment_map[rnn_pred]}") print(f" LSTM 预测: {sentiment_map[lstm_pred]}") else: print("\n 未找到符合条件的情感复杂评论。")
最新发布
11-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值