Bolhaverso

Reader

pt-br

Leia os posts do bolha.blog.

en-us

Read all posts from our users.

from orixás

Oxalá > Epa Babá

Logunan > Olha o tempo

Ogum > Ogunhê

Iansã > Eparrey Oyá

Oxóssi > Okê Aro

Xangô > Kao Cabecilê

Oxum > Ora Lê Lê Ô

Nanã > Saluba

Iemanjá > Odoyá

Omulu > Atotô

Oroiná > Kali-Yê

Obá > Akiro Obá Ié

Oxumaré > Arroboboi

Entidades de esquerda:

Exu/Pomba Gira > Laroyê Exu > Exu é Mojubá

Outras:

Pretos Velhos(as) > Adorei as almas

Caboclos(as) > Saravá Cabloco(a)! > Okê Caboclo(a)! > Okê Cabloco(a)! > Okê aro! > Marrumbá Xetru Caboclo, Xetruá!

Boiaderos(as) > Xetruá, seu Boiadeiro! > Marrumbá, Xetruá, Boiadeiros! > Saravá, meu Pai Boiadeiro!

Marinheiros(as) > Salve os Marinheiros! > Saravá os Navegantes! > Salve as Sete Ondas! > Salve a Marujada!

Baianos(as) > É da Bahia, meu Pai! > Salve os Baianos! > Saravá Bahia!

 
Read more...

from orixás

Este novo blog é para catalogar meus estudos sobre a Umbanda, nova doutrina que estudo.

[s] Guto

 
Read more...

from in.versos

Sei que amas as flores com as quais teus tantos amantes te presenteiam. E talvez te entristeças por eu não te enviá-las.

Mas flores, querida, morrem cedo. Já o meu amor por ti jaz eternizado nos versos que te dediquei.

 
Leia mais...

from Riverfount

A complexidade ciclomática mede o número de caminhos de execução independentes em uma função ou módulo Python, ajudando a identificar código difícil de testar e manter. Desenvolvida por Thomas J. McCabe em 1976, essa métrica é calculada como o número de pontos de decisão (if, for, while, etc.) mais um, revelando riscos em fluxos ramificados excessivos.

Mas o que é Complexidade Ciclomática?

Complexidade ciclomática (CC) quantifica a densidade de caminhos lógicos em um grafo de controle de fluxo. Em Python, cada estrutura condicional ou de loop adiciona ramificações: um if simples eleva a CC para 2, enquanto and/or em condições compostas multiplica caminhos independentes. A fórmula básica é CC = E - N + 2P, onde E são arestas, N nós e P componentes conectados, mas ferramentas como radon ou flake8 computam isso automaticamente.

E por que diminuir a CC importa para Pythonistas?

Código Python com CC alta (>10) aumenta o risco de bugs ocultos e eleva o custo de testes unitários para cobertura total. Funções longas com if-elif-else encadeados violam o Zen of Python (“Flat is better than nested”), complicando debugging em IDEs como PyCharm. Em microservices ou APIs Flask/FastAPI, CC elevada impacta deploy em Docker, pois refatorações viram gargalos em CI/CD.

Calculando CC em Código Python

Considere este exemplo problemático:

def processar_usuario(usuario, eh_admin=False, eh_pago=False):
    if not usuario:
        return None
    if eh_admin and eh_pago:
        return "acesso_total"
    elif eh_admin:
        return "acesso_admin"
    elif eh_pago:
        return "acesso_basico"
    else:
        if usuario.ativo:
            return "acesso_limitado"
        return "bloqueado"

Aqui, CC ≈ 6 devido a ramificações múltiplas. Use radon cc arquivo.py para medir:

processar_usuario: CC=6 (alto risco)

Interpretação e Limites Recomendados

Faixa de CC Nível de Risco Ação Sugerida
1-5 Baixo Manter como está
6-10 Moderado Refatorar se possível
11-20 Alto Dividir função imediatamente
>20 Crítico Refatoração urgente

Valores acima de 10 sinalizam antipadrões em Python, como god functions em Django views.

Estratégias de Redução em Python

  • Extraia funções puras: Divida em helpers como validar_usuario() e determinar_nivel_acesso().
  • Use polimorfismo: Substitua condicionais por classes com @dataclass ou Enum.
  • Guard clauses: Prefira if not condicao: return para early returns.
  • Strategy Pattern: Dicionários mapeiam condições a funções: handlers = {eh_admin: handler_admin}.
  • Ferramentas: Integre pylint ou mypy no pre-commit hook Git para alertas automáticos.

Exemplo refatorado (CC reduzida para 2):

def processar_usuario(usuario, eh_admin=False, eh_pago=False):
    if not usuario:
        return None
    return determinar_nivel_acesso(usuario.ativo, eh_admin, eh_pago)

def determinar_nivel_acesso(ativo, eh_admin, eh_pago):
    if eh_admin and eh_pago:
        return "acesso_total"
    handlers = {
        (eh_admin, eh_pago): "acesso_basico",
        eh_admin: "acesso_admin"
    }
    return handlers.get((eh_admin, eh_pago), "acesso_limitado" if ativo else "bloqueado")

