137 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			137 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
|   | --- | |||
|  | title: Python defaultdict | |||
|  | localeTitle: Python defaultdict | |||
|  | --- | |||
|  | ## Python defaultdict
 | |||
|  | 
 | |||
|  | O dicionário é uma das estruturas de dados mais usadas no Python. Um dicionário é uma coleção desordenada de itens e geralmente temos chaves e valores armazenados em um dicionário. Vejamos alguns exemplos de como o dicionário é normalmente usado. | |||
|  | 
 | |||
|  | ```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  | |||
|  | ``` | |||
|  | 
 | |||
|  | Vamos agora olhar para algumas formas de recuperação. | |||
|  | 
 | |||
|  | ```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"]  | |||
|  | ``` | |||
|  | 
 | |||
|  | ### Evitando KeyError: Use a função .get
 | |||
|  | 
 | |||
|  | Caso a chave fornecida não exista no dicionário, o Python lançará um `KeyError` . Existe uma solução simples para isso. Vamos ver como podemos evitar o `KeyError` usando o função `.get` embutida para dicionários. | |||
|  | 
 | |||
|  | ```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_))  | |||
|  | ``` | |||
|  | 
 | |||
|  | Muitas vezes, estamos bem recebendo um valor padrão quando a chave não existe. Por exemplo, quando construindo um contador. Existe uma maneira melhor de obter valores padrão do dicionário em caso de faltando chaves em vez de depender do padrão `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  | |||
|  | ``` | |||
|  | 
 | |||
|  | Portanto, `get(<key>, <defaultval>)` é uma operação útil para recuperar o valor padrão de qualquer chave do dicionário. O problema com este método vem quando queremos lidar com estruturas de dados mutáveis como valores, por exemplo, `list` ou `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}  | |||
|  | ``` | |||
|  | 
 | |||
|  | Você viu o problema? | |||
|  | 
 | |||
|  | O novo `set` ou a `list` não são atribuídos à chave do dicionário. Devemos atribuir uma nova `list` ou um `set` para a chave em caso de falta de valor e, em seguida, `append` ou `add` respectivamente. Ley olha para um exemplo disso. | |||
|  | 
 | |||
|  | ```python | |||
|  | dict_ = {}  | |||
|  |  dict_[random_key] = dict_.get(random_key, set())  | |||
|  |  dict_[random_key].add("Hello World!")  | |||
|  |  print(dict_) # {'random': set(['Hello World!'])}. Yay!  | |||
|  | ``` | |||
|  | 
 | |||
|  | ### Evitando KeyError: Use defaultdict
 | |||
|  | 
 | |||
|  | Isso funciona na maioria das vezes. No entanto, existe uma maneira melhor de fazer isso. Uma maneira mais `pythonic` . O `defaultdict` é uma subclasse da classe dict incorporada. O `defaultdict` simplesmente atribui o valor padrão que especificamos no caso de uma chave ausente. Então, os dois passos: | |||
|  | 
 | |||
|  | ```python | |||
|  | dict_[random_key] = dict_.get(random_key, set())  | |||
|  |  dict_[random_key].add("Hello World!")  | |||
|  | ``` | |||
|  | 
 | |||
|  | agora pode ser combinado em um único passo. Por exemplo | |||
|  | 
 | |||
|  | ```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_)  | |||
|  | ``` | |||
|  | 
 | |||
|  | * * * | |||
|  | 
 | |||
|  | [Documentos oficiais](https://docs.python.org/2/library/collections.html) |