Introdução parte 2
Script - pega vários nomes e coloca numa lista
nomes = []
while True:
print('Entre com o nome', str(len(nomes) + 1), '- Aperte enter sem nada para parar')
pega_nome = input()
if pega_nome == '':
break
nomes += [pega_nome] # cincatenação de lista
print('Os nomes são:')
for nome_lista in nomes:
print(' ' + nome_lista)
Script - Verifica se o convidado foi cadastrado
É usado NOME in lista_ARRAY
para retornar true
ou false
, vê se o nome esta lá, o not
é o inverso.
convidados = ['joao','rodrigo','felipe','fabiano','marcia']
print ("Ve se o convidado está cadastrado.\n")
nome_conv = input("Digite o nome do convidado: ")
if nome_conv not in convidados:
print("\nConvidado não cadastrado -",nome_conv)
else:
print("\nConvidado cadastrado -",nome_conv)
Fazendo slicing e concatenação para criar uma nova string
name = 'Zophie a cat'
print(name[0:7])
# 'Zophie '
print(name[8:12])
# ' cat'
print(name[0:7] + 'the' + name[8:12])
# Zophie the cat
TYPE
Podemos ver qual o tipo de objeto é o dado:
num = '42'
type(num)
# <class 'str'>
num = 42
type(num)
# <class 'int'>
dict = {'key1': 'value1', 'key2': 'value2'}
type(dict)
# <class 'dict'>
DIR
Ao passar o objeto para o dir
, ele nos informa uma lista com os atributos e métodos desse objeto, ou seja, ele nos informa as funções, módulos, strings, listas, dicionários e muito mais.
# Por exemplo, sabemos um dicionário nós temos 3 módulos básicos para trabalhar, são eles: keys, items e values.
# Vamos ver na prática:
print(dir(dict))
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'clear', 'copy', 'fromkeys', 'get', 'items', 'keys', 'pop', 'popitem', 'setdefault', 'update', 'values']
# Aqui podemos ver os módulos que citamos e muito mais.
# Listando os atributos de listas:
print(dir(list))
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
Função HASATTR
Usado para verificar se um objeto possui um atributo:
# Olhando a função keys() de dicionarios:
>>> hasattr(dict, "keys")
True
# Não pode usar os '()':
>>> hasattr(dict, "keys()")
False
# Olhando a função items() de dicionarios:
>>> hasattr(dict, "items")
True
Método list() - Convertendo tupla em lista
lista_tupla = ('ola', 'oie')
list(lista_tupla)
# ['ola', 'oie']
Método copy() - Copiando valores
import copy
lista2 = copy.copy(lista1)
# Faz uma cópia de algo mutável e não faz apenas uma referencia.
Dicionario
O dicionário (dictionary) é uma coleção de diversos valores baseados em <chave>: <valor>
. Sua forma é idêntica ao json
, então muitos preferem trabalhar com dicionários sempre que possível.
## Criando um dicionário simples:
dicionario = {'size': 'fat', 'dia': 'feio'}
## Exibindo o valor da chave 'size':
print(dicionario['size'])
# fat
## Exibindo o valor da chave 'dia':
print(dicionario['dia'])
# feio
# Adicionando uma chave com valor no dicionário?
dicionario['rodrigo'] = '36 tim' # rodrigo é a chave e '36 tim' é o valor
Verificando se uma chave existe no dicionário
## Criando um dicionário simples:
dicionario = {'size': 'fat', 'dia': 'feio'}
if 'size' in dicionario:
print('A chave existe!')
else:
print('A chave não existe!')
## Para verificar se não existe:
if 'size' not in dicionario:
print('A chave não existe!')
else:
print('A chave existe!')
Nós também podemos ter dicionários aninhados, que nada mais são do que dicionários dentro de dicionários.
#################################
# Estrutura #
#################################
<var_name> = {
'chave': {'chave': 'valor'},
'chave': {'chave': 'valor'},
}
## Criando um dicionário aninhado:
dicionario = {
'1': {'size': 'fat', 'dia': 'feio'},
'2': {'comida': 'Arroz e feijão', 'bebida': 'agua'}
}
print(dicionario['1'])
# {'size': 'fat', 'dia': 'feio'}
print(dicionario['2'])
# {'comida': 'Arroz e feijão', 'bebida': 'agua'}
print(dicionario['2']['bebida'])
# agua
Método values()
Usado para retornar apenas os valores:
dicionario = {'size': 'fat', 'dia': 'feio'}
print(dicionario.values())
# dict_values(['fat', 'feio'])
Método keys()
Usado para ver apenas as chaves do dicionário:
dicionario = {'size': 'fat', 'dia': 'feio'}
print(dicionario.keys())
# dict_keys(['size', 'dia'])
Método setdefault()
Usado para definir um valor para uma chave caso ela não exista:
dicionario = {'size': 'fat', 'dia': 'feio'}
## Se a chave 'noite' não existir, vamos definir seu valor para 'escura':
dicionario.setdefault('noite', 'escura')
print(dicionario)
# {'size': 'fat', 'dia': 'feio', 'noite': 'escura'}
Método items()
Usado para ver chave e valor:
dicionario = {'size': 'fat', 'dia': 'feio'}
print(dicionario.items())
# dict_items([('size', 'fat'), ('dia', 'feio')])
Método clear()
Usado para limpar o dicionário, apagando todos os seus valores:
dicionario = {'size': 'fat', 'dia': 'feio'}
## Limpando o dicionário:
dicionario.clear()
print(dicionario)
# {}
Método get()
Usado para retornar um o valor baseado na chave (igual a usar o colchetes como em print(dicionario['size'])
):
dicionario = {'size': 'fat', 'dia': 'feio'}
dicionario.get('dia')
# 'feio'
Remover uma chave e valor
Para remover uma chave e o valor de um dicionário, podemos usar:
meu_dict = {"nome": "Fulano", "idade": 27}
# Deletar:
del meu_dict["idade"]
print(meu_dict)
Virtual Env
O conceito de ambiente virtual, conhecido como virtualenv no Python, é uma funcionalidade essencial para manter os projetos isolados uns dos outros, evitando conflitos entre dependências e versões de pacotes.
Quando você cria um ambiente virtual, está estabelecendo uma área separada do sistema principal onde o Python executa com seu próprio conjunto de bibliotecas. Isso significa que, dentro desse ambiente, você pode instalar pacotes com pip
que não afetarão o restante do sistema e tampouco serão afetados por outras instalações globais ou de outros projetos.
O principal objetivo disso é garantir reprodutibilidade e controle de versões. Por exemplo, um projeto pode depender do Flask==1.1.2
, enquanto outro pode exigir Flask==2.0.0
, e ambos funcionarão corretamente se estiverem em ambientes virtuais separados.
A criação de um ambiente virtual geralmente é feita com o módulo venv
, que está disponível nativamente a partir do Python 3.3. O comando python3 -m venv nome_do_ambiente
cria a estrutura básica do ambiente. Ao ser ativado com source nome_do_ambiente/bin/activate
no Linux ou macOS, ou nome_do_ambiente\Scripts\activate.bat
no Windows, o shell passa a usar os executáveis e bibliotecas daquele ambiente ao invés do sistema principal.
É possível verificar isso ao rodar which python
ou where python
, que apontará para o diretório interno do virtualenv.
Quando o ambiente está ativo, você pode instalar pacotes com pip
e eles ficarão disponíveis apenas naquele ambiente. Isso é útil inclusive para gerar arquivos requirements.txt
, que listam exatamente os pacotes e versões instaladas, permitindo que outros desenvolvedores repliquem o mesmo ambiente com pip install -r requirements.txt
.
A desativação do ambiente é feita com o comando deactivate
, que restaura o ambiente global do sistema. Durante a ativação, variáveis de ambiente como PATH
e VIRTUAL_ENV
são alteradas temporariamente, e tudo isso é revertido com a desativação.
Além do venv
, existe também o virtualenv
, um projeto externo que funciona de maneira parecida mas oferece mais opções e compatibilidade com versões mais antigas do Python. No entanto, para projetos modernos com Python 3, o venv
é suficiente e amplamente recomendado.
Criando um ambiente virtual
No terminal, vá até o diretório onde deseja criar seu projeto e digite:
# Criando o ambiente virtual:
$ python3 -m venv projeto1
$ ls -l projeto1
total 16
drwxrwxr-x 2 Fulano Fulano 4096 Jun 19 19:32 bin
drwxrwxr-x 3 Fulano Fulano 4096 Jun 19 19:32 include
drwxrwxr-x 3 Fulano Fulano 4096 Jun 19 19:32 lib
lrwxrwxrwx 1 Fulano Fulano 3 Jun 19 19:32 lib64 -> lib
-rw-rw-r-- 1 Fulano Fulano 159 Jun 19 19:32 pyvenv.cfg
A ativação depende do sistema operacional.
# No Linux/macOS:
source projeto1/bin/activate
# No Windows (cmd.exe):
projeto1\Scripts\activate.bat
# No Windows (PowerShell):
projeto1\Scripts\Activate.ps1
Se quiser compartilhar os pacotes usados em seu projeto, gere um arquivo com a lista deles:
$ pip freeze > requirements.txt
# Para restaurar o ambiente em outra máquina ou instalação:
$ pip install -r requirements.txt
Set
O set
é uma estrutura de dados embutida que representa um conjunto, ou seja, uma coleção não ordenada de elementos únicos e mutáveis. Isso significa que não há elementos repetidos e que você pode adicionar ou remover elementos, mas não acessar diretamente pelo índice (como em listas ou tuplas).
Criando um set vazio:
empty_set = set()
Você pode criar um set
de duas formas: usando a função set()
ou com chaves {}
(desde que não esteja criando um dicionário). Exemplo com set()
:
s = set([1, 2, 3, 3, 2])
print(s) # saída: {1, 2, 3}
Exemplo com {}
:
s = {1, 2, 3, 3}
print(s) # saída: {1, 2, 3}
Note que os elementos duplicados são automaticamente removidos. Você também pode adicionar elementos com add()
:
s = {1, 2, 3}
s.add(4)
print(s) # {1, 2, 3, 4}
E remover com remove()
(que dá erro se não existir) ou discard()
(que não dá erro):
s.remove(2) # remove o 2
s.discard(5) # não faz nada, pois 5 não está no conjunto
Também é possível fazer operações matemáticas de conjuntos, como união, interseção e diferença:
a = {1, 2, 3}
b = {3, 4, 5}
print(a | b) # união: {1, 2, 3, 4, 5}
print(a & b) # interseção: {3}
print(a - b) # diferença: {1, 2}
print(a ^ b) # diferença simétrica: {1, 2, 4, 5}
Sets não aceitam elementos mutáveis, como listas ou dicionários:
s = { [1, 2, 3] } # isso dá erro: TypeError: unhashable type: 'list'
Mas tuplas podem ser usadas se contiverem apenas elementos imutáveis:
s = { (1, 2), (3, 4) } # isso é válido
Se quiser um conjunto imutável, use frozenset
, que funciona da mesma forma que set
, mas não permite alterações.
fs = frozenset([1, 2, 3])
# fs.add(4) # isso gera erro
O set
é muito útil quando você precisa garantir unicidade (ser único) de elementos ou realizar comparações rápidas entre coleções.
Lambda
A função lambda
é uma forma compacta de criar funções anônimas, ou seja, funções sem nome, geralmente usadas quando você precisa de uma função simples, de uma única linha, e não quer escrever um def
.
A sintaxe é:
lambda argumentos: expressão
Ela retorna automaticamente o resultado da expressão. Não pode ter mais de uma linha, nem comandos como if
, for
, print
, etc. a não ser que estejam dentro da própria expressão. Por exemplo:
soma = lambda x, y: x + y
print(soma(3, 4)) # 7
Isso é equivalente a:
def soma(x, y):
return x + y
O lambda
é muito usado quando você precisa passar uma função como argumento, como em sorted()
, map()
, filter()
, reduce()
:
numeros = [5, 2, 8, 1]
ordenado = sorted(numeros, key=lambda x: x) # aqui não muda nada
Com mais sentido:
nomes = ['ana', 'Fulano', 'Carlos']
ordenado = sorted(nomes, key=lambda nome: nome.lower())
print(ordenado) # ['ana', 'Fulano', 'Carlos']
Ou com map()
:
valores = [1, 2, 3]
dobrados = list(map(lambda x: x * 2, valores))
print(dobrados) # [2, 4, 6]
Apesar de útil, o lambda
não substitui funções normais. Ele é bom apenas para expressões simples e de uso rápido. Se o código ficar muito grande ou confuso, o ideal é usar def
com nome e blocos explícitos.
É muito comum você ter uma lista de dicionários e quer ordená-la com base em um dos campos internos de cada dicionário. O lambda
é ideal para isso porque permite acessar diretamente a chave que você quer usar na ordenação.
Exemplo:
pessoas = [
{"nome": "Fulano", "idade": 27},
{"nome": "Ana", "idade": 23},
{"nome": "Carlos", "idade": 30}
]
Se quiser ordenar por idade:
ordenado = sorted(pessoas, key=lambda pessoa: pessoa["idade"])
Resultado:
[
{'nome': 'Ana', 'idade': 23},
{'nome': 'Fulano', 'idade': 27},
{'nome': 'Carlos', 'idade': 30}
]
Se quiser ordenar por nome:
ordenado = sorted(pessoas, key=lambda pessoa: pessoa["nome"])
E se quiser em ordem decrescente:
ordenado = sorted(pessoas, key=lambda pessoa: pessoa["idade"], reverse=True)
O lambda
aqui está dizendo ao sorted()
qual valor deve ser comparado entre os dicionários. Ele é extremamente útil nesse tipo de caso, evitando a criação de uma função separada só para isso.
Args e Kwargs
O *args
e **kwargs
são usados para permitir que uma função receba um número variável de argumentos. Eles são muito úteis quando você não sabe exatamente quantos argumentos serão passados, ou quando quer dar flexibilidade à função para lidar com chamadas diferentes.
*args
O *args
permite receber vários argumentos posicionais como uma tupla.
def somar(*args):
return sum(args)
print(somar(1, 2, 3)) # 6
print(somar(10, 20)) # 30
print(somar()) # 0
Aqui, args
vira uma tupla com todos os valores passados. Você pode iterar sobre ela, somar, multiplicar etc.
**kwargs
O **kwargs
permite receber vários argumentos nomeados (chave=valor), armazenando-os em um dicionário.
def mostrar_dados(**kwargs):
for chave, valor in kwargs.items():
print(f"{chave}: {valor}")
mostrar_dados(nome="Fulano", idade=27, cidade="SP")
Saída:
nome: Fulano
idade: 27
cidade: SP
Expansão de listas e dicionários
Você também pode usar *
e **
ao chamar funções, para desempacotar valores:
def saudacao(nome, idade):
print(f"Olá {nome}, você tem {idade} anos.")
dados = {"nome": "Ana", "idade": 25}
saudacao(**dados)
Ou:
valores = [1, 2, 3]
print(sum(*[valores])) # sum(1, 2, 3) -> 6
Quando você usa *
ou **
ao chamar uma função, não está definindo a função, e sim dizendo: pegue os valores dentro dessa lista ou dicionário e passe como argumentos separados para a função. Isso é chamado de desempacotamento.
Quando você usa *
, o Python pega cada item da sequência e passa como argumento individual para a função. Exemplo:
def somar(a, b, c):
return a + b + c
valores = [1, 2, 3]
print(somar(*valores)) # equivale a somar(1, 2, 3)
Se você escrever
somar(valores)
sem o*
, o Python passaria uma lista só, que seria atribuida para variavela
, e daria erro porqueb
ec
ficariam faltando.
Já o **
funciona com dicionários e envia os pares chave=valor como argumentos nomeados.
def apresentar(nome, idade):
print(f"{nome} tem {idade} anos.")
dados = {"nome": "Fulano", "idade": 27}
apresentar(**dados) # equivale a apresentar(nome="Fulano", idade=27)
Se você escrever apresentar(dados)
, o Python tentaria passar um único argumento (o dicionário inteiro) para o primeiro parâmetro (nome
) e daria erro, porque idade
não seria preenchido.
Desempacotar com *
e **
é útil para passar argumentos dinamicamente, como quando você recebe dados prontos de outro lugar e precisa repassar para uma função.
isinstance
A função isinstance()
é usada para verificar se um valor ou objeto pertence a um tipo específico (ou a uma tupla de tipos). Ela retorna True
se o objeto for do tipo indicado, e False
caso contrário.
A sintaxe é:
isinstance(objeto, tipo)
Por exemplo:
x = 5
print(isinstance(x, int)) # True
print(isinstance(x, float)) # False
Isso é útil quando você quer garantir que está lidando com o tipo certo antes de fazer alguma operação que depende disso:
def dobrar(valor):
if isinstance(valor, (int, float)):
return valor * 2
return None
Você pode passar uma tupla de tipos, e o isinstance
retorna True
se o objeto for de qualquer um deles:
print(isinstance(3.14, (int, float))) # True
print(isinstance("teste", (int, float))) # False
Se você estiver usando classes, isinstance()
também reconhece herança:
class Animal:
pass
class Gato(Animal):
pass
miau = Gato()
print(isinstance(miau, Gato)) # True
print(isinstance(miau, Animal)) # True
Isso acontece porque miau
é um Gato
, mas também é um Animal
por herança. O type()
só considera o tipo exato, já isinstance()
também considera herança.