Desde 2014, quando o Python introduziu o suporte para
anotações de tipo , os programadores estão trabalhando em sua implementação em seu código. A autora do material, a primeira parte da tradução publicada hoje, diz que, de acordo com sua avaliação, bastante ousada, agora as anotações de tipo (às vezes chamadas de "dicas") são usadas em cerca de 20 a 30% do código escrito em Python 3.
Aqui estão os resultados da pesquisa, que ela, em maio de 2019, postou no Twitter.
Como se viu, as anotações são usadas por 29% dos entrevistados. Segundo a autora do artigo, nos últimos anos, ela se deparou cada vez mais com anotações de tipos em vários
livros e guias de estudo.
→
A segunda parte
Na documentação do Python, os termos "dica de tipo" e "anotação de tipo" são usados de forma intercambiável. O autor do artigo usa principalmente o termo "dica de tipo", usamos o termo "anotação de tipo".
Este artigo abordará uma ampla gama de questões relacionadas ao uso de anotações de tipo no Python. Se você quiser discutir o artigo
original com o autor, pode usar o mecanismo de
solicitação de recebimento.
1. Introdução
Aqui você pode encontrar um exemplo clássico de como é o código escrito usando anotações de tipo.
Aqui está o código regular:
def greeting(name): return 'Hello ' + name
Aqui está o código ao qual as anotações são adicionadas:
def greeting(name: str) -> str: return 'Hello ' + name
O modelo segundo o qual o código com anotações de tipo é executado é semelhante a este:
def function(variable: input_type) -> return_type: pass
À primeira vista, parece que a aplicação de anotações de tipo no código parece simples e direta. Mas ainda há uma grande quantidade de incerteza na comunidade de desenvolvedores para entender o que exatamente são as anotações de tipo. Além disso, há até ambiguidade em como chamá-los corretamente - "anotações" ou "dicas" e em quais vantagens o uso deles na base de código.
Quando comecei a pesquisar esse tópico e pensar se precisava usar anotações de tipo, fiquei completamente confuso. Como resultado, decidi fazer o mesmo de sempre, tendo encontrado algo incompreensível. Decidi pesquisar profundamente essa questão e apresentar minha pesquisa na forma deste material, que, espero, será útil para aqueles que, como eu, desejam lidar com anotações de tipo em Python.
Como os computadores executam nossos programas?
Para entender o que os desenvolvedores do Python estão tentando obter com as anotações de tipo, vamos falar sobre os mecanismos dos sistemas de computadores que estão vários níveis abaixo do código do Python. Graças a isso, podemos entender melhor como, em termos gerais, computadores e linguagens de programação funcionam.
As linguagens de programação, em sua essência, são ferramentas que permitem processar dados usando uma unidade central de processamento (CPU), além de armazenar na memória os dados que precisam ser processados e os dados resultantes do processamento.
Circuito de computador simplificadoUm processador é uma coisa bastante estúpida em sua essência. Ele é capaz de executar ações impressionantes com dados, mas só entende as instruções da máquina, que se resumem a conjuntos de sinais elétricos. A linguagem de máquina pode ser representada como consistindo de zeros e uns.
Para preparar esses zeros e os que o processador entende, você precisa traduzir o código de um idioma de alto nível para um idioma de baixo nível. É aqui que entram os compiladores e intérpretes.
Se a linguagem for
compilada ou executável (o código Python é executado por meio do intérprete), o código nessa linguagem se transforma em código de máquina de baixo nível, que contém instruções para os componentes de baixo nível do computador, ou seja, para o hardware.
Existem várias maneiras de traduzir o código escrito em alguma linguagem de programação em código que as máquinas possam entender. Você pode criar um arquivo com o código do programa e convertê-lo em código de máquina usando o compilador (é assim que C ++, Go, Rust e algumas outras linguagens funcionam) ou executar o código diretamente usando o intérprete, que será responsável por converter o código em comandos de máquina. É assim que, com a ajuda de intérpretes, os programas em Python são lançados, assim como em outras linguagens de "script", como PHP e Ruby.
Esquema de processamento de código de idioma interpretadoComo o hardware sabe armazenar zeros e os que representam os dados com os quais o programa trabalha na memória? Nosso programa deve informar o computador como alocar memória para esses dados. E quais são esses dados? Depende de quais tipos de dados um idioma específico suporta.
Os tipos de dados estão disponíveis em todos os idiomas. Normalmente, os tipos de dados são um dos primeiros tópicos que os iniciantes aprendem a aprender programação em um determinado idioma.
Existem excelentes tutoriais sobre o mesmo Python, por exemplo - é aqui que você pode encontrar informações detalhadas sobre os tipos de dados. Em palavras simples, os tipos de dados são maneiras diferentes de representar dados armazenados na memória.
Entre os tipos de dados existentes, por exemplo, cadeias e números inteiros podem ser observados. O conjunto de tipos de dados disponíveis para o desenvolvedor depende da linguagem de programação que eles usam. Aqui, por exemplo, está uma lista de
tipos de dados básicos do Python :
int, float, complex str bytes tuple frozenset bool array bytearray list set dict
Existem tipos de dados que consistem em outros tipos de dados. Por exemplo, uma lista em Python pode armazenar números inteiros ou seqüências de caracteres, bem como ambos.
Para descobrir quanta memória você precisa alocar para armazenar alguns dados, o computador precisa saber sobre que tipo de dados o programa irá colocar na memória. O Python possui uma
função getsizeof
embutida que nos informa sobre a quantidade de memória, expressa em bytes, necessária para armazenar os valores de vários tipos de dados.
Aqui está uma ótima resposta para o StackOverflow, onde você pode encontrar informações sobre como descobrir os tamanhos dos valores "mínimos" que podem ser armazenados em vários tipos de variáveis.
import sys import decimal import operator d = {"int": 0, "float": 0.0, "dict": dict(), "set": set(), "tuple": tuple(), "list": list(), "str": "a", "unicode": u"a", "decimal": decimal.Decimal(0), "object": object(), }
Como resultado, classificando um dicionário contendo amostras de valores de vários tipos, podemos descobrir que o tamanho máximo é um dicionário vazio (
dict
) e seguido por um conjunto (
set
). Em comparação com eles, é necessário muito pouco espaço para armazenar um número inteiro (tipo
int
).
O exemplo acima nos dá uma idéia de quanta memória é necessária para armazenar vários valores usados nos programas.
Por que isso deveria nos incomodar? O fato é que alguns tipos são melhores que outros para solucionar alguns problemas, permitindo que você resolva esses problemas com mais eficiência. Em algumas situações, os tipos devem ser verificados com cuidado. Por exemplo, às vezes são feitas verificações de que os tipos de dados usados no programa não são contrários a algumas suposições feitas ao projetar o programa.
Mas quais são esses tipos? Por que precisamos deles? É aqui que o conceito de "sistema de tipos" entra em jogo.
Introdução aos sistemas de tipos
Há muito tempo , em uma galáxia distante e distante, as pessoas que realizavam cálculos matemáticos percebiam
manualmente que se comparassem os "tipos" com números ou elementos de equações, poderiam reduzir o número de erros lógicos que apareciam ao obter provas matemáticas sobre esses elementos.
Como, no início, a ciência da computação foi reduzida, em essência, à execução de grandes volumes de cálculos manuais, alguns desses princípios de longa data foram transferidos para esses cálculos. Os sistemas de tipos tornaram-se uma ferramenta usada para reduzir o número de erros nos programas, atribuindo tipos apropriados a várias variáveis ou elementos.
Aqui estão alguns exemplos:
- Se escrevermos software para o banco, não podemos usar as linhas no fragmento de código que calcula o saldo na conta de outra pessoa.
- Se estivermos trabalhando com os dados de uma pesquisa e quisermos entender se alguém respondeu a uma pergunta positiva ou negativamente, a resposta "sim" e "não" serão naturalmente codificadas usando um tipo lógico.
- Ao desenvolver um grande mecanismo de pesquisa, devemos limitar o número de caracteres que os usuários deste sistema podem inserir no campo de consulta de pesquisa. Isso significa que precisamos verificar alguns dados da string para verificar se há conformidade com determinados parâmetros.
Hoje em programação, existem dois sistemas de tipos principais. Aqui está o que
Steve Klabnik escreve sobre isso: "Um sistema de tipo estático é o mecanismo pelo qual o compilador verifica o código-fonte e atribui rótulos (chamados" tipos ") aos fragmentos do programa e os utiliza para tirar conclusões sobre o comportamento do programa. Um sistema de tipo dinâmico é o mecanismo pelo qual o compilador gera código para observar quais tipos de dados (também chamados de "tipos", por coincidência) são usados pelo programa ".
O que isso significa? Isso significa que, ao trabalhar com idiomas compilados, você geralmente precisa atribuir tipos de entidade com antecedência. Graças a isso, o compilador poderá verificá-los durante a compilação do código e descobrir se será possível criar um programa significativo a partir do código-fonte fornecido a ele.
Recentemente, deparei com uma
explicação da diferença entre tipagem estática e dinâmica. Este é provavelmente o melhor texto que li sobre esse assunto. Aqui está um fragmento: “Eu costumava usar linguagens estaticamente tipadas, mas nos últimos anos tenho programado principalmente em Python. No começo, o uso de digitação estática me incomodou um pouco. Havia um sentimento de que a necessidade de declarar tipos de variáveis diminui e me obriga a exagerar minhas idéias. O Python me deixou fazer o que queria, mesmo que acidentalmente fizesse algo errado. Usar idiomas com digitação estática é como dar uma tarefa a alguém que sempre pergunta novamente, esclarecendo os pequenos detalhes do caso que ele foi designado para concluir. Digitação dinâmica é quando a pessoa que recebe a tarefa sempre concorda com a cabeça. Nesse caso, há um sentimento de que ele entendeu você. Mas, às vezes, não há certeza absoluta de que aquele a quem a tarefa é dada descobriu adequadamente o que se espera dele.
Ao falar sobre sistemas de tipos, me deparei com algo que não entendi imediatamente. Ou seja, os conceitos de "digitação estática" e "digitação dinâmica" estão intimamente relacionados aos conceitos de "linguagem compilada" e "linguagem interpretada", mas os termos "estático" e "compilado", bem como os termos "dinâmico" e "interpretado" não são sinônimos . A linguagem pode ser digitada dinamicamente, como Python, e ao mesmo tempo compilada. Da mesma forma, uma linguagem pode ser digitada estaticamente, como Java, mas também interpretada (por exemplo, no caso de Java, ao usar o Java REPL).
Comparação de tipos de dados em linguagens estática e dinâmica
Qual é a diferença entre os tipos de dados nas linguagens estática e dinâmica?
Ao usar a digitação estática, os tipos devem ser declarados com antecedência. Por exemplo, se você trabalha em Java, seus programas terão a seguinte aparência:
public class CreatingVariables { public static void main(String[] args) { int x, y, age, height; double seconds, rainfall; x = 10; y = 400; age = 39; height = 63; seconds = 4.71; rainfall = 23; double rate = calculateRainfallRate(seconds, rainfall); } private static double calculateRainfallRate(double seconds, double rainfall) { return rainfall/seconds; }
Preste atenção ao início do programa. Diversas variáveis são declaradas lá, próximas às quais há indicações dos tipos dessas variáveis:
int x, y, age, height; double seconds, rainfall;
Além disso, os tipos são especificados ao declarar funções e ao declarar seus argumentos. Sem essas declarações de tipo, o programa não pode ser compilado. Ao criar programas Java, desde o início, você precisa planejar quais tipos essas ou essas entidades terão. Como resultado, o compilador, enquanto processa o código de tais programas, saberá exatamente o que precisa verificar no processo de geração do código da máquina.
O Python elimina os problemas de um programador. Código Python semelhante pode ser assim:
y = 400 age = 39 height = 63 seconds = 4.71 rainfall = 23 rate = calculateRainfall(seconds, rainfall) def calculateRainfall(seconds, rainfall): return rainfall/seconds
Como tudo isso funciona nas entranhas do Python? Para continuar ...
Caros leitores! Qual linguagem de programação que você usou deixou a impressão mais agradável?
