❝Não enterre seu fardo em silêncio santo. Você tem um problema? Excelente. Alegre-se, mergulhe e investigue.❞
- Ven. Henepola Gunaratana
Mergulho
A convenção dita que devo aborrecê-lo com os blocos de construção fundamentais da programação, para que possamos trabalhar lentamente para construir algo útil. Vamos pular tudo isso. Aqui está um programa Python completo e funcional. Provavelmente não faz absolutamente nenhum sentido para você. Não se preocupe com isso, porque você vai dissecar linha por linha. Mas leia primeiro e veja o que você pode fazer com isso, se é que pode fazer alguma coisa.
SUFIXOS = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}
def tamanho_aproximado(tamanho, um_kilobyte_eh_1024_bytes=True):
'''Converta um tamanho de arquivo em um formato legível.
Argumentos keyword:
tamanho -- tamanho do arquivo em bytes
um_kilobyte_eh_1024_bytes -- if True (padrão), usa multiplos de 1024
if False, usa multiplos de 1000
Retorna: string
'''
if tamanho < 0:
raise ValueError('O número não deve ser negativo')
multiplo = 1024 if um_kilobyte_eh_1024_bytes else 1000
for sufixo in SUFIXOS[multiplo]:
tamanho /= multiplo
if tamanho < multiplo:
return '{0:.1f} {1}'.format(tamanho, sufixo)
raise ValueError('numero muito longo')
if __name__ == '__main__':
print(tamanho_aproximado(1000000000000, False))
print(tamanho_aproximado(1000000000000))
Agora vamos executar este programa na linha de comando. No Windows, será mais ou menos assim:
PS C:\Users\user\working\dive_into_python_3> & C:/Users/user/AppData/Local/Programs/Python/Python37/python.exe c:/Users/user/working/dive_into_python_3/teste.py 1.0 TB 931.3 GiB
No Mac OS X ou Linux, seria algo assim:
you@localhost:~/diveintopython3/examples$ python3 teste.py 1.0 TB 931.3 GiB
O que acabou de acontecer? Você executou seu primeiro programa Python. Você chamou o interpretador Python na linha de comando e passou o nome do script que queria que o Python executasse. O script define uma única função, a função tamanho_aproximado()
, que pega um tamanho de arquivo exato em bytes e calcula um tamanho “bonito” (mas aproximado). (Você provavelmente já viu isso no Windows Explorer, ou no Mac OS X Finder, ou Nautilus ou Dolphin ou Thunar no Linux. Se você exibir uma pasta de documentos como uma lista de várias colunas, será exibida uma tabela com o ícone do documento, o nome do documento, o tamanho, o tipo, a data da última modificação e assim por diante. Se a pasta contiver um arquivo de 1093 bytes denominado TODO
, seu gerenciador de arquivos não será exibido TODO 1093 bytes
; em vez disso, aparecerá algo como TODO 1 KB
. Isso é o que a função tamanho_aproximado()
faz).
Observe a parte inferior do script e você verá duas chamadas para print(tamanho_aproximado(
. Essas são chamadas de função - primeiro chamando a função arguments
))tamanho_aproximado()
e passando uma série de argumentos, depois pegando o valor de retorno e passando-o direto para a função print()
. A função print()
é integrada; você nunca verá uma declaração explícita disso. Você pode simplesmente usá-la, a qualquer hora, em qualquer lugar. (Existem muitas funções integradas e muito mais funções que são separadas em módulos. Paciência, gafanhoto).
Então, por que a execução do script na linha de comando fornece sempre a mesma saída? Nós vamos chegar a isso. Primeiro, vamos examinar essa função tamanho_aproximado()
.
Declarando funções
Python tem funções como a maioria das outras linguagens, mas não tem arquivos de cabeçalho separados como C++ ou seções interface/implementation
como Pascal. Quando você precisar de uma função, basta declará-la, assim:
def tamanho_aproximado(tamanho, um_kilobyte_eh_1024_bytes=True):
A palavra-chave def
inicia a declaração da função, seguida pelo nome da função, seguido pelos argumentos entre parênteses. Vários argumentos são separados por vírgulas.
Observe também que a função não define um tipo de dados de retorno. As funções Python não especificam o tipo de dados de seu valor de retorno; eles nem mesmo especificam se retornam ou não um valor. (Na verdade, toda função Python retorna um valor; se a função alguma vez executar uma instrução return
, ela retornará esse valor; caso contrário, retornará None
o valor nulo do Python).
Observação
Em algumas linguagens, as funções (que retornam um valor) começam com function
, e as sub-rotinas (que não retornam um valor) começam com sub
. Não há sub-rotinas em Python. Tudo é uma função, todas as funções retornam um valor (mesmo que seja None
) e todas as funções começam com def
.
A função tamanho_aproximado()
leva os dois argumentos - tamanho
e um_kilobyte_eh_1024_bytes
- mas nenhum dos argumentos especifica um tipo de dados. Em Python, as variáveis nunca são tipadas explicitamente. Python descobre que tipo é uma variável e mantém o controle dela internamente.
Observação
Em Java e outras linguagens tipadas estaticamente, você deve especificar o tipo de dados do valor de retorno da função e cada argumento da função. Em Python, você nunca especifica explicitamente o tipo de dados de nada. Com base no valor que você atribui, o Python rastreia o tipo de dados internamente.
Argumentos opcionais e nomeados
Python permite que argumentos de função tenham valores padrão; se a função for chamada sem o argumento, o argumento obterá seu valor padrão. Além disso, os argumentos podem ser especificados em qualquer ordem usando argumentos nomeados.
Vamos dar outra olhada na declaração da função tamanho_aproximado()
:
def tamanho_aproximado(tamanho, um_kilobyte_eh_1024_bytes=True):
O segundo argumento, um_kilobyte_eh_1024_bytes
, especifica um valor padrão igual a True
. Isso significa que o argumento é opcional; você pode chamar a função sem ele e o Python agirá como se você tivesse chamado como a função passando o valor True
para o segundo parâmetro.
Agora observe a parte inferior do script:
if __name__ == '__main__':
print(tamanho_aproximado(1000000000000, False)) ①
print(tamanho_aproximado(1000000000000)) ②
-
Isso chama a função
tamanho_aproximado()
com dois argumentos. Dentro da funçãotamanho_aproximado()
,um_kilobyte_eh_1024_bytes
seráFalse
, já que você passou explicitamenteFalse
como o segundo argumento. -
Isso chama a função
tamanho_aproximado()
com apenas um argumento. Mas tudo bem, porque o segundo argumento é opcional! Como o chamador não especifica, o segundo argumento é padronizado (True
), conforme definido pela declaração da função.
Você também pode passar valores para uma função por nome.
Observação
teste
é o nome do nosso script python. Execute o shell python na pasta onde o arquivo teste.py foi salvo.
Por exemplo: No PowerShell (windows), terminal (Linux, Mac) execute esses comando: cd caminho_da_pasta
.
Exemplo PowerShell: cd C:\Users\dive_into_python_3
; No terminal: cd /home/user/dive_into_python_3
.
>>> from teste import tamanho_aproximado
>>> tamanho_aproximado(4000, um_kilobyte_eh_1024_bytes=False) ①
'4.0 KB'
>>> tamanho_aproximado(tamanho=4000, um_kilobyte_eh_1024_bytes=False) ②
'4.0 KB'
>>> tamanho_aproximado(um_kilobyte_eh_1024_bytes=False, tamanho=4000) ③
'4.0 KB'
>>> tamanho_aproximado(um_kilobyte_eh_1024_bytes=False, 4000) ④
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
>>> tamanho_aproximado(tamanho=4000, False) ⑤
File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
-
Isso chama a função
tamanho_aproximado()
passando o valor4000
para o primeiro argumento (tamanho
) eFalse
para o argumento denominadoum_kilobyte_eh_1024_bytes
. (Esse é o segundo argumento, mas não importa, como você verá em um minuto). -
Isso chama a função
tamanho_aproximado()
passando o valor4000
para o argumento denominadotamanho
eFalse
para o argumento denominadoum_kilobyte_eh_1024_bytes
. (Esses argumentos nomeados estão na mesma ordem que os argumentos listados na declaração da função, mas isso também não importa). -
Isso chama a função
tamanho_aproximado()
passando o valorFalse
para o argumento denominadoum_kilobyte_eh_1024_bytes
e4000
para o argumento denominadotamanho
. (Viu? Eu disse que a ordem não importava). -
Essa chamada falha, porque você tem um argumento nomeado seguido por um argumento não nomeado (posicional) e isso nunca funciona. Lendo a lista de argumentos da esquerda para a direita, uma vez que você tenha um único argumento nomeado, o restante dos argumentos também deve ser nomeado.
-
Esta chamada também falha, pelo mesmo motivo da chamada anterior. Isso é surpreendente? Afinal, você passou
4000
para o argumento nomeadotamanho
, então “obviamente” esse valorFalse
era para o argumentoum_kilobyte_eh_1024_bytes
. Mas Python não funciona assim. Assim que você tiver um argumento nomeado, todos os argumentos à direita dele também precisam ser argumentos nomeados.
Escrevendo código legível
Não vou aborrecê-lo com um longo discurso de abanar o dedo sobre a importância de documentar seu código. Saiba que o código é escrito uma vez, mas lido muitas vezes, e o público mais importante para o seu código é você mesmo, seis meses depois de escrevê-lo (ou seja, depois que você esqueceu tudo, mas precisa consertar algo). Python facilita a escrita de código legível, então tire proveito disso. Você vai me agradecer em seis meses.
Strings de documentação
Você pode documentar uma função Python fornecendo a ela uma string de documentação (docstring
para abreviar). Neste programa, a função tamanho_aproximado()
possui uma docstring
:
def tamanho_aproximado(tamanho, um_kilobyte_eh_1024_bytes=True):
'''Converta um tamanho de arquivo em um formato legível.
Argumentos keyword:
tamanho -- tamanho do arquivo em bytes
um_kilobyte_eh_1024_bytes -- if True (padrão), usa multiplos de 1024
if False, usa multiplos de 1000
Retorna: string
'''
Cada função merece uma docstring decente.
As aspas triplas significam uma string de várias linhas. Tudo entre as aspas iniciais e finais faz parte de uma única string, incluindo retornos de carro, espaço em branco inicial e outros caracteres de aspas. Você pode usá-los em qualquer lugar, mas verá que são usados com mais frequência ao definir uma docstring
.
Observação
As aspas triplas também são uma maneira fácil de definir uma string com aspas simples e duplas, como qq/.../
no Perl 5.
Tudo o que está entre as aspas triplas é da docstring
da função, que documenta o que a função faz. A docstring
, se existir, deve ser a primeira coisa definida em uma função (ou seja, na próxima linha após a declaração da função). Tecnicamente, você não precisa atribuir um valor à sua docstring
da função, mas sempre deve. Eu sei que você já ouviu isso em todas as aulas de programação que já fez, mas o Python oferece um incentivo adicional: A docstring
está disponível em tempo de execução como um atributo da função.
Observação
Muitas IDEs Python usam a docstring
para fornecer documentação sensível ao contexto, de forma que quando você digita o nome de uma função, a docstring
aparece como uma dica de ferramenta. Isso pode ser extremamente útil, mas é tão bom quanto a docstring
que você escreve.
O Caminho de Pesquisa import
Antes de prosseguir, quero mencionar brevemente o caminho de pesquisa da biblioteca. Python procura em vários lugares quando você tenta importar um módulo. Especificamente, ele procura em todos os diretórios definidos em sys.path
. Esta é apenas uma lista e você pode facilmente visualizá-la ou modificá-la com métodos de lista padrão. (Você aprenderá mais sobre listas em tipos de dados nativos).
>>> import sys ①
>>> sys.path ②
['',
'/usr/lib/python31.zip',
'/usr/lib/python3.1',
'/usr/lib/python3.1/plat-linux2@EXTRAMACHDEPPATH@',
'/usr/lib/python3.1/lib-dynload',
'/usr/lib/python3.1/dist-packages',
'/usr/local/lib/python3.1/dist-packages']
>>> sys ③
<module 'sys' (built-in)>
>>> sys.path.insert(0, '/home/mark/diveintopython3/examples') ④
>>> sys.path ⑤
['/home/mark/diveintopython3/examples',
'',
'/usr/lib/python31.zip',
'/usr/lib/python3.1',
'/usr/lib/python3.1/plat-linux2@EXTRAMACHDEPPATH@',
'/usr/lib/python3.1/lib-dynload',
'/usr/lib/python3.1/dist-packages',
'/usr/local/lib/python3.1/dist-packages']
-
A importação do módulo
sys
disponibiliza todas as suas funções e atributos. -
sys.path
é uma lista de nomes de diretório que constituem o caminho de pesquisa atual. (O seu terá uma aparência diferente, dependendo do seu sistema operacional, da versão do Python que você está executando e de onde foi instalado originalmente). O Python procurará nesses diretórios (nesta ordem) um arquivo.py
cujo nome corresponda ao que você está tentando importar. -
Na verdade, eu menti; a verdade é mais complicada do que isso, porque nem todos os módulos são armazenados como arquivos
.py
. Alguns são módulos integrados; eles são realmente embutidos no próprio Python. Módulos integrados se comportam como módulos regulares, mas seu código-fonte Python não está disponível, porque eles não são escritos em Python! (Como o próprio Python, esses módulos integrados são escritos em C). -
Você pode adicionar um novo diretório ao caminho de pesquisa do Python em tempo de execução, adicionando o nome do diretório a
sys.path
, e o Python também procurará nesse diretório, sempre que você tentar importar um módulo. O efeito dura enquanto o Python estiver em execução. -
Ao usar
sys.path.insert(0, new_path)
, você inseriu um novo diretório como o primeiro item da listasys.path
e, portanto, no início do caminho de pesquisa do Python. Quase sempre é isso que você deseja. Em caso de conflitos de nomenclatura (por exemplo, se Python vem com a versão 2 de uma biblioteca específica, mas você deseja usar a versão 3), isso garante que seus módulos serão encontrados e usados em vez dos módulos que vieram com Python.
Tudo é um objeto
Caso você tenha perdido, eu acabei de dizer que as funções do Python têm atributos e que esses atributos estão disponíveis em tempo de execução. Uma função, como tudo o mais em Python, é um objeto.
Execute o shell Python interativo e siga em frente:
>>> import teste ①
>>> print(teste.tamanho_aproximado(4096, True)) ②
4.0 KiB
>>> print(teste.tamanho_aproximado.__doc__) ③
Converta um tamanho de arquivo em um formato legível.
Argumentos keyword:
tamanho -- tamanho do arquivo em bytes
um_kilobyte_eh_1024_bytes -- if True (padrão), usa multiplos de 1024
if False, usa multiplos de 1000
Retorna: string
-
A primeira linha importa o programa
teste
como um módulo - um pedaço de código que você pode usar interativamente ou de um programa Python maior. Depois de importar um módulo, você pode fazer referência a qualquer uma de suas funções, classes ou atributos públicos. Os módulos podem fazer isso para acessar a funcionalidade em outros módulos, e você também pode fazer isso no shell interativo do Python. Este é um conceito importante, e você verá muito mais dele ao longo deste livro. -
Quando você deseja usar funções definidas em módulos importados, você precisa incluir o nome do módulo. Então você não pode simplesmente dizer
tamanho_aproximado
; deve serteste.tamanho_aproximado
. Se você usou classes em Java, isso deve parecer vagamente familiar. -
Em vez de chamar a função como você esperava, solicitou um dos atributos da função,
__doc__
.
Observação
import
em Python é como require
em Perl. Depois de criar um módulo Python, você acessa suas funções com module.function
; uma vez que você precisa de um módulo Perl, você acessa suas funções com module::function
.
O que é um objeto?
Tudo em Python é um objeto e tudo pode ter atributos e métodos. Todas as funções têm um atributo __doc__
embutido, que retorna a docstring
definida no código-fonte da função. O módulo sys
é um objeto que possui (entre outras coisas) um atributo denominado path
. E assim por diante.
Ainda assim, isso não responde à questão mais fundamental: o que é um objeto? Diferentes linguagens de programação definem “objeto” de maneiras diferentes. Em alguns, significa que todos os objetos devem ter atributos e métodos; em outros, significa que todos os objetos são subclassíveis. Em Python, a definição é mais ampla. Alguns objetos não têm atributos nem métodos, mas poderiam. Nem todos os objetos são subclassíveis. Mas tudo é um objeto no sentido de que pode ser atribuído a uma variável ou passado como um argumento para uma função.
Você pode ter ouvido o termo “objeto de primeira classe” em outros contextos de programação. Em Python, funções são objetos de primeira classe. Você pode passar uma função como um argumento para outra função. Módulos são objetos de primeira classe. Você pode passar um módulo inteiro como um argumento para uma função. As classes são objetos de primeira classe e as instâncias individuais de uma classe também são objetos de primeira classe.
Isso é importante, então vou repeti-lo caso você tenha perdido nas primeiras vezes: tudo em Python é um objeto. Strings são objetos. Listas são objetos. Funções são objetos. As classes são objetos. As instâncias de classe são objetos. Mesmo os módulos são objetos.
Indentação de código
As funções Python não têm begin
ou explícito end
e nem chaves para marcar onde o código da função começa e termina. O único delimitador é dois pontos (:
) e o recuo do próprio código.
def tamanho_aproximado(tamanho, um_kilobyte_eh_1024_bytes=True): ①
if tamanho < 0: ②
raise ValueError('O número não deve ser negativo') ③
④
multiplo = 1024 if um_kilobyte_eh_1024_bytes else 1000
for sufixo in SUFIXOS[multiplo]: ⑤
tamanho /= multiplo
if tamanho < multiplo:
return '{0:.1f} {1}'.format(tamanho, sufixo)
raise ValueError('numero muito longo')
-
Os blocos de código são definidos por sua indentação. Por “bloco de código”, quero dizer funções, instruções
if
, loopsfor
, loopswhile
e assim por diante. A indentação inicia um bloco e a desindentação o finaliza. Não há chaves, colchetes ou palavras-chave explícitas. Isso significa que o espaço em branco é significativo e deve ser consistente. Neste exemplo, o código da função tem quatro espaços indentados. Não precisa ter quatro espaços, só precisa ser consistente. A primeira linha sem recuo marca o fim da função. -
Em Python, uma instrução
if
é seguida por um bloco de código. Se a instruçãoif
for avaliada como verdadeira, o bloco recuado é executado, caso contrário, cai para o blocoelse
(se houver). Observe a falta de parênteses ao redor da expressão. -
Esta linha está dentro do bloco de código
if
. Esta instruçãoraise
gerará uma exceção (do tipoValueError
), mas somente setamanho < 0
. -
Este não é o fim da função. Linhas completamente em branco não contam. Eles podem tornar o código mais legível, mas não contam como delimitadores de bloco de código. A função continua na próxima linha.
-
O loop
for
também marca o início de um bloco de código. Os blocos de código podem conter várias linhas, desde que todos tenham o mesmo recuo. Este loopfor
contém três linhas de código. Não há nenhuma outra sintaxe especial para blocos de código de várias linhas. Apenas recue e continue com sua vida.
Depois de alguns protestos iniciais e várias analogias maliciosas com o Fortran, você fará as pazes com isso e começará a ver seus benefícios. Um grande benefício é que todos os programas Python são semelhantes, já que o recuo é um requisito da linguagem e não uma questão de estilo. Isso torna mais fácil ler e entender o código Python de outras pessoas.
Observação
Python usa retornos de carro para separar instruções e dois pontos e indentação para separar blocos de código. C++ e Java usam ponto-e-vírgula para separar instruções e chaves para separar blocos de código.
Exceções
As exceções estão em todos os lugares em Python. Praticamente todos os módulos da biblioteca Python padrão os usam, e o próprio Python os criará em muitas circunstâncias diferentes. Você os verá repetidamente ao longo deste livro.
O que é uma exceção? Normalmente é um erro, uma indicação de que algo deu errado. (Nem todas as exceções são erros, mas não importa por enquanto). Algumas linguagens de programação incentivam o uso de códigos de retorno de erro, que você verifica. Python incentiva o uso de exceções, com as quais você lida.
Quando ocorre um erro no Python Shell, ele imprime alguns detalhes sobre a exceção e como ela aconteceu, e pronto. Isso é chamado de exceção não tratada. Quando a exceção foi levantada, não havia código para notá-la explicitamente e lidar com ela, então ela borbulhou seu caminho de volta ao nível superior do Python Shell, que cospe algumas informações de depuração e o encerrou. No shell, isso não é grande coisa, mas se isso acontecesse enquanto seu programa Python real estivesse em execução, todo o programa iria parar bruscamente se nada tratasse da exceção. Talvez seja isso que você queira, talvez não.
Observação
Ao contrário do Java, as funções Python não declaram quais exceções podem gerar. Depende de você determinar quais possíveis exceções você precisa detectar.
No entanto, uma exceção não precisa resultar em um travamento completo do programa. As exceções podem ser tratadas. Às vezes, uma exceção é realmente porque você tem um bug em seu código (como acessar uma variável que não existe), mas às vezes uma exceção é algo que você pode antecipar. Se você estiver abrindo um arquivo, ele pode não existir. Se você estiver importando um módulo, ele pode não estar instalado. Se você estiver se conectando a um banco de dados, ele pode não estar disponível ou você pode não ter as credenciais de segurança corretas para acessá-lo. Se você sabe que uma linha de código pode gerar uma exceção, deve tratar a exceção usando um bloco try...except
.
Observação
Python usa blocos try...except
para lidar com exceções e a instrução raise
para gerá-las. Java e C++ usam blocos try...catch
para lidar com exceções e a instrução throw
para gerá-los.
A função tamanho_aproximado()
levanta exceções em dois casos diferentes: se o tamanho
fornecido for maior do que a função foi projetada para lidar ou se for menor que zero.
if tamanho < 0:
raise ValueError('O número não deve ser negativo')
A sintaxe para gerar uma exceção é bastante simples. Use a instrução raise
, seguida pelo nome da exceção e uma string opcional legível para fins de depuração. A sintaxe lembra a chamada de uma função. (Na realidade, as exceções são implementadas como classes, e essa instrução raise
está, na verdade, criando uma instância da classe ValueError
e passando a string 'O número não deve ser negativo'
para seu método de inicialização. Mas estamos nos adiantando!)
Observação
Você não precisa lidar com uma exceção na função que a gera. Se uma função não lida com isso, a exceção é passada para a função de chamada, a função de chamada dessa função e assim por diante "na pilha". Se a exceção nunca for tratada, seu programa irá travar, o Python imprimirá um “traceback” para o erro padrão e ponto final. Novamente, talvez seja isso que você deseja; depende do que seu programa faz.
Captura de erros de importação
Uma das exceções integradas do Python é ImportError
, que é gerada quando você tenta importar um módulo e falha. Isso pode acontecer por vários motivos, mas o caso mais simples é quando o módulo não existe em seu caminho de pesquisa de importação. Você pode usar isso para incluir recursos opcionais em seu programa. Por exemplo, a biblioteca chardet
fornece detecção automática de codificação de caracteres. Talvez o seu programa queira usar esta biblioteca, se ela existir, mas continue normalmente se o usuário não a tiver instalado. Você pode fazer isso com um bloco try..except
.
try:
import chardet
except ImportError:
chardet = None
Posteriormente, você pode verificar a presença do módulo chardet
com uma instrução if
simples:
if chardet:
# faça algo
else:
# continue de qualquer jeito
Outro uso comum da exceção ImportError
é quando dois módulos implementam uma API comum, mas um é mais desejável do que o outro. (Talvez seja mais rápido ou use menos memória). Você pode tentar importar um módulo, mas voltar para um módulo diferente se a primeira importação falhar. Por exemplo, o capítulo XML fala sobre dois módulos que implementam uma API comum, chamada API ElementTree
. O primeiro lxml
é um módulo de terceiros que você precisa fazer o download e instalar por conta própria. O segundo, xml.etree.ElementTree
é mais lento, mas faz parte da biblioteca padrão do Python 3.
try:
from lxml import etree
except ImportError:
import xml.etree.ElementTree as etree
Ao final deste try..except
bloco, você importou algum módulo e o nomeou etree
. Uma vez que ambos os módulos implementam uma API comum , o resto do seu código não precisa ficar verificando qual módulo foi importado. E uma vez que o módulo que foi importado é sempre chamado de etree
, o resto do seu código não precisa estar cheio de if
instruções para chamar módulos com nomes diferentes.
Variáveis não definidas
Dê uma outra olhada nesta linha de código da função tamanho_aproximado()
:
multiplo = 1024 if um_kilobyte_eh_1024_bytes else 1000
Você nunca declara a variável multiplo
, apenas atribuiu um valor a ela. Tudo bem, porque Python permite que você faça isso. O que Python não vai permitirá que você faça referência a uma variável à qual nunca foi atribuído um valor. Tentar fazer isso gerará uma exceção NameError
.
>>> x
Traceback (most recent call last):
File "<stdin≷", line 1, in <module≷
NameError: name 'x' is not defined
>>> x = 1
>>> x
1
Você vai agradecer ao Python por isso um dia.
Tudo diferencia maiúsculas de minúsculas
Todos os nomes em Python diferenciam maiúsculas de minúsculas: nomes de variáveis, nomes de funções, nomes de classes, nomes de módulos, nomes de exceções. Se você puder obtê-lo, configurá-lo, chamá-lo, construí-lo, importá-lo ou aumentá-lo, ele diferencia maiúsculas de minúsculas.
≷≷≷ um_inteiro = 1
≷≷≷ um_inteiro
1
≷≷≷ UM_INTEIRO
Traceback (most recent call last):
File "<stdin≷", line 1, in <module≷
NameError: name 'UM_INTEIRO' is not defined
≷≷≷ Um_Inteiro
Traceback (most recent call last):
File "<stdin≷", line 1, in <module≷
NameError: name 'Um_Inteiro' is not defined
≷≷≷ um_inTeiro
Traceback (most recent call last):
File "<stdin≷", line 1, in <module≷
NameError: name 'um_inTeiro' is not defined
E assim por diante.
Executando Scripts
Tudo em Python é um objeto.
Módulos Python são objetos e têm vários atributos úteis. Você pode usar isso para testar facilmente seus módulos à medida que os escreve, incluindo um bloco especial de código que é executado quando você executa o arquivo Python na linha de comando. Pegue as últimas linhas de teste.py
:
if __name__ == '__main__':
print(tamanho_aproximado(1000000000000, False))
print(tamanho_aproximado(1000000000000))
Observação
Como C, Python usa ==
para comparação e =
para atribuição. Ao contrário de C, Python não oferece suporte para atribuição in-line, portanto, não há chance de atribuir acidentalmente o valor que você pensou que estava comparando.
Então, o que torna esta declaração if
especial? Bem, os módulos são objetos e todos os módulos têm um atributo __name__
embutido. Um módulo __name__
depende de como você está usando o módulo. Se você for importar o módulo, então __name__
será o nome do arquivo do módulo, sem um caminho de diretório ou extensão de arquivo.
>>> import teste
>>> teste.__name__
'teste'
Mas você também pode executar o módulo diretamente como um programa independente; nesse caso __name__
, será um valor padrão especial: __main__
. Python avaliará essa instrução if
, encontrará uma expressão verdadeira e executará o bloco de código if
. Neste caso, para imprimir dois valores.
c:\home\diveintopython3> c:\python31\python.exe humansize.py 1.0 TB 931.3 GiB
E esse é o seu primeiro programa Python!
Leitura Adicional
-
PEP 257: Docstring Conventions explica o que distingue uma boa
docstring
de um excelentedocstring
. - Python Tutorial: Documentation Strings também aborda o assunto.
- PEP 8: Guia de estilo para código Python discute um bom estilo de indentação.
- O Manual de Referência do Python explica o que significa dizer que tudo em Python é um objeto, porque algumas pessoas são pedantes e gostam de discutir esse tipo de coisa longamente.
Esse artigo é uma tradução de um capítulo do livro "Dive Into Python 3" escrito por Mark Pilgrim. Você pode ler o livro desde o início em português clicando aqui.
Traduzido por Acervo Lima. O original pode ser acessado aqui.
0 comentários:
Postar um comentário