Câu trả lời:
Như thế này:
host = connectionDetails.get('host', someDefaultValue)
if/else
nhanh hơn nhiều. Điều đó có thể hoặc không thể đóng một vai trò.
if/else
nhanh hơn?
Bạn cũng có thể sử dụng defaultdict
như vậy:
from collections import defaultdict
a = defaultdict(lambda: "default", key="some_value")
a["blabla"] => "default"
a["key"] => "some_value"
Bạn có thể vượt qua bất kỳ chức năng thông thường thay vì lambda:
from collections import defaultdict
def a():
return 4
b = defaultdict(a, key="some_value")
b['absent'] => 4
b['key'] => "some_value"
get
hoặc các phương pháp tương tự.
Mặc dù .get()
là một thành ngữ hay, nhưng nó chậm hơn if/else
(và chậm hơn try/except
nếu sự hiện diện của khóa trong từ điển có thể được mong đợi hầu hết thời gian):
>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
... stmt="try:\n a=d[1]\nexcept KeyError:\n a=10")
0.07691968797894333
>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
... stmt="try:\n a=d[2]\nexcept KeyError:\n a=10")
0.4583777282275605
>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
... stmt="a=d.get(1, 10)")
0.17784020746671558
>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
... stmt="a=d.get(2, 10)")
0.17952161730158878
>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
... stmt="if 1 in d:\n a=d[1]\nelse:\n a=10")
0.10071221458065338
>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
... stmt="if 2 in d:\n a=d[2]\nelse:\n a=10")
0.06966537335119938
if/then
sẽ nhanh hơn. Cả hai trường hợp yêu cầu tra cứu từ điển, và trừ khi gọi trình get()
là quá chậm hơn nhiều, những gì các tài khoản khác cho suy thoái?
O(1)
không phụ thuộc vào kích thước từ điển, do đó, chức năng gọi qua chức năng có liên quan.
Đối với nhiều mặc định khác nhau, hãy thử điều này:
connectionDetails = { "host": "www.example.com" }
defaults = { "host": "127.0.0.1", "port": 8080 }
completeDetails = {}
completeDetails.update(defaults)
completeDetails.update(connectionDetails)
completeDetails["host"] # ==> "www.example.com"
completeDetails["port"] # ==> 8080
None
hoặc blankString là một trong các giá trị trong các cặp khóa-giá trị. Các defaults
từ điển có thể có khả năng có một trong những giá trị của nó vô tình trống rỗng. (xem thêm stackoverflow.com/questions/6354436 )
Có một phương pháp trong từ điển python để làm điều này: dict.setdefault
connectionDetails.setdefault('host',someDefaultValue)
host = connectionDetails['host']
Tuy nhiên phương pháp này đặt giá trị của connectionDetails['host']
để someDefaultValue
nếu chủ chốt host
chưa được xác định, không giống như những gì các câu hỏi yêu cầu.
setdefault()
trả về giá trị, vì vậy điều này cũng hoạt động : host = connectionDetails.setdefault('host', someDefaultValue)
. Chỉ cần lưu ý rằng nó sẽ được đặt thành connectionDetails['host']
giá trị mặc định nếu khóa không có trước đó.
(đây là một câu trả lời muộn)
Một cách khác là phân dict
lớp lớp và thực hiện __missing__()
phương thức, như thế này:
class ConnectionDetails(dict):
def __missing__(self, key):
if key == 'host':
return "localhost"
raise KeyError(key)
Ví dụ:
>>> connection_details = ConnectionDetails(port=80)
>>> connection_details['host']
'localhost'
>>> connection_details['port']
80
>>> connection_details['password']
Traceback (most recent call last):
File "python", line 1, in <module>
File "python", line 6, in __missing__
KeyError: 'password'
Thử nghiệm sự nghi ngờ của @Tim Pietzcker về tình huống trong PyPy (5.2.0-alpha0) cho Python 3.3.5, tôi thấy rằng thực sự cả hai .get()
và if
/ else
cách thực hiện tương tự nhau. Trên thực tế, dường như trong trường hợp if / other thậm chí chỉ có một lần tra cứu nếu điều kiện và phép gán liên quan đến cùng một khóa (so sánh với trường hợp cuối cùng có hai lần tra cứu).
>>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
.... stmt="try:\n a=d[1]\nexcept KeyError:\n a=10")
0.011889292989508249
>>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
.... stmt="try:\n a=d[2]\nexcept KeyError:\n a=10")
0.07310474599944428
>>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
.... stmt="a=d.get(1, 10)")
0.010391917996457778
>>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
.... stmt="a=d.get(2, 10)")
0.009348208011942916
>>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
.... stmt="if 1 in d:\n a=d[1]\nelse:\n a=10")
0.011475925013655797
>>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
.... stmt="if 2 in d:\n a=d[2]\nelse:\n a=10")
0.009605801998986863
>>>> timeit.timeit(setup="d={1:2, 3:4, 5:6, 7:8, 9:0}",
.... stmt="if 2 in d:\n a=d[2]\nelse:\n a=d[1]")
0.017342638995614834
Bạn có thể sử dụng chức năng lamba cho việc này như là một lớp lót. Tạo một đối tượng mới connectionDetails2
được truy cập như hàm ...
connectionDetails2 = lambda k: connectionDetails[k] if k in connectionDetails.keys() else "DEFAULT"
Bây giờ sử dụng
connectionDetails2(k)
thay vì
connectionDetails[k]
trong đó trả về giá trị từ điển nếu k
có trong các khóa, nếu không nó sẽ trả về"DEFAULT"