Publicamos recentemente uma
tradução do material, que fornecia dicas úteis para programadores de Python. Esse material tem uma sequência que chamamos a sua atenção hoje.

Nomeação de fatia usando a função de fatia
Trabalhar com os muitos valores especificados por índices pode rapidamente se transformar em confusão - tanto em termos de suporte quanto em legibilidade do código. Uma maneira de melhorar a situação é usar constantes para os valores especificados pelos índices. Mas há uma maneira melhor de escrever código de qualidade:
Neste exemplo, você pode ver que, dando nomes às fatias usando a função
slice
e usando esses nomes para obter os fragmentos da sequência, conseguimos nos livrar dos índices complexos. Você pode aprender mais sobre o objeto de
slice
usando seus
.start
,
.stop
e
.step
.
Solicitando uma senha do usuário durante a execução do programa
Muitas ferramentas ou scripts de linha de comando exigem um nome de usuário e senha para funcionar. Se você precisar escrever um programa assim, poderá achar
getpass
módulo
getpass
:
import getpass user = getpass.getuser() password = getpass.getpass()
Este pacote muito simples permite que você solicite a senha de um usuário e obtenha um nome de usuário recuperando o nome com o qual ele está conectado. No entanto, ao trabalhar com senhas, você deve estar ciente de que nem todos os sistemas oferecem suporte à ocultação de senhas. O Python tentará notificá-lo. Se isso acontecer, você verá um aviso correspondente na linha de comando.
Localizando correspondências próximas em strings
Agora vamos falar sobre um recurso um pouco mais misterioso da biblioteca padrão do Python. Suponha que você esteja em uma situação em que precisava, usando um conceito como
a distância de Levenshtein , para encontrar palavras na lista que se pareçam com uma determinada linha de entrada. Este problema pode ser resolvido usando o módulo
difflib
.
import difflib difflib.get_close_matches('appel', ['ape', 'apple', 'peach', 'puppy'], n=2)
O método
difflib.get_close_matches
as melhores correspondências "boas o suficiente". O primeiro argumento deste método especifica a cadeia de pesquisa, o segundo argumento especifica a lista na qual a pesquisa é realizada. Este método pode receber um argumento opcional
n
, que especifica o número máximo de correspondências retornadas. Esse método também suporta o
cutoff
opcional de argumento nomeado (por padrão, é definido como
0.6
), que permite definir um valor limite para avaliar correspondências.
Trabalhar com endereços IP
Se você precisar escrever programas Python para trabalhar com a rede, isso significa que o módulo
ipaddress
pode ser muito útil para você. Uma opção para usá-lo é gerar uma lista de endereços IP a partir de um intervalo de endereços especificado no formato CIDR (roteamento entre domínios sem classe, endereçamento sem classe).
import ipaddress net = ipaddress.ip_network('74.125.227.0/29')
Outro recurso útil deste módulo é verificar o endereço IP por pertencer a uma determinada rede:
ip = ipaddress.ip_address("74.125.227.3") ip in net
O módulo
ipaddress
possui muitos outros recursos interessantes dos quais não estou falando aqui. Leia mais sobre ele
aqui . É verdade que, usando este módulo, considere as limitações relacionadas ao seu trabalho conjunto com outros módulos relacionados à programação de rede. Por exemplo, você não pode usar instâncias
IPv4Network
como cadeias de endereços. Objetos semelhantes para isso devem primeiro ser convertidos em strings usando
str
.
Depurando um programa na linha de comando
Se você é um daqueles que não deseja usar o IDE e escreve código no Vim ou no Emacs, pode estar em uma situação em que precisaria de um depurador como o do IDE. E você sabe o que? Você já possui um depurador. Para usá-lo, basta executar o programa usando uma estrutura como
python3.8 -i
. O sinalizador
-i
permite, após a conclusão do programa, iniciar um shell interativo. Usando-o, você pode examinar variáveis e chamar funções. Esse é um recurso interessante, mas e um depurador real (pdb)? Vamos experimentar o seguinte programa simples, cujo código está no arquivo
script.py
:
def func(): return 0 / 0 func()
Execute-o com o
python3.8 -i script.py
e obtenha o seguinte:
Vemos o local do programa em que ocorreu o acidente. Defina um ponto de interrupção:
def func(): breakpoint()
Execute o script novamente.
script.py(3)func()
-> return 0 / 0
(Pdb) #
(Pdb) step
ZeroDivisionError: division by zero
> script.py(3)func()
-> return 0 / 0
(Pdb)
Na maioria das situações, o comando
print
e os resultados do rastreio são suficientes para scripts de depuração, mas, às vezes, para lidar com uma falha complexa, você precisa se aprofundar no programa e entender a essência do que está acontecendo. Nesses casos, os pontos de interrupção são definidos no código e o programa é examinado. Por exemplo, eles examinam os argumentos das funções, avaliam expressões, verificam os valores das variáveis ou, como mostrado acima, apenas executam o código passo a passo. Pdb é um wrapper Python totalmente funcional. Nesse shell, você pode fazer quase qualquer coisa. No decorrer do trabalho, alguns comandos específicos do depurador serão úteis, para os quais pode ser encontrada ajuda
aqui .
Declarando vários construtores em uma classe
A sobrecarga de funções é um dos recursos amplamente usados em várias linguagens de programação, mas não no Python. E mesmo que você não possa sobrecarregar uma função regular no Python, podemos usar algo como sobrecarregar construtores usando métodos de classe:
import datetime class Date: def __init__(self, year, month, day): self.year = year self.month = month self.day = day @classmethod def today(cls): t = datetime.datetime.now() return cls(t.year, t.month, t.day) d = Date.today() print(f"{d.day}/{d.month}/{d.year}")
Em uma situação semelhante, em vez de usar métodos de classe, você pode ficar tentado a colocar toda a lógica de construtores alternativos em
__init__
e resolver o problema usando
*args
,
**kwargs
e muitas
if
. O resultado pode estar funcionando, mas será difícil ler e manter esse código. Aqui eu recomendaria colocar um mínimo de lógica em
__init__
e executar todas as operações em métodos / construtores separados. Com essa abordagem, teremos à disposição um código limpo que será conveniente tanto para o autor desse código quanto para quem o usará.
Armazenando em cache resultados de chamadas de função usando um decorador
Você já escreveu funções que executavam algumas operações longas de leitura / gravação ou cálculos recursivos lentos? Ao mesmo tempo, você achou que o armazenamento em cache dos resultados não prejudicaria essas funções? Você pode armazenar em cache (memorizar) os resultados de uma chamada de função usando o decorador
functools
módulo
functools
:
from functools import lru_cache import requests @lru_cache(maxsize=32) def get_with_cache(url): try: r = requests.get(url) return r.text except: return "Not Found" for url in ["https://google.com/", "https://martinheinz.dev/", "https://reddit.com/", "https://google.com/", "https://dev.to/martinheinz", "https://google.com/"]: get_with_cache(url) print(get_with_cache.cache_info())
Neste exemplo, executamos solicitações GET cujos resultados são armazenados em cache (até 32 resultados podem ser armazenados em cache). Aqui você pode ver que obtemos informações sobre o cache da função usando o método
cache_info
. O decorador também nos fornece o método
clear_cache
, que é usado para
clear_cache
cache. Aqui também gostaria de observar que o cache não pode ser usado com funções com efeitos colaterais ou com funções que criam objetos mutáveis a cada chamada.
Localizando itens que são encontrados no objeto iterável com mais frequência
Estar na lista de elementos que são encontrados nela com mais frequência do que outros é uma tarefa muito comum. Você pode resolvê-lo, por exemplo, usando o loop
for
e um dicionário, que coletará informações sobre o número de elementos idênticos. Mas essa abordagem é uma perda de tempo. O fato é que você pode resolver esses problemas usando a classe
Counter
no módulo de
collections
:
from collections import Counter cheese = ["gouda", "brie", "feta", "cream cheese", "feta", "cheddar", "parmesan", "parmesan", "cheddar", "mozzarella", "cheddar", "gouda", "parmesan", "camembert", "emmental", "camembert", "parmesan"] cheese_count = Counter(cheese) print(cheese_count.most_common(3))
Os mecanismos internos da classe
Counter
são baseados em um dicionário que armazena a correspondência de elementos e o número de entradas na lista. Portanto, o objeto correspondente pode ser usado como um objeto de
dict
regular:
print(cheese_count["mozzarella"])
Além disso, ao trabalhar com o
Counter
, temos à disposição o método
update(more_words)
, que é usado para adicionar novos elementos ao contador. Outro recurso útil do
Counter
é que ele permite que você use operações matemáticas (adição e subtração) ao trabalhar com instâncias dessa classe.
Sumário
Eu acho que a maioria das dicas dadas hoje pode muito bem ser usada por quem escreve em Python quase diariamente. Espero que você encontre entre eles algo que seja útil para você.
Caros leitores! Você conhece algum truque interessante de programação em Python? Se sim, compartilhe-os.
