Jawaban:
Seperti ini:
host = connectionDetails.get('host', someDefaultValue)
if/else
jauh lebih cepat. Itu mungkin atau mungkin tidak berperan.
if/else
lebih cepat?
Anda juga dapat menggunakan defaultdict
seperti ini:
from collections import defaultdict
a = defaultdict(lambda: "default", key="some_value")
a["blabla"] => "default"
a["key"] => "some_value"
Anda dapat melewati fungsi biasa alih-alih lambda:
from collections import defaultdict
def a():
return 4
b = defaultdict(a, key="some_value")
b['absent'] => 4
b['key'] => "some_value"
get
atau metode serupa.
Meskipun .get()
ini adalah ungkapan yang bagus, ini lebih lambat daripada if/else
(dan lebih lambat daripada try/except
jika kehadiran kunci dalam kamus dapat diharapkan sebagian besar waktu):
>>> 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
akan lebih cepat. Kedua kasus memerlukan lookup kamus, dan kecuali seruan get()
ini begitu jauh lebih lambat, apa account lain untuk perlambatan?
O(1)
terlepas dari ukuran kamus, sehingga overhead panggilan fungsi relevan.
Untuk beberapa standar yang berbeda coba ini:
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
atau BlankString sebagai salah satu nilai dalam pasangan nilai kunci. The defaults
kamus berpotensi memiliki salah satu dari nilai-nilai tidak sengaja blanked keluar. (lihat juga stackoverflow.com/questions/6354436 )
Ada metode dalam kamus python untuk melakukan ini: dict.setdefault
connectionDetails.setdefault('host',someDefaultValue)
host = connectionDetails['host']
Namun metode ini menetapkan nilai connectionDetails['host']
untuk someDefaultValue
jika kunci host
belum ditentukan, tidak seperti apa pertanyaan yang diajukan.
setdefault()
nilai pengembalian, jadi ini bekerja dengan baik: host = connectionDetails.setdefault('host', someDefaultValue)
. Berhati-hatilah karena akan disetel connectionDetails['host']
ke nilai default jika kunci tidak ada di sana sebelumnya.
(ini jawaban yang terlambat)
Alternatifnya adalah dengan subkelas dict
kelas dan mengimplementasikan __missing__()
metode, seperti ini:
class ConnectionDetails(dict):
def __missing__(self, key):
if key == 'host':
return "localhost"
raise KeyError(key)
Contoh:
>>> 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'
Menguji kecurigaan @Tim Pietzcker tentang situasi di PyPy (5.2.0-alpha0) untuk Python 3.3.5, saya menemukan bahwa memang keduanya .get()
dan if
/ else
cara melakukan yang serupa. Sebenarnya sepertinya dalam kasus if / else bahkan hanya ada satu pencarian jika kondisi dan tugas melibatkan kunci yang sama (bandingkan dengan kasus terakhir di mana ada dua pencarian).
>>>> 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
Anda dapat menggunakan fungsi lamba untuk ini sebagai satu-liner. Buat objek baru connectionDetails2
yang diakses seperti fungsi ...
connectionDetails2 = lambda k: connectionDetails[k] if k in connectionDetails.keys() else "DEFAULT"
Sekarang gunakan
connectionDetails2(k)
dari pada
connectionDetails[k]
yang mengembalikan nilai kamus jika k
ada di tombol, jika tidak maka akan kembali"DEFAULT"