Integração em Workflows Python

Em projetos com pytest, mire 100% branch coverage em funções CC<10. No VS Code, extensões como "Python Docstring Generator" ajudam na documentação pós-refatoração. Para equipes, thresholds no GitHub Actions bloqueiam merges com CC>15, alinhando com práticas DevOps em Kubernetes.

Monitore CC regularmente para código limpo e escalável em Python. Experimente radon no seu repo hoje e compartilhe comigo em @riverfount@bolha.us sua maior redução de CC!

 
Read more...

from in.versos

Ah, os doces sabores da vida.

Suaves, cítricos, florais, intensos, agridoces.

Sorrisos, olhares, abraços e lábios.

Lábios que beijam, sussurram e provocam.

Lábios vermelhos, lábios de Mell, Pablyne, sublimes.

Sabores que não precisam ser provados para se saber que são doçura, delícia e prazer.

 
Leia mais...

from Riverfount

Evitar números mágicos em expressões booleanas é uma recomendação explícita de linters Python modernos (como Pylint e Ruff, via regra PLR2004), pois esses valores dificultam a leitura e a manutenção do código. Entender essa regra e o contexto em que ela surgiu ajuda a justificar a prática ao time e a padronizar o estilo da base de código.

PLR2004: de onde vem essa regra?

A sigla PLR2004 é o identificador da regra magic-value-comparison em ferramentas de lint para Python, como o linter Ruff, que reutiliza a numeração herdada do Pylint. A regra é derivada diretamente da mensagem de refatoração R2004 – magic-value-comparison do Pylint, mantido pelo projeto PyCQA, que incentiva o uso de constantes nomeadas em vez de valores mágicos em comparações.

Na documentação do Ruff, a PLR2004 é descrita como uma verificação que detecta o uso de constantes numéricas “mágicas” em comparações, sugerindo substituí-las por variáveis constantes, justamente para melhorar legibilidade e manutenibilidade. A própria descrição enfatiza que o uso de valores mágicos é desencorajado pelas diretrizes de estilo PEP 8.

O que a PLR2004 considera um “magic value”

A regra PLR2004 inspeciona comparações como ==, !=, <, >, <= e >= em busca de literais numéricos sem nome, tratando-os como magic values quando representam algo além de números triviais. A documentação do Ruff destaca que esses valores tornam o código mais difícil de ler, pois o significado precisa ser inferido apenas pelo contexto, e recomenda o uso de constantes nomeadas.

Por conveniência, a regra costuma ignorar alguns valores muito comuns, como 0, 1 e "", que aparecem em operações idiomáticas, mas ainda assim permite configurar uma allowlist de valores aceitáveis para cenários específicos. Essa flexibilidade existe porque, em certos domínios, números como 90, 180 ou 360 deixam de ser “mágicos” e passam a ser parte da linguagem natural do problema (por exemplo, ângulos em graus).

Por que números mágicos atrapalham em expressões booleanas

Em expressões booleanas, o problema dos números mágicos fica mais evidente, porque a condição deveria comunicar a regra de negócio de forma clara. Ao escrever algo como if status == 2:, o leitor não sabe, de imediato, o que 2 representa: ativo, suspenso, cancelado?

A documentação do Pylint para magic-value-comparison / R2004 afirma que usar constantes nomeadas em vez de valores mágicos melhora a legibilidade e a manutenibilidade do código. Quando o valor de negócio muda (por exemplo, o status “ativo” deixa de ser 2 e passa a ser 3), o uso de literais espalhados exige uma busca manual sujeita a erro, enquanto uma constante única permite a mudança em um único ponto.

Exemplos em Python aplicando a PLR2004

Exemplo ruim: números mágicos em comparações

def can_access_admin_area(user_role: int) -> bool:
    # 1 = admin, 2 = editor, 3 = viewer
    return user_role == 1

Nesse caso, a PLR2004 sinalizaria o 1 como um magic value na comparação, sugerindo a extração para uma constante com nome significativo.

Exemplo melhor: constante nomeada

ADMIN_ROLE_ID = 1

def can_access_admin_area(user_role: int) -> bool:
    return user_role == ADMIN_ROLE_ID

Aqui, a expressão booleana se explica sozinha e a ferramenta de lint não acusa a regra PLR2004, pois o valor numérico está encapsulado em uma constante nomeada.[2][1]

Exemplo ruim: múltiplos valores mágicos

def is_valid_retry(status_code: int, retries: int) -> bool:
    # 200: OK; 500: erro interno; 3: máximo de tentativas
    return status_code != 200 and status_code != 500 and retries < 3

Esse padrão é exatamente o tipo de uso que a regra magic-value-comparison (PLR2004) se propõe a detectar.

Exemplo melhor: constantes de domínio

HTTP_OK = 200
HTTP_INTERNAL_ERROR = 500
MAX_RETRIES = 3

