137 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | ||
| title: Python defaultdict
 | ||
| localeTitle: Python defaultdict
 | ||
| ---
 | ||
| ## Python defaultdict
 | ||
| 
 | ||
| Словарь - одна из наиболее используемых структур данных в Python. Словарь представляет собой неупорядоченный набор элементов, и мы обычно имеем ключи и значения, хранящиеся в словаре. Давайте рассмотрим несколько примеров того, как обычно используется словарь.
 | ||
| 
 | ||
| ```python
 | ||
| # dictionary declaration 1 
 | ||
|  dict1 = dict() 
 | ||
|  
 | ||
|  # dictionary declaration 2 
 | ||
|  dict2 = {} 
 | ||
|  
 | ||
|  # Add items to the dictionary 
 | ||
|  # The syntax to add and retrieve items is same for either of the two objects we defined above. 
 | ||
|  key = "X" 
 | ||
|  value = "Y" 
 | ||
|  dict1[key] = value 
 | ||
|  
 | ||
|  # The dictionary doesn't have any specific data-type. 
 | ||
|  # So, the values can be pretty diverse. 
 | ||
|  dict1[key] = dict2 
 | ||
| ```
 | ||
| 
 | ||
| Давайте посмотрим на некоторые способы поиска.
 | ||
| 
 | ||
| ```python
 | ||
| # Since "X" exists in our dictionary, this will retrieve the value 
 | ||
|  value = dict1[key] 
 | ||
|  
 | ||
|  # This key doesn't exist in the dictionary. 
 | ||
|  # So, we will get a `KeyError` 
 | ||
|  value = dict1["random"] 
 | ||
| ```
 | ||
| 
 | ||
| ### Избегайте KeyError: используйте функцию .get
 | ||
| 
 | ||
| В случае, если данный ключ не существует в словаре, Python будет бросать `KeyError` . Для этого есть простой способ обхода. Давайте посмотрим, как мы можем избежать `KeyError` используя встроенная функция `.get` для словарей.
 | ||
| 
 | ||
| ```python
 | ||
| dict_ = {} 
 | ||
|  
 | ||
|  # Some random key 
 | ||
|  random_key = "random" 
 | ||
|  
 | ||
|  # The most basic way of doing this is to check if the key 
 | ||
|  # exists in the dictionary or not and only retrieve if the 
 | ||
|  # key exists. Otherwise not. 
 | ||
|  if random_key in dict_: 
 | ||
|   print(dict_[random_key]) 
 | ||
|  else: 
 | ||
|   print("Key = {} doesn't exist in the dictionary".format(dict_)) 
 | ||
| ```
 | ||
| 
 | ||
| Много раз мы нормально получаем значение по умолчанию, когда ключ не существует. Например, когда построение счетчика. Существует лучший способ получить значения по умолчанию из словаря в случае отсутствующие ключи, а не полагаться на стандартное `if-else` .
 | ||
| 
 | ||
| ```python
 | ||
| # Let's say we want to build a frequency counter for items in the following array 
 | ||
|  arr = [1,2,3,1,2,3,4,1,2,1,4,1,2,3,1] 
 | ||
|  
 | ||
|  freq = {} 
 | ||
|  
 | ||
|  for item in arr: 
 | ||
|   # Fetch a value of 0 in case the key doesn't exist. Otherwise, fetch the stored value 
 | ||
|   freq[item] = freq.get(item, 0) + 1 
 | ||
| ```
 | ||
| 
 | ||
| Таким образом, `get(<key>, <defaultval>)` - это удобная операция для получения значения по умолчанию для любого заданного ключа из словаря. Проблема с этим методом возникает, когда мы хотим иметь дело с изменяемыми структурами данных как значения, например, `list` или `set` .
 | ||
| 
 | ||
| ```python
 | ||
| dict_ = {} 
 | ||
|  
 | ||
|  # Some random key 
 | ||
|  random_key = "random" 
 | ||
|  
 | ||
|  dict_[random_key] = dict_.get(random_key, []).append("Hello World!") 
 | ||
|  print(dict_) # {'random': None} 
 | ||
|  
 | ||
|  dict_ = {} 
 | ||
|  dict_[random_key] = dict_.get(random_key, set()).add("Hello World!") 
 | ||
|  print(dict_) # {'random': None} 
 | ||
| ```
 | ||
| 
 | ||
| Вы видели проблему?
 | ||
| 
 | ||
| Новый `set` или `list` не привязаны к ключу словаря. Мы должны назначить новый `list` или `set` к ключу в случае отсутствия значения, а затем `append` или `add` соответственно. Лей смотрит на пример для этого.
 | ||
| 
 | ||
| ```python
 | ||
| dict_ = {} 
 | ||
|  dict_[random_key] = dict_.get(random_key, set()) 
 | ||
|  dict_[random_key].add("Hello World!") 
 | ||
|  print(dict_) # {'random': set(['Hello World!'])}. Yay! 
 | ||
| ```
 | ||
| 
 | ||
| ### Избегайте KeyError: используйте defaultdict
 | ||
| 
 | ||
| Это работает большую часть времени. Однако есть лучший способ сделать это. Более `pythonic` путь. `defaultdict` является подклассом встроенного класса dict. `defaultdict` просто присваивает значение по умолчанию, которое мы укажем в случае отсутствия ключа. Итак, два шага:
 | ||
| 
 | ||
| ```python
 | ||
| dict_[random_key] = dict_.get(random_key, set()) 
 | ||
|  dict_[random_key].add("Hello World!") 
 | ||
| ```
 | ||
| 
 | ||
| теперь можно объединить в один шаг. Например, для
 | ||
| 
 | ||
| ```python
 | ||
| from collections import defaultdict 
 | ||
|  
 | ||
|  # Yet another random key 
 | ||
|  random_key = "random_key" 
 | ||
|  
 | ||
|  # list defaultdict 
 | ||
|  list_dict_ = defaultdict(list) 
 | ||
|  
 | ||
|  # set defaultdict 
 | ||
|  set_dict_ = defaultdict(set) 
 | ||
|  
 | ||
|  # integer defaultdict 
 | ||
|  int_dict_ = defaultdict(int) 
 | ||
|  
 | ||
|  list_dict_[random_key].append("Hello World!") 
 | ||
|  set_dict_[random_key].add("Hello World!") 
 | ||
|  int_dict_[random_key] += 1 
 | ||
|  
 | ||
|  """ 
 | ||
|   defaultdict(<class 'list'>, {'random_key': ['Hello World!']}) 
 | ||
|   defaultdict(<class 'set'>, {'random_key': {'Hello World!'}}) 
 | ||
|   defaultdict(<class 'int'>, {'random_key': 1}) 
 | ||
|  """ 
 | ||
|  print(list_dict_, set_dict_, int_dict_) 
 | ||
| ```
 | ||
| 
 | ||
| * * *
 | ||
| 
 | ||
| [Официальные документы](https://docs.python.org/2/library/collections.html) |