ET Cetera

ET Cetera

Set

Um conjunto (set) é uma estrutura de dados que armazena elementos únicos e não ordenados. Ele é representado por chaves🔑 { } ou pela palavra set ( ) e não permite duplicatas, ou seja, cada elemento em um conjunto é único, bora ver um exemplo:

estudantes = [
    {"nome":"Harry","casa":"grifinória"},
    {"nome":"Hermione", "casa":"grifinória"},
    {"nome":"Draco", "casa":"sonserina"}
] #uma lista com dicionarios

def main():
    casas = set()  #set vazio
    for estudante in estudantes:
        casas.add(estudante["casa"])  #adiciona a casa para o set
    print(type(casas))  #mostra o tipo
    print(casas)

if __name__ == "__main__":
    main()
<class 'set'>
{'grifinória', 'sonserina'}
💡
Conjuntos são úteis quando precisamos lidar com coleções de elementos e não nos importamos com a ordem em que estão armazenados.

Global

A palavra global é utilizada para indicar que uma variável está sendo referenciada no escopo global, ou seja, fora de uma função, por padrão é considerada local a essa função. No entanto, se você precisa modificar uma variável global de dentro de uma função, vc deve usar a palavra-chave global para informar ao interpretador que a variável pertence ao escopo global, por exemplo:

saldo = 0

def main():
    print("Saldo:", saldo)
    deposito(100)
    saque(50)
    print("Saldo:", saldo)

def deposito(n):
    global saldo #sem 'global' não modifica o saldo
    saldo += n

def saque(n):
    global saldo
    saldo -= n

if __name__=="__main__":
    main()

Constantes

As constantes em python deveriam de ser imutáveis, mas elas são mutáveis, por que? não sei. Constantes em outras línguas de programação são imutáveis. Para representar uma constante (constant) escreve-se a variável toda em maiúscula, e ela serve como indicador para programadores, veja os exemplos 👇🏻:

MIADO = 3
MIADO = 4
for _ in range(MIADO):
    print("Miau")
#quantos miados mostrara?

Type Hints

👉🏻 Type Hints ou "tipos de dicas" são anotações opcionais que você pode adicionar ao código para indicar o tipo de dados que uma variável espera ou que uma função retorna. Essas anotações não afetam o comportamento do programa em tempo de execução, mas fornecem informações úteis para desenvolvedores, documentar, ⚙️ ferramentas de análise estática e IDEs. A continuação utilizarei uma ferramenta de análise estática, chamada "mypy", para instalar é só:

pip install mypy

#nome do arquivo: meuarquivo.py

def miado(n: int):  # :int (dica)
    for _ in range(n):
        print("miau")

Nesse exemplo básico ☝🏻, observa-se a dica :int que indica que recebe como parâmetro um número inteiro e para usar a ferramenta mypy, desde o terminal usa-se : mypy meuarquivo.py

Outros tipos de dicas 👇🏻:

#nome do arquivo: meuarquivo.py

def miado(n: int) -> None:  # :int (dica)  -> None (dica)
    for _ in range(n):
        print("miau")

Neste código ☝🏻, -> None indica que retorna None (nada), porque a função esta fazendo um print e não retornando um valor.

def miado(n: int) -> str:
    return "miau\n" * n

Você está certo, -> str indica que retorna uma string (palavra), desta vez a função está retornando um valor e não fazendo print.

Docstrings

São string de 👉🏻 documentação incorporadas diretamente no código-fonte para descrever o propósito, funcionamento e uso de módulos, classes, funções ou métodos, bora ver alguns exemplos 👇🏻:

def miado(n: int) -> str:
    """ Mia n vezes """  #docstring
    return "miau\n" * n
def miado(n: int) -> str:
    """
    Mia n vezes
    :param n: Numero de vezes que mia
    :type n: int
    :raise TypeError: Se n não é um int
    :return : Uma string de n miados, um por linha
    :rtype : str
    """
    return "miau\n" * n

Essa template de documentação aqui não 🙅🏻‍♂️ é obrigatória, mas é muito usada por desenvolvedores ✅, é bom pegar essas dicas e fazer um hábito delas no seu código, pega visão! 🚀

Argparse