def is_valid_retry(status_code: int, retries: int) -> bool:
    return status_code not in (HTTP_OK, HTTP_INTERNAL_ERROR) and retries < MAX_RETRIES

Agora cada número tem um nome de domínio, a intenção da condição é clara e a manutenção futura fica concentrada nas constantes.

Exemplo com Enum para estados

from enum import Enum, auto

class UserStatus(Enum):
    INACTIVE = auto()
    ACTIVE = auto()
    SUSPENDED = auto()

def is_active(status: UserStatus) -> bool:
    return status is UserStatus.ACTIVE

Ao usar Enum, o código evita completamente comparações numéricas, eliminando o gatilho da PLR2004 e expressando a lógica booleana em termos de estados de negócio.

Conclusão: aproveite PLR2004 a seu favor

A regra PLR2004 (magic-value-comparison), definida originalmente no Pylint e incorporada pelo linter Ruff, existe justamente para forçar a substituição de números mágicos por constantes e construções semânticas em comparações. Em vez de encarar o aviso como ruído, é possível usá-lo como guia de refatoração para deixar suas expressões booleanas mais claras, consistentes e fáceis de evoluir.

 
Read more...

from in.versos

Vi, refletida na superfície do espelho, a face oculta da Morte.

Anjo, em vestes negras, cuja efígie me enfeitiça e cujo toque gélido anseio — em encanto e deleite —

no entrecruzar das mãos, cedidas a uma dança.

Uma única valsa, antes do fim.

 
Leia mais...

from in.versos

Era primeiro de abril. Uma noite serena.

Dois desconhecidos entre amigos e cigarros baratos.

Você sorriu! Era primeiro de abril.

E foi a primeira vez em que eu te amei!

 
Leia mais...

from Riverfount

Descubra como o pattern matching no Python 3.10+ transforma árvores de if/elif em código declarativo e poderoso, superando limitações do switch case clássico. Neste guia técnico para desenvolvedores Python, explore exemplos práticos de destructuring de listas, dicionários e classes, guards e padrões compostos – otimizado para buscas como “pattern matching Python tutorial”, “match case vs switch Python” e “structural pattern matching exemplos”.

O que Torna o Pattern Matching Único

Introduzido pelos PEPs 634, 635 e 636 no Python 3.10, o match/case vai além da comparação de valores: descreve a estrutura de dados, desconstruindo tuplas, listas, dicionários e objetos em variáveis prontas para uso. Diferente do switch case de C/Java, que compara apenas escalares sem fallthrough automático, aqui o primeiro case que casa encerra o bloco, eliminando bugs comuns. Ideal para APIs REST, eventos JSON e parsers em projetos full-stack Python.

Sintaxe Básica vs Switch Case

Exemplo clássico de dias da semana, similar a um switch mas com OR nativo (|) e wildcard (_):

def weekday_name(day: int) -> str:
    match day:
        case 1:
            return "Segunda-feira"
        case 2 | 3 | 4 | 5:
            return "Dia útil"
        case 6 | 7:
            return "Fim de semana"
        case _:
            raise ValueError(f"Dia inválido: {day}")

Sem break necessário – o case para automaticamente. Switch tradicional exigiria enum ou strings com fallthrough manual.

Destructuring: Poder Estrutural

O diferencial: padrões que capturam partes de estruturas compostas.

Tuplas e Listas

def process_point(point):
    match point:
        case (0, 0):
            return "Origem"
        case (0, y):
            return f"Eixo Y: {y}"
        case (x, 0):
            return f"Eixo X: {x}"
        case (x, y):
            return f"Ponto: ({x}, {y})"
        case [x, y, *rest]:
            return f"Lista longa: inicia {x},{y} + {len(rest)}"
        case _:
            raise TypeError("Formato inválido")

Captura variáveis diretamente, sem indexação manual – impossível em switch puro.

Dicionários e Eventos

def handle_event(event: dict):
    match event:
        case {"type": "click", "x": x, "y": y}:
            return f"Clique em ({x}, {y})"
        case {"type": "user", "id": uid}:
            return f"Usuário {uid}"
        case _:
            return "Ignorado"

Perfeito para payloads HTTP/JSON em Flask ou FastAPI.

Classes e Dataclasses

from dataclasses import dataclass

@dataclass
class CreateUser:
    email: str

@dataclass
class DeleteUser:
    id: int

def dispatch(cmd):
    match cmd:
        case CreateUser(email=email):
            return f"Criar: {email}"
        case DeleteUser(id=uid):
            return f"Excluir: {uid}"

Desconstrói atributos por nome – switch não acessa objetos assim.

Guards e Padrões Compostos

Combine matching com condições (if) e OR:

def classify(num: int):
    match num:
        case 0:
            return "Zero"
        case x if x > 0:
            return "Positivo"
        case x if x % 2 == 0:
            return "Par negativo"
        case _:
            return "Ímpar negativo."

Guards executam pós-captura, mantendo lógica coesa – superior a ifs externos em switches.

Vantagens sobre Switch Case

