{"id":38649,"date":"2019-10-31T22:25:04","date_gmt":"2019-10-31T19:25:04","guid":{"rendered":"https:\/\/prohoster.info\/blog\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3\/"},"modified":"2019-10-31T22:25:04","modified_gmt":"2019-10-31T19:25:04","slug":"put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","title":{"rendered":"O caminho para verifica\u00e7\u00e3o de tipos em 4 milh\u00f5es de linhas de c\u00f3digo Python. Parte 3","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Apresentamos a voc\u00ea a terceira parte da tradu\u00e7\u00e3o do material sobre o caminho que a empresa Dropbox percorreu ao implementar um sistema de verifica\u00e7\u00e3o de tipos no c\u00f3digo Python.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468237\/\"><img decoding=\"async\" alt=\"O caminho para verifica\u00e7\u00e3o de tipos em 4 milh\u00f5es de linhas de c\u00f3digo Python. Parte 3\" src=\"\/wp-content\/uploads\/2019\/10\/757669265e870de604388c66adef814d.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><\/p>\n<p>\u2192 Partes anteriores: <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468233\/\">primeiro<\/a><\/noindex> e <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468235\/\">segundo<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Alcan\u00e7ando 4 milh\u00f5es de linhas de c\u00f3digo tipadas<\/h2>\n<p>\nOutra tarefa importante (esta era a segunda quest\u00e3o mais popular que preocupava os participantes das pesquisas internas) foi aumentar o volume de c\u00f3digo no Dropbox coberto por verifica\u00e7\u00f5es de tipos. Experimentamos v\u00e1rias abordagens para resolver essa quest\u00e3o \u2014 desde o crescimento natural do volume da base de c\u00f3digo tipada at\u00e9 a concentra\u00e7\u00e3o dos esfor\u00e7os da equipe mypy em dedu\u00e7\u00e3o de tipos est\u00e1tica e din\u00e2mica automatizada. Como resultado, pareceu que n\u00e3o havia uma estrat\u00e9gia vencedora simples, mas conseguimos alcan\u00e7ar um r\u00e1pido crescimento no volume de c\u00f3digo anotado, combinando v\u00e1rias abordagens.<\/p>\n<p>Como resultado, em nosso maior reposit\u00f3rio Python (com c\u00f3digo de backend), o n\u00famero de linhas de c\u00f3digo anotado quase alcan\u00e7ou 4 milh\u00f5es. O trabalho na tipagem est\u00e1tica do c\u00f3digo foi realizado em cerca de tr\u00eas anos. O mypy agora suporta v\u00e1rios tipos de relat\u00f3rios de cobertura de tipos de c\u00f3digo que facilitam o monitoramento do progresso da tipagem. Especificamente, podemos gerar relat\u00f3rios para c\u00f3digo com incertezas de tipos, como por exemplo, o uso expl\u00edcito de tipo <code>Any<\/code> em anota\u00e7\u00f5es que n\u00e3o podem ser verificadas, ou como no caso da importa\u00e7\u00e3o de bibliotecas de terceiros que n\u00e3o possuem anota\u00e7\u00f5es de tipos. Como parte de um projeto para melhorar a precis\u00e3o da verifica\u00e7\u00e3o de tipos no Dropbox, contribu\u00edmos para aprimorar defini\u00e7\u00f5es de tipos (os chamados arquivos stub) para algumas bibliotecas open-source populares em um reposit\u00f3rio Python centralizado <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/python\/typeshed\">typeshed<\/a><\/noindex>.<\/p>\n<p>Implementamos (e padronizamos nas PEP subsequentes) novos recursos do sistema de tipos que permitem usar tipos mais precisos para alguns padr\u00f5es espec\u00edficos do Python. Um exemplo not\u00e1vel disso \u00e9 <code>TypeDict<\/code>, que fornece tipos para dicion\u00e1rios semelhantes a JSON que possuem um conjunto fixo de chaves de string, cada uma com um valor de seu pr\u00f3prio tipo. Continuaremos a expandir o sistema de tipos. Provavelmente, nosso pr\u00f3ximo passo ser\u00e1 melhorar o suporte para as capacidades do Python relacionadas a n\u00fameros.<\/p>\n<p><img decoding=\"async\" alt=\"O caminho para verifica\u00e7\u00e3o de tipos em 4 milh\u00f5es de linhas de c\u00f3digo Python. Parte 3\" src=\"\/wp-content\/uploads\/2019\/10\/297b9e823141d6cb0d2f19f9a78a1153.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>N\u00famero de linhas de c\u00f3digo anotado: servidor<\/i><\/p>\n<p><img decoding=\"async\" alt=\"O caminho para verifica\u00e7\u00e3o de tipos em 4 milh\u00f5es de linhas de c\u00f3digo Python. Parte 3\" src=\"\/wp-content\/uploads\/2019\/10\/c183a9227e51d847bfdb2b8f6153684f.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>N\u00famero de linhas de c\u00f3digo anotado: cliente<\/i><\/p>\n<p><img decoding=\"async\" alt=\"O caminho para verifica\u00e7\u00e3o de tipos em 4 milh\u00f5es de linhas de c\u00f3digo Python. Parte 3\" src=\"\/wp-content\/uploads\/2019\/10\/0a8b936fa454a34c09a9c6a2694485c9.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Total de linhas de c\u00f3digo anotado<\/i><\/p>\n<p>Aqui est\u00e1 uma vis\u00e3o geral das principais caracter\u00edsticas das a\u00e7\u00f5es que realizamos para aumentar a quantidade de c\u00f3digo anotado no Dropbox:<\/p>\n<p>Rigor da anota\u00e7\u00e3o. Aumentamos gradualmente as exig\u00eancias de rigor na anota\u00e7\u00e3o do novo c\u00f3digo. Come\u00e7amos com sugest\u00f5es de linters, que recomendavam adicionar anota\u00e7\u00f5es em arquivos que j\u00e1 tinham algumas anota\u00e7\u00f5es. Agora, exigimos a presen\u00e7a de anota\u00e7\u00f5es de tipo em novos arquivos Python e na maioria dos arquivos existentes.<\/p>\n<p>Relat\u00f3rios de tipagem. Enviamos semanalmente \u00e0s equipes relat\u00f3rios sobre o n\u00edvel de tipagem de seu c\u00f3digo e damos conselhos sobre o que deve ser anotado primeiro.<\/p>\n<p>Promo\u00e7\u00e3o do mypy. Estamos falando sobre o mypy em diversos eventos e interagindo com as equipes, ajudando-as a come\u00e7ar a usar anota\u00e7\u00f5es de tipos.<\/p>\n<p>Pesquisas. Realizamos pesquisas peri\u00f3dicas com usu\u00e1rios para identificar os principais problemas. Estamos dispostos a ir longe na resolu\u00e7\u00e3o desses problemas (at\u00e9 mesmo criando uma nova linguagem para acelerar o mypy!).<\/p>\n<p>Desempenho. Melhoramos significativamente o desempenho do mypy por meio do uso de daemon e mypyc. Isso foi feito para suavizar as dificuldades que surgem durante a anota\u00e7\u00e3o e para permitir o trabalho com grandes volumes de c\u00f3digo.<\/p>\n<p>Integra\u00e7\u00e3o com editores. Criamos ferramentas para suportar a execu\u00e7\u00e3o do mypy em editores populares do Dropbox. Isso inclui PyCharm, Vim e VS Code. Isso facilitou significativamente o processo de anota\u00e7\u00e3o do c\u00f3digo e verifica\u00e7\u00e3o de sua funcionalidade. Essas a\u00e7\u00f5es s\u00e3o geralmente caracter\u00edsticas ao anotar c\u00f3digo existente.<\/p>\n<p>An\u00e1lise est\u00e1tica. Criamos uma ferramenta para gerar assinaturas de fun\u00e7\u00f5es usando ferramentas de an\u00e1lise est\u00e1tica. Essa ferramenta pode funcionar apenas em situa\u00e7\u00f5es relativamente simples, mas nos ajudou a aumentar a cobertura de tipos no c\u00f3digo sem muito esfor\u00e7o.<\/p>\n<p>Suporte para bibliotecas de terceiros. Muitos de nossos projetos utilizam o conjunto de ferramentas SQLAlchemy. Ele utiliza as capacidades din\u00e2micas do Python, que os tipos PEP 484 n\u00e3o conseguem modelar diretamente. De acordo com o PEP 561, criamos o arquivo stub correspondente e escrevemos um plugin para o mypy.<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/dropbox\/sqlalchemy-stubs\">c\u00f3digo aberto<\/a><\/noindex>), melhorando o suporte ao SQLAlchemy.<\/p>\n<h2>Desafios que encontramos<\/h2>\n<p>\nO caminho at\u00e9 4 milh\u00f5es de linhas de c\u00f3digo tipificado nem sempre foi f\u00e1cil. Ao longo dessa jornada, encontramos v\u00e1rios obst\u00e1culos e cometemos alguns erros. Aqui est\u00e3o alguns dos problemas que enfrentamos. Esperamos que este relato ajude outros a evitar problemas semelhantes.<\/p>\n<p>Arquivos ausentes. Come\u00e7amos nosso trabalho com a verifica\u00e7\u00e3o de um pequeno volume de arquivos. Tudo o que n\u00e3o estava nessa lista n\u00e3o era checado. Arquivos eram adicionados \u00e0 lista de verifica\u00e7\u00e3o assim que as primeiras anota\u00e7\u00f5es apareciam. Se algo era importado de um m\u00f3dulo fora da \u00e1rea de verifica\u00e7\u00e3o, est\u00e1vamos lidando com valores do tipo <code>Any<\/code>, que n\u00e3o eram verificados. Isso levou a uma significativa perda de precis\u00e3o na tipifica\u00e7\u00e3o, especialmente nas fases iniciais da migra\u00e7\u00e3o. Esse m\u00e9todo ainda funcionava surpreendentemente bem, embora fosse comum que a adi\u00e7\u00e3o de arquivos \u00e0 \u00e1rea de verifica\u00e7\u00e3o revelasse problemas em outras partes da base de c\u00f3digo. No pior dos casos, quando duas \u00e1reas de c\u00f3digo isoladas, nas quais os tipos foram verificados independentemente, eram combinadas, descobria-se que os tipos dessas \u00e1reas eram incompat\u00edveis. Isso resultava na necessidade de fazer muitas altera\u00e7\u00f5es nas anota\u00e7\u00f5es. Agora, olhando para tr\u00e1s, percebemos que dever\u00edamos ter inclu\u00eddo os m\u00f3dulos de biblioteca b\u00e1sica na \u00e1rea de verifica\u00e7\u00e3o de tipos mypy o mais cedo poss\u00edvel. Isso teria tornado nosso trabalho muito mais previs\u00edvel.<\/p>\n<p>Anota\u00e7\u00e3o de c\u00f3digo antigo. Quando come\u00e7amos nosso trabalho, t\u00ednhamos cerca de 4 milh\u00f5es de linhas de c\u00f3digo Python j\u00e1 existente. Ficou claro que a anota\u00e7\u00e3o de todo esse c\u00f3digo era uma tarefa dif\u00edcil. Criamos uma ferramenta chamada PyAnnotate, que pode coletar informa\u00e7\u00f5es de tipos durante a execu\u00e7\u00e3o dos testes e adicionar anota\u00e7\u00f5es de tipos ao c\u00f3digo com base nas informa\u00e7\u00f5es coletadas. No entanto, n\u00e3o percebemos uma ado\u00e7\u00e3o muito ampla dessa ferramenta. A coleta de informa\u00e7\u00f5es de tipos era lenta e as anota\u00e7\u00f5es geradas automaticamente frequentemente exigiam muitas corre\u00e7\u00f5es manuais. Pensamos em iniciar automaticamente essa ferramenta a cada verifica\u00e7\u00e3o de c\u00f3digo ou em coletar informa\u00e7\u00f5es de tipos com base na an\u00e1lise de um pequeno volume de solicita\u00e7\u00f5es de rede reais, mas decidimos n\u00e3o faz\u00ea-lo, pois qualquer uma dessas abordagens era muito arriscada.<\/p>\n<p>No final, podemos notar que a maior parte do c\u00f3digo foi anotaada manualmente por seus propriet\u00e1rios. Para direcionar esse processo na dire\u00e7\u00e3o certa, estamos preparando relat\u00f3rios sobre m\u00f3dulos e fun\u00e7\u00f5es especialmente importantes que precisam ser anotados. Por exemplo, \u00e9 importante fornecer anota\u00e7\u00f5es de tipos para o m\u00f3dulo de biblioteca, utilizado em centenas de locais. J\u00e1 para o servi\u00e7o antigo, que est\u00e1 sendo substitu\u00eddo por um novo, n\u00e3o \u00e9 t\u00e3o importante anot\u00e1-lo. Al\u00e9m disso, estamos experimentando o uso de an\u00e1lise est\u00e1tica para gerar anota\u00e7\u00f5es de tipos para o c\u00f3digo antigo.<\/p>\n<p>Importa\u00e7\u00f5es c\u00edclicas. Acima, mencionei as importa\u00e7\u00f5es c\u00edclicas (os \"novelos de depend\u00eancias\"), cuja exist\u00eancia complicou a acelera\u00e7\u00e3o do mypy. Al\u00e9m disso, tivemos que trabalhar arduamente para fornecer ao mypy suporte a todos os tipos de idiomatismos, cuja origem est\u00e1 nessas importa\u00e7\u00f5es c\u00edclicas. Recentemente, conclu\u00edmos um grande projeto de redesign do sistema, que corrigiu a maioria dos problemas do mypy relacionados a importa\u00e7\u00f5es c\u00edclicas. Esses problemas, na verdade, surgiram desde os prim\u00f3rdios do projeto, ainda do Alore, a linguagem de programa\u00e7\u00e3o educativa para a qual o mypy foi inicialmente orientado. A sintaxe do Alore resolve facilmente os problemas de comandos de importa\u00e7\u00e3o c\u00edclica. O mypy moderno herdou algumas limita\u00e7\u00f5es de sua implementa\u00e7\u00e3o inicial simples (que funcionava muito bem para Alore). O Python complica o trabalho com importa\u00e7\u00f5es c\u00edclicas principalmente devido \u00e0 ambiguidade das express\u00f5es. Por exemplo, durante uma opera\u00e7\u00e3o de atribui\u00e7\u00e3o, um alias de tipo pode, na verdade, ser definido. O mypy nem sempre consegue identificar essas coisas at\u00e9 que a maior parte do ciclo de importa\u00e7\u00e3o tenha sido processada. No Alore, essas ambiguidades n\u00e3o existiam. Decis\u00f5es mal sucedidas tomadas nos est\u00e1gios iniciais de desenvolvimento do sistema podem surpreender o programador anos depois.<\/p>\n<h2>Resultados: o caminho para 5 milh\u00f5es de linhas de c\u00f3digo e novos horizontes<\/h2>\n<p>\nO projeto mypy percorreu um longo caminho \u2013 desde os primeiros prot\u00f3tipos at\u00e9 um sistema que controla os tipos de c\u00f3digo de produ\u00e7\u00e3o com 4 milh\u00f5es de linhas. Ao longo do desenvolvimento, houve uma padroniza\u00e7\u00e3o das sugest\u00f5es de tipos em Python. Hoje em dia, uma poderosa ecossistema se desenvolveu em torno da tipagem de c\u00f3digo Python. Isso inclui suporte a bibliotecas, ferramentas auxiliares para IDEs e editores, al\u00e9m de v\u00e1rios sistemas de controle de tipos, cada um com suas vantagens e desvantagens.<\/p>\n<p>Embora a verifica\u00e7\u00e3o de tipos j\u00e1 seja considerada algo trivial no Dropbox, estou convencido de que ainda estamos no amanhecer da tipagem de c\u00f3digo em Python. Acredito que as tecnologias de verifica\u00e7\u00e3o de tipos continuar\u00e3o a evoluir e se aprimorar.<\/p>\n<p>Se voc\u00ea ainda n\u00e3o utilizou checagens de tipos em seu projeto Python em grande escala, saiba que agora \u00e9 um momento bastante apropriado para come\u00e7ar a transi\u00e7\u00e3o para a tipagem est\u00e1tica. Conversamos com aqueles que fizeram essa mudan\u00e7a. Ningu\u00e9m se arrependeu. O controle de tipos transforma o Python em uma linguagem que se adapta muito melhor ao desenvolvimento de grandes projetos do que o \"Python comum\".<\/p>\n<p><b>Prezados leitores!<\/b> Voc\u00ea utiliza controle de tipos em seus projetos Python?<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/vps_start\/\"><img decoding=\"async\" alt=\"O caminho para verifica\u00e7\u00e3o de tipos em 4 milh\u00f5es de linhas de c\u00f3digo Python. Parte 3\" src=\"\/wp-content\/uploads\/2019\/10\/bf2bc557ce4481dd87398515bff60e3f.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/ruvds.com\/ru-rub\/#order\"><img decoding=\"async\" alt=\"O caminho para verifica\u00e7\u00e3o de tipos em 4 milh\u00f5es de linhas de c\u00f3digo Python. Parte 3\" src=\"\/wp-content\/uploads\/2019\/10\/098d481c25b3afaba9534c686e8f943a.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<br \/>Fonte: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/468237\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430. \u2192 \u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0447\u0430\u0441\u0442\u0438: \u043f\u0435\u0440\u0432\u0430\u044f \u0438 \u0432\u0442\u043e\u0440\u0430\u044f \u0414\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0435 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0415\u0449\u0451 \u043e\u0434\u043d\u043e\u0439 \u0432\u0430\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 (\u044d\u0442\u043e \u0431\u044b\u043b \u0432\u0442\u043e\u0440\u0430\u044f \u043f\u043e \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u0432\u043e\u043b\u043d\u043e\u0432\u0430\u0432\u0448\u0430\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 \u043e\u043f\u0440\u043e\u0441\u0430\u0445) \u0431\u044b\u043b\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0451\u043c\u0430 \u043a\u043e\u0434\u0430 \u0432 Dropbox, [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":28992,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-38649","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041f\u0443\u0442\u044c \u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0442\u0438\u043f\u043e\u0432 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a Python-\u043a\u043e\u0434\u0430. \u0427\u0430\u0441\u0442\u044c 3 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:25:04+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:25:04+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47O caminho para a verifica\u00e7\u00e3o de tipos em 4 milh\u00f5es de linhas de c\u00f3digo Python. Parte 3 | ProHoster","description":"Apresentamos a voc\u00ea a terceira parte da tradu\u00e7\u00e3o do material sobre o caminho que a empresa Dropbox percorreu ao implementar um sistema de verifica\u00e7\u00e3o de tipos no c\u00f3digo Python.","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041f\u0443\u0442\u044c \u043a \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0442\u0438\u043f\u043e\u0432 4 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u0441\u0442\u0440\u043e\u043a Python-\u043a\u043e\u0434\u0430. \u0427\u0430\u0441\u0442\u044c 3 | ProHoster","og:description":"\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u0442\u0440\u0435\u0442\u044c\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0430 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0430 \u043e \u043f\u0443\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0448\u043b\u0430 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f Dropbox, \u0432\u043d\u0435\u0434\u0440\u044f\u044f \u0443 \u0441\u0435\u0431\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 Python-\u043a\u043e\u0434\u0430.","og:url":"https:\/\/prohoster.info\/pt\/blog\/administrirovanie\/put-k-proverke-tipov-4-millionov-strok-python-koda-chast-3","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:25:04+00:00","article:modified_time":"2019-10-31T19:25:04+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"38649","title":null,"description":null,"keywords":null,"keyphrases":{"focus":[],"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-23 22:54:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:05:23","updated":"2026-08-11 12:50:30","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/38649","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=38649"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/38649\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/28992"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=38649"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=38649"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=38649"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}