Câu trả lời:
in
chắc chắn là nhiều pythonic.
Trong thực tế has_key()
đã được gỡ bỏ bằng Python 3.x .
keys()
chỉ là một chế độ xem giống như tập hợp vào từ điển chứ không phải là bản sao, x in d.keys()
O (1) cũng vậy. Tuy nhiên, x in d
là nhiều Pythonic.
x in d.keys()
phải xây dựng và phá hủy một đối tượng tạm thời, hoàn thành việc cấp phát bộ nhớ, trong đó x in d.keys()
chỉ là thực hiện một phép toán số học (tính toán hàm băm) và thực hiện tra cứu. Lưu ý rằng d.keys()
chỉ dài khoảng 10 lần, điều này vẫn không thực sự dài. Tôi chưa kiểm tra nhưng tôi vẫn khá chắc chắn đó chỉ là O (1).
in
chiến thắng thực sự, không chỉ ở sự thanh lịch (và không bị phản đối ;-) mà còn về hiệu suất, ví dụ:
$ 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
Mặc dù quan sát sau đây không phải lúc nào cũng đúng, nhưng bạn sẽ nhận thấy rằng thông thường , trong Python, giải pháp nhanh hơn là thanh lịch và Pythonic hơn; đó là lý do tại sao -mtimeit
SO hữu ích - nó không chỉ là tiết kiệm một trăm nano giây ở đây và đó! -)
has_key
dường như là O (1).
Theo tài liệu python :
has_key()
được phản đối ủng hộkey in d
.
has_key()
hiện đã bị xóa trong Python 3
Sử dụng dict.has_key()
if (và chỉ khi) mã của bạn được yêu cầu để có thể chạy được bởi các phiên bản Python sớm hơn 2.3 (khi key in dict
được giới thiệu).
Có một ví dụ in
thực sự giết chết hiệu suất của bạn.
Nếu bạn sử dụng in
trên một thùng chứa O (1) chỉ thực hiện __getitem__
và has_key()
không thực hiện , __contains__
bạn sẽ biến tìm kiếm O (1) thành tìm kiếm O (N) (khi in
quay lại tìm kiếm tuyến tính thông qua __getitem__
).
Sửa lỗi rõ ràng là tầm thường:
def __contains__(self, x):
return self.has_key(x)
has_key()
là đặc trưng cho từ điển Python 2 . in
/ __contains__
là API chính xác để sử dụng; đối với những vùng chứa không thể tránh được việc quét toàn bộ thì không có has_key()
phương pháp nào và nếu có cách tiếp cận O (1) thì đó sẽ là trường hợp sử dụng cụ thể và tùy thuộc vào nhà phát triển để chọn loại dữ liệu phù hợp cho vấn đề.
has_key
là một phương thức từ điển, nhưng in
sẽ hoạt động trên bất kỳ bộ sưu tập nào và ngay cả khi __contains__
bị thiếu, in
sẽ sử dụng bất kỳ phương pháp nào khác để lặp lại bộ sưu tập để tìm hiểu.
in
các thử nghiệm trên range
các đối tượng. xrange
Mặc dù vậy, tôi không chắc về hiệu quả của nó trên Python 2 . ;)
__contains__
có thể tính toán tầm thường nếu một giá trị nằm trong phạm vi hay không.
range
thể hiện mới mỗi lần. Sử dụng một ví dụ duy nhất có sẵn , bài kiểm tra "số nguyên trong phạm vi" nhanh hơn khoảng 40% trong thời gian của tôi.
Giải pháp cho dict.has_key () không được dùng nữa, sử dụng 'in' - trình soạn thảo văn bản cao siêu 3
Ở đây tôi đã lấy một ví dụ về từ điển có tên là 'lứa tuổi' -
ages = {}
# Add a couple of names to the dictionary
ages['Sue'] = 23
ages['Peter'] = 19
ages['Andrew'] = 78
ages['Karren'] = 45
# use of 'in' in if condition instead of function_name.has_key(key-name).
if 'Sue' in ages:
print "Sue is in the dictionary. She is", ages['Sue'], "years old"
else:
print "Sue is not in the dictionary"
Mở rộng bài kiểm tra hiệu suất của Alex Martelli với nhận xét của Adam Parkin ...
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' 'd.has_key(12)'
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 301, in main
x = t.timeit(number)
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/timeit.py", line 178, in timeit
timing = self.inner(it, self.timer)
File "<timeit-src>", line 6, in inner
d.has_key(12)
AttributeError: 'dict' object has no attribute 'has_key'
$ python2.7 -mtimeit -s'd=dict.fromkeys(range( 99))' 'd.has_key(12)'
10000000 loops, best of 3: 0.0872 usec per loop
$ python2.7 -mtimeit -s'd=dict.fromkeys(range(1999))' 'd.has_key(12)'
10000000 loops, best of 3: 0.0858 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' '12 in d'
10000000 loops, best of 3: 0.031 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d'
10000000 loops, best of 3: 0.033 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range( 99))' '12 in d.keys()'
10000000 loops, best of 3: 0.115 usec per loop
$ python3.5 -mtimeit -s'd=dict.fromkeys(range(1999))' '12 in d.keys()'
10000000 loops, best of 3: 0.117 usec per loop
Nếu bạn có một cái gì đó như thế này:
t.has_key(ew)
thay đổi nó thành bên dưới để chạy trên Python 3.X trở lên:
key = ew
if key not in t
t.has_key(ew)
trả về True
nếu ew
tham chiếu giá trị cũng là một khóa trong từ điển. key not in t
trả về True
nếu giá trị không có trong từ điển. Hơn nữa, key = ew
bí danh là rất, rất dư thừa. Viết đúng chính tả là if ew in t
. Đó là những gì câu trả lời được chấp nhận từ 8 năm trước đã nói với bạn.