Aspecto Switch Case (C/Java) Pattern Matching Python
Comparação Valores escalares Estrutura + valores [4]
Destructuring Não Sim (listas/objetos) [1]
Guards/Condições Externo Integrado no case [2]
Fallthrough Manual (break) Automático [8]
Casos Múltiplos Labels separados `

Reduz if/elif verbosos em 50-70% para roteamento de dados.

Adote pattern matching em seus projetos Python para código mais legível e robusto. Teste os exemplos acima no seu ambiente e compartilhe comigo em @riverfount@bolha.us qual use case você vai aplicar primeiro. Para mais tutoriais avançados em Python, Spring Boot ou microservices, inscreva-se ou pergunte aqui!

 
Read more...

from Riverfount

Procurando por dicionários Python DSA, hash tables em Python, complexidade Big O dict Python ou estruturas de dados Python avançadas? Neste guia técnico desvendamos os princípios internos dos dicionários (dict), desde hashing e colisões até operações otimizadas para algoritmos reais. Ideal para engenheiros de software que buscam performance em microservices, grafos e entrevistas técnicas – leia e eleve seu código Python a outro nível!

Dicionários em Python (dict) são uma implementação eficiente de hash tables (tabelas de hash), uma estrutura de dados essencial em DSA para mapear chaves únicas a valores com acesso médio em tempo constante O(1). Essa performance os torna superiores a listas para operações de busca, inserção e deleção em cenários não ordenados, como caches, contagens de frequência ou representações de grafos. Desde Python 3.7, eles mantêm ordem de inserção, combinando benefícios de hash tables com listas ordenadas.[1]

Implementação Interna e Hashing

Internamente, o Python computa um hash da chave imutável (ex.: hash('chave')) para determinar o índice na tabela subjacente, um array redimensionável. Colisões são resolvidas por open addressing com probing quadrático. Chaves mutáveis (como listas) geram TypeError para evitar inconsistências.

Exemplo de hashing básico:

chave = 'abc'
hash_val = hash(chave)  # Resultado varia por sessão, ex: -123456789
print(f"Hash de '{chave}': {hash_val}")

Isso garante lookups rápidos, mas hashes ruins (ex.: ataques de hash-flooding) degradam para O(n) no pior caso.

Operações Fundamentais com Exemplos

Aqui estão as operações core, com análise de complexidade:

  • Criação e Inicialização:
  # Dict literal
  freq = {'a': 2, 'b': 1}
  
  # From iterable
  from collections import Counter
  freq = Counter('abacaxi')  # {'a': 3, 'b': 1, 'c': 1, 'x': 1, 'i': 1}
  • Inserção/Atualização (O(1) médio):

    freq['z'] = 1  # Insere ou atualiza
    freq.setdefault('y', 0)  # Insere só se ausente
    
  • Busca e Acesso (O(1) médio):

    valor = freq.get('a', 0)  # 3, com default se chave ausente
    if 'a' in freq:  # Verificação segura
      print(freq['a'])
    
  • Remoção (O(1) médio):

    del freq['z']  # Remove chave
    popped = freq.pop('b', None)  # Retorna valor ou default
    
  • Iteração Eficiente:

    # Chaves, valores ou itens
    for chave, valor in freq.items():
      print(f"{chave}: {valor}")
    

Complexidade Assintótica Detalhada

Operação Média (Amortizada) Pior Caso Notas
Inserção O(1) O(n) Redimensiona em load factor ~2/3
Busca (get) O(1) O(n) Colisões extremas
Deleção O(1) O(n) Marca como “tombstone”
Iteração O(n) O(n) Linear no tamanho
Len() O(1) O(1) Armazenado explicitamente

Boas Práticas e Casos de Uso em DSA

  • Evite chaves mutáveis: Use frozenset ou tuplas para chaves compostas.
  • Defaultdict para Simplicidade: python from collections import defaultdict graph = defaultdict(list) graph['A'].append('B') # Lista auto-criada
  • Aplicações:
    • Grafo de Adjacência: adj = {'A': ['B', 'C'], 'B': ['A']} para BFS/DFS.
    • Cache LRU Manual: Track acessos com dict + heapq.
    • Contagem de Frequência: Counter para anagramas ou sliding windows.
  • Alternativas: collections.OrderedDict para popitem(LRU), ou dict com __missing__ customizado.

Em projetos full-stack ou microservices, dicionários otimizam APIs REST (ex.: roteamento por ID) e automação, escalando para milhões de entradas sem gargalos.

Conclusão

Dominar dicionários é o primeiro passo para algoritmos escaláveis em Python – aplique esses conceitos hoje e veja seu código voar! Teste os exemplos no seu ambiente, experimente em LeetCode ou compartilhe em @riverfount@bolha.us como usou em projetos reais.

 
Read more...

from Riverfount

Generators em Python são funções especiais que usam yield para gerar valores sob demanda, economizando memória em vez de criar listas completas na RAM. Pense neles como “listas preguiçosas” que produzem um item por vez, ideais para processar arquivos grandes ou sequências infinitas sem travar o sistema.

Yield vs Return: A Diferença Fundamental

return encerra a função imediatamente após retornar um único valor, enquanto yield pausa a execução, retorna um valor e preserva o estado interno para continuar de onde parou na próxima chamada. Isso permite que uma única função gere múltiplos valores sequencialmente, como um loop “congelado” e retomado.

def com_return(n):
    for i in range(n):
        return i  # Para após o primeiro valor: sempre retorna 0

def com_yield(n):
    for i in range(n):
        yield i  # Gera 0, 1, 2... até n, pausando entre cada yield

print(next(com_return(5)))  # 0 (e função termina)
for i in com_yield(5):      # 0, 1, 2, 3, 4 (estado preservado)
    print(i)

return é para resultados finais únicos; yield constrói iteradores reutilizáveis.

Como Funcionam os Generators Básicos

Uma função generator parece normal, mas substitui return por yield, que pausa a execução e retorna um valor, preservando o estado para continuar depois. Isso cria um objeto iterável consumido com for ou next(), perfeito para loops sem alocar memória extra.

def contar_ate(n):
    for i in range(n):
        yield i

for numero in contar_ate(5):
    print(numero)  # Saída: 0 1 2 3 4

Vantagens em Memória e Performance

Generators brilham com dados grandes: uma lista de 1 milhão de números usa ~80MB, mas o generator equivalente consome apenas 128 bytes, gerando itens sob demanda. São nativos para for, list(), sum() e economizam tempo em cenários reais como leitura de logs ou CSV gigantes.

Expressões geradoras simplificam ainda mais: (x**2 for x in range(1000000)) cria um generator conciso sem parênteses extras, consumido iterativamente.

Tratamento de Exceções Simples

Exceções funcionam naturalmente dentro do generator. Use try/except para capturar erros durante a geração, como valores inválidos em um parser de JSON, mantendo o fluxo seguro.

def numeros_validos(arquivo):
    with open(arquivo) as f:
        for linha in f:
            try:
                yield int(linha.strip())
            except ValueError:
                print(f"Ignorando linha inválida: {linha}")
                continue

Isso previne crashes em dados reais “sujos”, comuns em automações e ETLs.

Fechamento Correto de Resources

Generators com arquivos ou conexões precisam de fechamento para evitar vazamentos. Use try/finally internamente ou generator.close() externamente, garantindo liberação automática.

# Exemplo 1: try/finally interno + close() externo
def ler_arquivo(arquivo):
    f = open(arquivo)
    try:
        for linha in f:
            yield linha.strip()
    finally:
        f.close()

gen = ler_arquivo('dados.csv')
try:
    for dado in gen:
        processar(dado)
finally:
    gen.close()

Context managers (with) integram perfeitamente para automação, eliminando necessidade de close() manual.

# Exemplo 2: Context manager with (mais limpo e automático)
def ler_arquivo_with(arquivo):
    with open(arquivo) as f:
        for linha in f:
            yield linha.strip()

# Uso simples e seguro - fecha automaticamente
for dado in ler_arquivo_with('dados.csv'):
    processar(dado)

Aplicações Práticas Iniciais

  • Arquivos gigantes: Leia linha por linha sem carregar tudo.
  • Sequências infinitas: Fibonacci ou contadores sem fim.
  • Pipelines simples: Filtre e transforme dados em cadeia.
  • Testes unitários: Mock de iteradores sem dados reais.​

Esses padrões otimizam ERPs, scripts de automação e APIs desde o primeiro projeto.

Conclusão

Generators transformam código Python em soluções eficientes e elegantes. Comece substituindo listas por generators em seus loops e veja a diferença em performance imediatamente.

Teste os exemplos acima no seu próximo projeto Python, meça o uso de memória com sys.getsizeof() e compartilhe seus resultados em @riverfount@bolha.us para discutirmos otimizações reais juntos!

 
Read more...

from Outras Coisas Mais

Oi! Estou procurando por uma amiga. Pode me ajudar?

Acho que talvez você a conheça:

Ela tem um sorriso gracioso; uma presença radiante; uma personalidade marcante, Ela gosta de dançar na chuva, o que é incrível visto o jeitinho de Paty — mas é só de primeira vista; usa uns vestidos lindos e tem um caminhar tão envolvente; A observar na contra luz do por do sol é de uma magia indescritível e os olhos, ah, aqueles olhos — são como uma doce e terna melodia. E por falar em melodia... O modo dela falar é delicioso, você pode ficar horas a ouvindo; ela tem uma forma curiosa de conversar sobre a vida e uma mania de terminar as frases com “Sabe?” que é tão maravilhoso de ouvir; e é o máximo como ela pronuncia “fácil”; O gosto para filmes é meio estranho; É maconheira; Gosta de ler para viajar a outros mundos— não é o máximo alguém que gosta de ler? E por incrível que pareça, ela gosta dos meus poemas. Ou parecia gostar. Ela tem alergia a pimenta; faz umas panquecas que parecem ser muito, muito saborosas; gosta de jabuticabas e coisas com canela — já falei das panquecas? E não gosta de lavar a louça, principalmente panelas; Ela é Bartender; gosta de jogar bilhar; virar shots e apreciar drinks — lembro de um tal Fritzgerald. Costuma ser um tanto distante, excessivamente focada no trabalho e ultimamente, tem parecido menos afetuosa — ou talvez seja um equívoco meu. Mas eu entendo esse jeito dela ser, e amo esse jeito dela ser.

Ah! Ela é inteligentíssima e escreve textos maravilhosos — que estou com saudade de ler.

Viu ela por aí? Se a vir, diga que mandei um abraço e que estou com saudade. E que quando ela puder e quiser, que me dê notícias de como está se sentindo.

Carta enviada para amiga
 
Leia mais...

from Paulo Henrique Rodrigues Pinheiro

Clara Charf

Morreu ontem, 3 de novembro de 2025, aos 100 anos, a camarada Clara Charf, militante revolucionária forjada nas lutas comunistas desde a juventude. Nascida em 17 de julho de 1925, Clara ingressou no Partido Comunista Brasileiro (PCB) ainda adolescente, tornando-se uma das vozes ativas na resistência à ditadura do Estado Novo.

Casada com Carlos Marighella, com quem compartilhou não apenas a vida afetiva, mas também o profundo compromisso com a transformação social, Clara teve uma longa carreira na estrutura partidária do velho PCB. Utilizando suas prerrogativas profissionais como aeromoça da Panair do Brasil, desempenhou papel crucial na logística da militância, transportando documentos clandestinos do Partidão por diversas cidades, cruzando fronteiras e arriscando a própria liberdade em nome da organização revolucionária.

Além dessa atuação discreta porém fundamental, Clara participou ativamente de inúmeras outras tarefas revolucionárias – desde a organização de bases operárias até a coordenação de ações de solidariedade internacionalista. Após o golpe de 1964, aprofundou seu engajamento na resistência à ditadura militar, tornando-se uma das fundadoras da Ação Libertadora Nacional (ALN), organização da qual Marighella seria principal dirigente.

Sua trajetória não se limitou à militância armada. Com a redemocratização, Clara Charf seguiu na linha de frente das lutas sociais, dedicando-se especialmente à causa feminista e tornando-se uma das principais referências do movimento de mulheres no Brasil. Foi fundadora da União de Mulheres de São Paulo e esteve envolvida nas campanhas pela Anistia ampla, geral e irrestrita e na construção do Partido dos Trabalhadores.

 
Leia mais...

from Fure a bolha

#tecnologia #tecnootimismo #IA

Introdução

Há uma ideia muito errada de que inteligência artificial seria juiz confiável e imparcial. Tem relato na rede social Lemmy de um infeliz cuja namorada vive jogando as brigas no casal no ChatGPT para dizer que o cara estava errado mesmo, o ChatGPT confirmou.

Na minha área (TI), antigamente era bem mais comum as pessoas lerem manuais info; man pages; e livros sobre algoritmos, matemática, engenharia de software. Aí quando se popularizaram sítios como Stack Overflow, alguns desenvolvedores passaram a copiar trechos prontos desses sítios para a base de código sem entender plenamente o funcionamento. Hoje piorou – o povo chupa da IA códigos grandes sem entender nada de como funciona. Menos conhecimento ainda do código que a pessoa terceirizou, e maior chance de erros (IA usando fontes ruins) e alucinações (IA fantasiando).

A seguinte entrevista de Jeremy Howard traz excelente perspectiva sobre o uso responsável de IA: https://youtu.be/LrFbxIvsipw

Entrevista com Jeremy Howard

Jeremy é CEO da Fast.ai e da Answer.ai. Criou o primeiro LLM – Large Language Model, ou modelo de linguagem de grande escala. Esse modelo, chamado ULMFiT, mostrou que o deep learning (aprendizagem profunda) funcionava muito bem com linguagem natural, e foi a base do ChatGPT (hoje temos Deep Seek).

No vídeo ele contesta a empolgação com agentes de IA (AI agents). Contesta a ideia de que a IA fará tudo para as pessoas. Argumenta que quem mergulha em agentes pára de aprender. Não pratica suas habilidades. Terceiriza tudo. Jeremy pretende estar no grupo de pessoas que usa IA com muito cuidado para continuar melhorando suas habilidades. Ele usa IA para se aprimorar, ganhar competência, aprender mais, praticar melhor.

Pessoas estão esquecendo como trabalhar. Estão esquecendo que conseguem trabalhar. Se a IA não resolve, ficam perdidas. Isso faz mal à psique. Quem deveria programar software, usa IA para criar milhares de linhas de código que não entende. Isso acumula dívida tecnológica, tornando muito difícil a depuração de defeitos e a integração. Jeremy já viu pessoas se tornarem deprimidas percebendo que perderam a competência e o controle. A abordagem centrada em agentes de IA coloca o computador no controle. Quem faz isso se coloca no caminho de se tornar incompetente e obsoleto.

O uso cego de IA pode aumentar no curto prazo o volume de trabalho, mas reduz a produtividade real a longo prazo. Código fonte gerado por IA não é muito bom. Não é bem integrado. Não cria camadas de abstração que funcionam bem em conjunto. A boa engenharia de software faz a produtividade aumentar ao longo do tempo. Com código gerado por IA ocorre o oposto. Jeremy avalia que empresas que se apoiam cegamente em IA vão olhar para trás e perceber que, no esforço de sempre conseguir resultado rápido em duas semanas, destruíram sua competência organizacional de criar coisas que duram.

Jeremy propõe que a IA observe o trabalho humano, dê dicas e responda perguntas de modo a guiar nosso trabalho, ao invés de executá-lo. Ele avalia ser um desenvolvedor de software muito melhor do que dois anos atrás, pois se dedica a usar IA para se aprimorar. Quer superar a IA.

Jeremy também apoia fortemente o código aberto, inclusive na IA, pelo bem da democracia. O poder deve ser decentralizado e não concentrado nas mãos dos ricos e poderosos. O Estado precisa intervir. Instituições privadas têm um papel de aproveitar os mercados.

No momento a China é o país que está nos salvando da centralização. Hoje todos os melhores modelos de IA de código aberto são chineses. Jeremy passou muito tempo na China, e avalia que lá o sistema investe de verdade em ciência da computação e matemática, e muitas pessoas acreditam na abertura.

Conclusão

Considero que é crítica a habilidade de usar IA de maneira responsável, para aprimorar o trabalhador humano e não substituí-lo. No entanto, falar é mais fácil do que fazer. Assim como sabemos que alimentação balanceada é muito importante para saúde, mas é difícil resistir à tentação de comer fast food e ultraprocessados, também é difícil resistir à tentação de terceirizar o trabalho para IA.

Eu aqui tento conferir e entender o que o Deep Seek diz. Por privacidade instalei também o qwen2.5:3b localmente em um contêiner Podman no meu laptop. Pretendo comprar uma máquina mais parruda para rodar localmente modelos mais poderosos e reduzir o uso de modelos hospedados em outros países. E quando preciso usar modelos hospedados em outros países, dou forte preferência a modelos de código aberto e hospedados em um país amigo como a China.

 
Leia mais...

from Fure a bolha

#ciencia #jornalismo #historia

Fontes confiáveis

Introdução

Na ciência da computação dizemos em inglês garbage in, garbage out – se a entrada é lixo, a saída é lixo. Isso vale também para argumentação lógica e aprendizado. Conclusões verdadeiras exigem não apenas um método válido mas também fontes confiáveis. Podemos aplicar metaforicamente o ditado “você é o que você come”.

Critério 1: fidelidade a fatos (literatura científica)

Para qualidade de fonte jornalística ou histórica, um critério crucial é fidelidade aos fatos, respeito ao consenso da literatura científica e uso de bons métodos e boas fontes. Isso importa mais que o tamanho e o prestígio do veículo.

Muito me inspira o argumento de Santo Agostinho – um dos maiores doutores da Igreja. Ele, da época do Império Romano, já defendia que os cristãos se informassem bem sobre a ciência secular. Argumentava (parafraseando): quando um infiel ouve um cristão dizer asneiras e barbaridades sobre coisas visíveis, a Igreja perde credibilidade. De fato, quem diz barbaridades até sobre coisas visíveis não tem credibilidade nem para coisas visíveis, nem (muito menos) para coisas invisíveis.

Isso me serve de valiosa analogia para fontes jornalísticas e históricas. Meu ponto forte são as exatas, pois sou formado em engenharia eletrônica e ciência da computação. Penso que as ciências humanas e sociais são mais sutis e mais suscetíveis a controvérsia do que as ciências exatas. Então quem diz asneiras e barbaridades até sobre as exatas, que dirá das humanas? Quando a cegueira ideológica não poupa nem as exatas, aquela fonte não é confiável nem para exatas, e muito menos para humanas e sociais.

Por exemplo, quem nega a ciência climática perde a credibilidade.

Critério 2: autoridade

Normalmente, quem consulta um cardiologista renomado não exige as fontes (artigo científico, livro etc) quando ele diagnostica pressão alta. Da mesmo forma, um especialista em determinado assunto fala com autoridade sobre aquele assunto. Já um anônimo tem necessidade reforçada de mostrar boas fontes para suas principais alegações controversas. Das fontes sugeridas abaixo, o sítio Red Sails é pouco conhecido mas ainda assim é confiável, pois veicula artigos de autores bem formados ou cobertos de citações de boas fontes.

Critério 3: enquadramento

O enquadramento (ou framing) é uma arma poderosa. Vai além da factualidade e direciona a seleção, ênfase e apresentação de aspectos de uma realidade, promovendo uma definição particular do problema, uma interpretação causal, uma avaliação moral ou uma recomendação de conduta.

Não se trata apenas do que é noticiado, mas como. A escolha de palavras, a voz gramatical (ativa ou passiva), a atribuição (ou não) de autoria e a adjetivação criam um “quadro” mental que induz a interpretação do leitor. Um mesmo acontecimento pode ser enquadrado como “ataque brutal” ou “auto defesa”.

A seguir, contrastamos manchetes do jornal estadunidense The New York Times, ilustrando a diferença drástica de enquadramento conforme os interesses geopolíticos dos Estados Unidos.

Enquadramento desfavorável e atributivo

The New York Times: Russia Strikes Children’s Hospital in Deadly Barrage Across Ukraine

Russia Strikes Children’s Hospital in Deadly Barrage Across Ukraine

Para um adversário dos EUA, o jornal emprega técnicas para gerar condenação e imputar brutalidade a um responsável específico:

  • Identificação clara do agressor: “Russia Strikes” (“Rússia ataca”). As primeiras palavras da manchete explicitam o responsável pelo ataque.
  • Voz ativa: O emprego da voz ativa (”Russia Strikes”) ressalta a intenção. Apresenta o adversário dos EUA como um beligerante que escolheu a violência.
  • Linguagem emotiva e conotativa: “Deadly Barrage” (“ataque massivo mortal”). A palavra “barrage” enfatiza um volume massivo e indiscriminado de ataques, enquanto “deadly” enfatiza o custo humano.

Enquadramento favorável e dissociativo

The New York Times: Israel-Hamas War: At Least 25 Reported Killed in Strike on School Building in Southern Gaza

Israel-Hamas War: At Least 25 Reported Killed in Strike on School Building in Southern Gaza

Em contraste gritante, o jornal enquadra o ataque israelense a uma escola palestina empregando técnicas para diluir a responsabilidade e contextualizar o ato de forma favorável:

  • Contextualização que justifica: “Israel-Hamas War” (guerra entre Israel e Hamas). A manchete insere o evento no contexto amplo de uma “guerra”. Isto, por um lado, informa, mas por outro, insinua a normalidade do acontecimento, como se fosse um resultado esperado e inevitável da guerra.
  • Voz passiva e agente oculto: “At Least 25 Reported Killed” (“pelo menos 25 mortos são reportados”). A voz passiva omite o autor do ato. As vítimas (“25”) tornam-se o sujeito gramatical da frase, enquanto o ator das mortes desaparece do texto.
  • Dissociação do agressor: A manchete omite Israel como o autor do ataque. O leitor desatento pode, inclusive, inferir que possa ter sido o Hamas. O jornal descreve o ataque como um evento fortuito.
  • Linguagem técnica e impessoal: “Strike on School Building” (Ataque a Edifício Escolar). Comparado com “Strikes a Children's Hospital in Deadly Barrage”, a linguagem é mais fria e burocrática, minimizando a carga emocional.

Impacto do enquadramento

Os veículos jornalísticos sistematicamente enquadram acontecimentos conforme sua visão de mundo e seus interesses. A cobertura jornalística pode, por meio de escolhas conscientes ou inconscientes, orientar a percepção do público:

  • No primeiro exemplo, o veículo induz o leitor a condenar um agressor claramente identificado por um ato de brutalidade.
  • No outro exemplo, o veículo induz o leitor a registrar um evento trágico, mas sem um agressor claro, num contexto de “guerra” que atenua a responsabilidade.

Reconhecer esses mecanismos é vital para uma leitura crítica da mídia. A honestidade de um veículo vai além da factualidade, mas alcança o enquadramento da realidade:

  • Quem é apresentado como agente de ação e quem é apresentado como sujeito passivo?
  • O que é omitido? O que é enfatizado?
  • Que palavras são escolhidas para influenciar minha percepção?

Sugestões

Abaixo vão algumas sugestões de comunicadores e veículos que respeitam a ciência e, transparentemente, se posicionam à esquerda.

Língua portuguesa

  1. Opera Mundi
  2. Elias Jabbour – Presidente do Instituto Municipal de Urbanismo Pereira Passos. Professor Associado da Faculdade de Ciências Econômicas, do Programa de Pós-Graduação em Ciências Econômicas e do Programa de Pós-Graduação em Relações Internacionais na UERJ. Em 2023–2024 foi Consultor Sênior da Presidência do Banco do BRICS e, de abril de 2006 a fevereiro de 2007, Assessor Econômico da Presidência da Câmara dos Deputados. Graduado em Geografia (1997), Doutor (2010) e Mestre (2005) em Geografia Humana pela USP. Tem experiência em Geografia e Economia com ênfase em Geografia Humana e Econômica, Economia Política, Economia Política Internacional e Planejamento Econômico. Atua principalmente nos temas: China; Socialismo com Características Chinesas; Nova Economia do Projetamento; Categorias de Transição ao Socialismo; Estratégias e Experiências Nacionais e Comparadas de Desenvolvimento; Categoria Marxista de Formação Econômico-Social; e Pensamento Independente de Ignacio Rangel. Vencedor do Special Book Award of China.
  3. José Kobori, importante financista de esquerda
  4. ICL Notícias
  5. Carta Capital

Língua inglesa

  1. Geopolitical Economy Report
  2. Red Sails
 
Leia mais...