Métodos Mágicos em Python

Método __new__

# Exemplo básico de __new__
class ExemploBase:
    def __new__(cls):
        print(f"Classe recebida: {cls}")
        return object.__new__(cls)

objeto = ExemploBase()

# Demonstração da ordem de execução
class Demonstracao:
    def __new__(cls):
        print("1: Criação do objeto")
        return object.__new__(cls)

    def __init__(self):
        print("2: Inicialização do objeto")

instancia = Demonstracao()

# Passando parâmetros
class Parametros:
    def __new__(cls, valor, *args, **kwargs):
        return object.__new__(cls)

    def __init__(self, valor, extra=None):
        self.dado = valor
        self.complemento = extra

param = Parametros(10, extra="info")

# Importante: Se __new__ não retornar a instância atual, __init__ não será chamado
class SemInit:
    def __new__(cls):
        return None  # __init__ não será executado

teste = SemInit()
print(type(teste))  # Output: NoneType
# Implementação do Singleton
class Singleton:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

a = Singleton()
b = Singleton()
print(f"Mesma instância? {a is b}")

# Singleton com inicialização de atributos
class GerenciadorConexao:
    _instance = None

    def __new__(cls, url):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance.url = url
        return cls._instance

    def conectar(self):
        return f"Conectado a {self.url}"

conexao1 = GerenciadorConexao("db://principal")
conexao2 = GerenciadorConexao("db://secundaria")
print(conexao1.conectar())  # Apenas a primeira URL é mantida
# Exemplo de destrutor
class Recurso:
    def __init__(self, nome):
        self.nome = nome
        self.arquivo = open(f"{nome}.txt", "w")

    def escrever(self, texto):
        self.arquivo.write(texto)

    def __del__(self):
        self.arquivo.close()
        print(f"Recurso '{self.nome}' liberado")

# Quando o objeto é destruído
recurso = Recurso("temp")
recurso.escrever("dados")
recurso = None  # __del__ será chamado aqui

# Controle de referências
obj1 = Recurso("dados")
obj2 = obj1
del obj1  # Não destrói ainda, pois obj2 ainda referencia
obj2 = None  # Agora __del__ é chamado
# Usando objetos como funções
class Calculadora:
    def __call__(self, a, b):
        return a + b

calc = Calculadora()
resultado = calc(3, 4)  # Executa __call__

# Encadeamento de operações
class Pipeline:
    def __init__(self):
        self.etapas = []

    def adicionar(self, funcao):
        self.etapas.append(funcao)
        return self

    def __call__(self, valor):
        resultado = valor
        for etapa in self.etapas:
            resultado = etapa(resultado)
        return resultado

processamento = Pipeline()
processamento.adicionar(lambda x: x * 2).adicionar(lambda x: x + 1)
print(processamento(5))  # Output: 11
# Representação para debug (repr)
class Ponto:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Ponto({self.x}, {self.y})"

# Representação para usuário (str)
class Usuario:
    def __init__(self, nome, email):
        self.nome = nome
        self.email = email

    def __str__(self):
        return self.nome

    def __repr__(self):
        return f"Usuario('{self.nome}', '{self.email}')"

p = Ponto(2, 3)
print(repr(p))  # Output: Ponto(2, 3)

u = Usuario("Ana", "ana@email.com")
print(u)        # Output: Ana (usa __str__)
print(repr(u))  # Output: Usuario('Ana', 'ana@email.com') (usa __repr__)
def adicionar(self, item):
    self.itens.append(item)

def __bool__(self):
    return len(self.itens) > 0

carrinho = Carrinho() print(bool(carrinho)) # Output: False (carrinho vazio) carrinho.adicionar("produto") print(bool(carrinho)) # Output: True

Métodos add e radd

class Vetor: def init(self, x, y): self.x = x self.y = y

def __add__(self, outro):
    return Vetor(self.x + outro.x, self.y + outro.y)

def __radd__(self, outro):
    if isinstance(outro, (int, float)):
        return Vetor(self.x + outro, self.y + outro)
    return NotImplemented

v1 = Vetor(1, 2) v2 = Vetor(3, 4) v3 = v1 + v2 # Usa add v4 = 5 + v1 # Usa radd print(f"Soma vetores: ({v3.x}, {v3.y})") print(f"Soma escalar: ({v4.x}, {v4.y})")

Método len

class Colecao: def init(self, dados): self._dados = list(dados)

def __len__(self):
    return len(self._dados)

colet = Colecao([1, 2, 3, 4]) print(f"Tamanho: {len(colet)}") # Output: 4


</div>

Tags: Python magic-methods singleton oo-programming classes

Publicado em 6-5 20:12 por Thomas