Yanıtlar:
Bunun gibi:
host = connectionDetails.get('host', someDefaultValue)
if/elseçok daha hızlı. Bu bir rol oynayabilir veya oynamaz.
if/elsedaha 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"
getbenzer yöntemlere uymuyor .
.get()Güzel bir deyim olsa da, daha yavaş if/else(ve try/exceptsö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
Noneanahtar / değer çiftlerindeki değerlerden biri olarak emptyString sağlanırsa veya emptyString beklenmedik sonuçlar doğurabilir . defaultsSö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 someDefaultValueanahtar eğer hostzaten 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 dictsı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/ elseyolunun 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 kanahtarlar içindeyse sözlük değerini döndürür, aksi takdirde döndürür"DEFAULT"