É um 👉🏻módulo padrão que facilita o processamento de argumentos da linha de comando, ou seja, ao usar o terminal. Ele fornece uma maneira flexível e poderosa de analisar argumentos passados quando um script é executado. Com o argparse é possível definir argumentos, opções e até mesmo argumento posicionais, associando valores a esses elementos. Ele gera mensagens de ajuda, tornando a utilização do script mais intuitiva para os usuários. bora ver uns exemplos👇🏻:

#nome do arquivo: meuarquivo.py
import sys

if len(sys.argv) == 1:
    print("E ai, blz?")
elif len(sys.argv) == 3 and sys.argv[1] == "-n":
    n = int(sys.argv[2])
    for _ in range(n):
        print("E ai, blz?")
else:
    print("Uso: arquivo.py")

Nesse exemplo não tem o uso do argparse ainda, mas normalmente o uso no terminal seria assim: python3 meuarquivo.py -n 3 o número pode ser qualquer número inteiro, que seria o número de vezes que mostrar a frase "E ai, blz?"

💡
Dica!! O uso de um traço ( - ) está associado à números, e o uso de dois traços ( -- ) está associado à palavras.

Bora usar o argparse e repare que ele vai facilitar a vida 🙌:

import argparse

parser = argparse.ArgumentParser(description="Comprimento Br")
parser.add_argument("-n", default=1,help="Número de vezes que comprimenta", type=int)
args = parser.parse_args() 

for _ in range(int(args.n)):
    print("E ai, blz?")

#arg.n contem um inteiro que é digitado depois do -n

Na documentação pode encontrar mais utilidades sobre argparse, mas nesse código, inicia o argparse com parser a opção description é opcional, mas serve para dar um título, depois no parser.add_argument é adicionado a funcionalidade utilizando a letra que quiser neste caso foi (-n), deixando default=1 como padrão caso não indique com o -n, em args é analisado o parser e tem o método .n para devolver um inteiro,o argparse vem com funções por padrão, como em qualquer outro módulo que usa argparse, mostrar um exemplo ao digitar errado ou pedir ajuda como comando --help:

usuario@terminal:~$ python3 meuarquivo.py --help
usage: teste.py [-h] [-n N]

Comprimento Br

options:
  -h, --help  show this help message and exit
  -n N        Número de vezes que comprimenta

Descompactar

Unpacking ou desempacotar 📦elementos de uma sequência (como uma lista, tupla ou dicionário) e atribuí-los a variáveis individuais de forma simultânea. Isso é feito usando a sintaxe de desempacotamento, sendo para tuplas as mais simples, bora ver exemplos 👇🏻:

# desempacotar tupla
first, _ = input("Qual é o seu nome:").split(" ")
print(f"Olá, {first}")

Este código ☝🏻irá pegar só o primeiro nome, por exemplo: João Careca 🧔🏻‍♂️

# desempacotar lista
def total(galeao, sicle, nuque):
    return (galeao * 17 + sicle) * 29 + nuque

def main():
    moedas = [100, 25, 12]
    print(total(*moedas), "nuques")  #desempacotar

if __name__ == "__main__":
    main()
# desempacotar dicionario
def total(galeao, sicle, nuque):
    return (galeao * 17 + sicle) * 29 + nuque

def main():
    moedas = {"galeao":100, "sicle":25, "nuque":72}
    print(total(**moedas), "nuques") #desempacotar

if __name__ == "__main__":
    main()

Perceba que para desempacotar uma lista basta usar um asterisco ( * ) e para desempacotar um dicionário basta usar dois asterisco ( ** )

💡
Para desempacotar ou descompactar, o número de itens numa lista ou dicionário devem de ser iguais ao parâmetros que a função pede.

Args / Kwargs

É o contrário de unpacking ou desempacotamento, não precisar ser esse nomes , *args ou **kwargs simplesmente foi estabelecido como acordo, *args significa que os parâmetros vão ser colocados ou compactados numa lista, e **kwargs num dicionário, veja os exemplos 👇🏻:

def por_lista(*args):
    print("Posição:", args)

por_lista(10,2,12,45,5,55,21,3,8)

> Posição: (10, 2, 12, 45, 5, 55, 21, 3, 8)

def por_dic(**kwargs):
    print("Posição: ", kwargs)

por_dic(dolar=100, ien=1500,real=5 , euro=15)

> Posição: {'dolar': 100, 'ien': 1500, 'real': 5, 'euro': 15}

Map

É uma 👉🏻função integrada que permite aplicar uma função a cada elemento de um iterável (como uma lista) e retorna um iterável com os resultados. A sintaxe básica é map(função, iterável) onde função é a função que você deseja aplicar e iterável é a sequência de dados a ser processada, bora ver um exemplo 👇🏻:

