<jupyter_start><jupyter_text>Neste notebook, vamos ver como realizar operações matemáticas básicas, como importar bibliotecas para realizar comandos mais específicos a cada domínio, e vamos estudar um pouco da sintaxe básica da linguagem e conceitos de programação.É claro que não será um tratamento exaustivo da linguagem; estudaremos estes conceitos durante todo o curso, e também veremos outras estruturas mais avançadas conforme houver necessidade para a resolução dos nossos problemas.  Variáveis e Operações Matemáticas BásicasAntes de tudo, o interpretador Python pode ser visto como uma calculadora:<jupyter_code>a = 1
b = 7
print(a+b)<jupyter_output>8<jupyter_text>(Observe que podemos incluir várias linhas em uma mesma célula em um Notebook, usando a tecla ENTER. Para executar uma célula e passar para a próxima, usamos SHIFT+ENTER) As variáveis não precisam ser "declaradas" em Python, e seu tipo não é fixo.<jupyter_code>a = 1
print(a)
type(a)<jupyter_output><empty_output><jupyter_text>A variável `a` é tratada como um número inteiro, já que atribuimos a ela o valor 1. No entanto, se fizermos<jupyter_code>a = "Teste"
print(a)
type(a)<jupyter_output><empty_output><jupyter_text>Vemos que o tipo da variável `a` mudou sem que nenhum aviso fosse dado. É preciso ficar atento e não reutilizar nomes de variável no mesmo notebook, a não ser que saibamos muito bem o que estamos fazendo! Observe que as variáveis são criadas no momento em que atribuimos um valor a elas (não antes):<jupyter_code>print(c)<jupyter_output><empty_output><jupyter_text>As operações matemáticas estão bem definidas:<jupyter_code>a = 5
b = 2
a+b
a-b
b-a
b*a
b**a
b/a<jupyter_output><empty_output><jupyter_text>Atenção: o Python converteu automaticamente os números (que eram inteiros) em números reais, para que a divisão pudesse ser realizada. A divisão só se comporta assim no Python 3 (no Python 2, essa conversão não é automática). Veja mais sobre isso abaixo.  Tipos básicos de variáveisAs variáveis criadas acima eram todas numéricas, porém podemos criar variáveis de tipos diferentes no Python.  InteirosUma variável que é inicializada com um número inteiro, e que sofre apenas modificações que preservam a natureza de um número inteiro, é assim considerada pelo Python.<jupyter_code>1+2
abs(-1)
a=1
a+2<jupyter_output><empty_output><jupyter_text>A função `type` nos informa que tipo de objeto temos em mãos:<jupyter_code>type(a+2)<jupyter_output><empty_output><jupyter_text>Nesse caso, `a+2` é um objeto do tipo `int`, ou um número inteiro.  Reais (ponto flutuante) Podemos representar números reais (racionais ou irracionais) através da notação usual:<jupyter_code>3.1
3.1+4.5<jupyter_output><empty_output><jupyter_text>Quando necessário (e sempre que possível) o Python *converte* números para que o resultado final da operação seja realizado:<jupyter_code>1+3.2
1/2<jupyter_output><empty_output><jupyter_text>**Observação**: devemos ter em mente que números em ponto flutuante são, por natureza, inexatos. Isso significa que quando realizamos operações aritméticas com esses números, os erros podem se acumular  (e então teremos erros de arredondamento, overflow, underflow...) [Aqui você pode assistir a um bom vídeo sobre números em ponto flutuante.](https://www.youtube.com/watch?v=PZRI1IfStY0)  Strings (sequências de caracteres)Para tratarmos palavras, frases e outras sequências de caracteres, usamos aspas (simples ou duplas):<jupyter_code>palavra = "<NAME>"
print(palavra)
type(palavra)<jupyter_output><empty_output><jupyter_text>As strings, como chamamos estas sequências de caracteres, são tratadas pelo Python como *objetos*. (Na realidade, todos os tipos de dados em Python podem ser vistos como objetos! Discutiremos isso mais à frente.)Para entender o que podemos fazer com estes objetos, usamos<jupyter_code>dir(palavra)<jupyter_output><empty_output><jupyter_text>O que aparece na *lista* acima são ações que podemos aplicar a objetos do tipo string; chamamos essas ações de **métodos**. Para aplicarmos algum desses métodos à variável `palavra`, vamos usar a seguinte sintaxe:<jupyter_code>palavra.capitalize()
palavra.upper()<jupyter_output><empty_output><jupyter_text>Observe que na célula anterior, a aplicação do método `upper` à string `palavra` não modificou a string original:<jupyter_code>palavra
palavra.islower()<jupyter_output><empty_output><jupyter_text>O valor da célula acima surpreendeu você? O que você acha que isso significa? Para sobrescrevermos o novo valor à variável `palavra`, usamos<jupyter_code>palavra = palavra.upper()
palavra
palavra.islower()<jupyter_output><empty_output><jupyter_text>Podemos chamar métodos de maneira encadeada:<jupyter_code>palavra.lower().isupper()<jupyter_output><empty_output><jupyter_text>Em Python, diferenciamos entre métodos, que são aplicados a objetos (sempre da forma `objeto.metodo()`) e funções, que tem a forma `funcao(argumento)` e que costumam poder ser aplicadas a mais de um tipo de objetos.<jupyter_code>print(palavra.upper())<jupyter_output><NAME><jupyter_text>Podemos descobrir quantos caracteres estão na string `palavra`, usando a função `len`<jupyter_code>len(palavra)<jupyter_output><empty_output><jupyter_text>(Para uma explicação de por que usamos uma função `len` ao invés de um método, veja http://lucumr.pocoo.org/2011/7/9/python-and-pola/) Se já sabemos o nome do método que desejamos usar, podemos obter mais informações sobre ele usando a função `help`:<jupyter_code>help(palavra.split)<jupyter_output>Help on built-in function split:

split(...) method of builtins.str instance
    S.split(sep=None, maxsplit=-1) -> list of strings
    
    Return a list of the words in S, using sep as the
    delimiter string.  If maxsplit is given, at most maxsplit
    splits are done. If sep is not specified or is None, any
    whitespace string is a separator and empty strings are
    removed from the result.<jupyter_text>ou (no IPython ou num kernel do Jupyter) usando a sintaxe<jupyter_code>palavra.split?<jupyter_output><empty_output><jupyter_text>O resultado do método split é uma **lista** de strings:<jupyter_code>palavra.split()<jupyter_output><empty_output><jupyter_text>Se quisermos separar palavras usando outros caracteres que não sejam o espaço (*whitespace*), podemos indicar qual separador a ser usado:<jupyter_code>minhafrase = "Nome: dois pontos"
minhafrase.split()
minhafrase.split(sep=":")
minhafrase.split(sep=" ")<jupyter_output><empty_output><jupyter_text>Na verdade, uma string pode ser pensada como uma lista de letras; assim, podemos acessar cada letra separadamente, como um dos itens dessa lista. (No Python, o primeiro elemento de uma lista tem índice 0)<jupyter_code>minhafrase[2]<jupyter_output><empty_output><jupyter_text>No entanto, uma lista é um tipo de objeto distinto em Python. Podemos transformar uma string em uma lista através da função `list`:<jupyter_code>list(minhafrase)<jupyter_output><empty_output><jupyter_text>Exemplo<jupyter_code>frase = "O dia está lindo!"<jupyter_output><empty_output><jupyter_text>O método `rstrip`, associado a uma string, remove o caracter escolhido pelo usuário do final da string.<jupyter_code>frase = frase.rstrip("!")
frase
pedacos = frase.split()
print(pedacos)<jupyter_output>['O', 'dia', 'está', 'lindo']
{'fraction_non_alphanumeric': 0.07935634713244395, 'fraction_numerical': 0.00522624123229267, 'mean_word_length': 6.606694560669456, 'pattern_counts': {'":': 1, '<': 99, '<?xml version=': 0, '>': 100, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '25', 'dir': 'jupyter-structured-clean-dedup', 'id': '254320', 'license': 'MIT', 'n_tokens_mistral': 2636, 'n_tokens_neox': 2582, 'n_words': 829, 'path': 'content/pt_br/Notebook 02 - Primeiros comandos.ipynb', 'repo_name': 'mauriciolanda4/callicore', 'size': '7281'}