Yanıtlar:
Bunun gibi:
host = connectionDetails.get('host', someDefaultValue)
if/else
çok daha hızlı. Bu bir rol oynayabilir veya oynamaz.
if/else
daha hızlı olduğu konusunda bir referans verebilir misiniz?
Bunun gibi de kullanabilirsiniz defaultdict
:
from collections import defaultdict
a = defaultdict(lambda: "default", key="some_value")
a["blabla"] => "default"
a["key"] => "some_value"
Lambda yerine herhangi bir sıradan işlevi geçebilirsiniz:
from collections import defaultdict
def a():
return 4
b = defaultdict(a, key="some_value")
b['absent'] => 4
b['key'] => "some_value"
get
benzer yöntemlere uymuyor .
.get()
Güzel bir deyim olsa da, daha yavaş if/else
(ve try/except
sözlükte anahtarın bulunması beklenenden daha yavaştır ):
>>> 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
daha hızlı olacağını anlamıyorum . Her iki durum da bir sözlük aramasını gerektirir ve çağırma sürece get()
olduğunu bu yüzden çok daha yavaş, yavaşlama başka ne hesaplar?
O(1)
sözlük boyutundan bağımsızdır, dolayısıyla fonksiyon çağrısı yükü önemlidir.
Birden çok farklı varsayılan için şunu deneyin:
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
anahtar / değer çiftlerindeki değerlerden biri olarak emptyString sağlanırsa veya emptyString beklenmedik sonuçlar doğurabilir . defaults
Sözlük potansiyel onun değerlerinden biri istemeden boş bırakıldı olabilir. (ayrıca bkz. stackoverflow.com/questions/6354436 )
Python sözlüklerinde bunu yapmak için bir yöntem vardır: dict.setdefault
connectionDetails.setdefault('host',someDefaultValue)
host = connectionDetails['host']
Ancak bu yöntem değerini ayarlar connectionDetails['host']
için someDefaultValue
anahtar eğer host
zaten soru sorduk aksine tanımlı değil.
setdefault()
döndürür değeri, bu da iyi çalışır, böylece: host = connectionDetails.setdefault('host', someDefaultValue)
. connectionDetails['host']
Anahtar daha önce orada değilse varsayılan değere ayarlanacağına dikkat edin .
(bu geç bir cevaptır)
Bir alternatif, sınıfın alt dict
sınıfını oluşturmak ve __missing__()
yöntemi şu şekilde uygulamaktır :
class ConnectionDetails(dict):
def __missing__(self, key):
if key == 'host':
return "localhost"
raise KeyError(key)
Örnekler:
>>> 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'
@Tim Pietzcker'ın Python 3.3.5 için PyPy'deki (5.2.0-alpha0) durum hakkındaki şüphesini test ederek, hem hem .get()
de if
/ else
yolunun benzer performans gösterdiğini görüyorum . Aslında if / else durumunda, koşul ve atama aynı anahtarı içeriyorsa yalnızca tek bir arama bile var (iki aramanın olduğu son durumla karşılaştırın).
>>>> 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
Bunun için bir lamba fonksiyonunu tek astar olarak kullanabilirsiniz. connectionDetails2
İşlev gibi erişilen yeni bir nesne oluşturun ...
connectionDetails2 = lambda k: connectionDetails[k] if k in connectionDetails.keys() else "DEFAULT"
Şimdi kullanın
connectionDetails2(k)
onun yerine
connectionDetails[k]
eğer k
anahtarlar içindeyse sözlük değerini döndürür, aksi takdirde döndürür"DEFAULT"