Aşağıdaki iki listeye sahip olduğumuzu düşünelim.
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
Bu listelerden aşağıdaki sözlüğü üretmenin en basit yolu nedir?
a_dict = {'name': 'Monty', 'age': 42, 'food': 'spam'}
En performanslı yöntem dict
ve zip
new_dict = dict(zip(keys, values))
Python 3’te zip artık tembel bir yineleyici döndürüyor. Dolayısıyla bu artık en performanslı yaklaşım.
dict(zip(keys, values))
için bir kerelik genel arama gerektirir. Ancak gereksiz ara veri yapıları oluşturmaz veya fonksiyonlar arasında yerel aramalarla uğraşmak zorunda kalmaz.
İkincilik, dict üreteci:
new_dict = {k: v for k, v in zip(keys, values)}
Anahtara veya değere göre eşlemeniz veya filtrelemeniz gerektiğinde bunu seçebilirsiniz.
Python 2’de, zip
bir liste döndürür, bunun yerine, gereksiz bir liste oluşturmamak için izip
kullanın.
from itertools import izip as zip
Tüm durumlar için sonuç:
Her durumda:
>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}
Açıklama:
Yardıma bakarsak, çeşitli argüman biçimleri gerektirdiğini görürüz:dict
>>> help(dict)
class dict(object)
| dict() -> new empty dictionary
| dict(mapping) -> new dictionary initialized from a mapping object's
| (key, value) pairs
| dict(iterable) -> new dictionary initialized as if via:
| d = {}
| for k, v in iterable:
| d[k] = v
| dict(**kwargs) -> new dictionary initialized with the name=value pairs
| in the keyword argument list. For example: dict(one=1, two=2)
En uygun yaklaşım, gereksiz veri yapıları oluşturmaktan kaçınırken bir yineleme kullanmaktır. Python 2’de zip gereksiz bir liste oluşturur:
>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
Python 3’te eşdeğeri şu şekildedir:
>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
ve Python 3’ler yalnızca yinelenebilir bir nesne oluşturur:
>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>
Gereksiz veri yapıları oluşturmaktan kaçınmak istediğimizden, genellikle Python 2’nin zip’inden kaçınmak isteriz (gereksiz bir liste oluşturduğundan).
Daha az performans gösteren alternatifler:
dict oluşturucusunun içine geçirilen bir oluşturucu ifadesi:
generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)
veya eşdeğer olarak:
dict((k, v) for k, v in zip(keys, values))
Ve bu da dict yapıcısına geçirilen bir liste oluşturucu:
dict([(k, v) for k, v in zip(keys, values)])
İlk iki durumda, zip tekrarlanabilir üzerine fazladan bir işlem dışı (bu nedenle gereksiz) hesaplama katmanı yerleştirilir ve gereksiz yere ek bir liste oluşturulur.
Performans incelemesi:
>>> min(timeit.repeat(lambda: dict(zip(keys, values))))
0.6695233230129816
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)}))
0.6941362579818815
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
0.8782548159942962
>>>
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)])))
1.077607496001292
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values))))
1.1840861019445583
dict(zip(keys, values))
küçük anahtar ve değer kümeleriyle bile kazançlı görünüyor, ancak daha büyük kümeler için performanstaki farklar daha büyük hale gelecektir.