def main():
    yell(["Isto", "é","python","do", "zero","ao", "arrojado"])  #lista

def yell(palavras):
    maiuscula = []
    for palavra in palavras:
        maiuscula.append(palavra.upper())
    print(*maiuscula)

if __name__=="__main__":
    main()

Neste código ☝🏻convertemos cada palavra da lista em maiúscula criando uma função, agora veja o uso do map no mesmo contexto 👇🏻:

def main():
    yell("Isto", "é","python","do", "zero","ao", "arrojado") 

def yell(*palavras):
    maiusculas = map(str.upper, palavras)
    print(*maiusculas)

if __name__=="__main__":
    main()

Compreensão da lista

"List comprehension" é uma construção sintática que permite criar listar de maneira concisa e expressiva. Em outras palavras, uma forma mais compacta de escrever código que muito chamam de 💪🏻"Pythonista" ( o jeitinho python ), a continuação uma estrutura básica de construção 🚧 :

nova_lista = [expressao for elemento in iteravel]
def main():
    yell("Isto", "é","python","do", "zero","ao", "arrojado") 

def yell(*palavras):
    maiusculas = []
    for palavra in palavras:
        maiusculas.append(palavra.upper())
    print(*maiusculas)

if __name__=="__main__":
    main()

Neste exemplo , pode-se aplicar a compreensão da lista da seguinte forma 👇🏻:

def yell(*palavras):
    maiusculas = [palavra.upper() for palavra in palavras]
    print(*maiusculas)

Veja um outro exemplo utilizando validação dentro👇🏻:

estudantes = [
    {"nome":"harry", "casa":"grifinória"},
    {"nome":"draco", "casa":"sonserina"},
    {"nome": "ron", "casa":"grifinória"}
]

grifinoria = [
    estudante["nome"] for estudante in estudantes if estudante["casa"] == "grifinória"
]

Compreensão do Dicionário

"Dictionary comprehension" também é uma construção 🦺 sintática que permite criar um dicionário de maneira concisa e eficiente. Similar à list comprehension, a continuação uma estrutura básica de construção 🏗️ :

novo_dicionario = {chave: valor for elemento in iteravel}

Primeiro um exemplo do código sem a compreensão do dicionário e depois com:

# sem o dictionary comprehension
estudantes = ["hermione","harry", "ron"]

grifinoria = []
for estudante in estudantes:
    grifinoria.append({"nome":estudante, "casa":"grifinória"})
# com o dictionary comprehension
estudantes = ["hermione","harry", "ron"]

grifinoria = [{"nome":estudante, "casa":"grifinória"} for estudante in estudantes]

Geradores

👉🏻Generators (geradores) são estruturas que permitem a criação de iteradores de forma eficiente e econômica em termos de memória. Eles são definidos por funções que utilizam a palavra-chave yield para produzir valores de maneira preguiçosa 🥱, ou seja, gerando cada valor sob demanda, veja um exemplo sem o gerador e no final com o gerador:

def main():
    n = int(input("Valor para n:"))
    for contar in ovelha(n):
        print(contar)

def ovelha(n):
    rebanho = []
    for i in range(n):
        rebanho.append("🐑" * i)
    return rebanho

if __name__=="__main__":
    main()

Nesse exemplo: foi testado com valor de 15, 30 e 1000000 🤯

Valor para n:15

🐑
🐑🐑
🐑🐑🐑
🐑🐑🐑🐑
🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
Valor para n:30

🐑
🐑🐑
🐑🐑🐑
🐑🐑🐑🐑
🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑🐑
O valor de 1 milhão 😱 simplesmente parou o computador ! 
Não há capacidade para fazer tudo isso.

Agora o mesmo exemplo com o gerador 👇🏻:

def main():
    n = int(input("Valor para n:"))
    for contar in ovelha(n):
        print(contar)

def ovelha(n):
    for i in range(n):
        yield "🐑" * i  #uso do gerador

if __name__=="__main__":
    main()

Dessa vez ele da conta de fazer para 1 milhão, não acredita??? faz no seu computador 🫣. Por que acontece essa sobrecarga?, porque 🙄com o gerador, mostra o resultado por partes , segundo ele vai gerando a tarefa. Sem o gerador, ele mostra tudo ao mesmo tempo.