Métodos mágicos
Os 95 ganchos que a linguagem procura no seu blueprint.
Um método mágico é um gancho: a linguagem o procura no blueprint quando uma operação acontece sobre uma instância. Declarar __add__ faz o + funcionar; declarar __getitem__ faz o [] funcionar. São 95, em 16 grupos.
blueprint Vetor:
action setup(x, y):
self.x := x
self.y := y
action __add__(outro):
yield spawn Vetor(self.x + outro.x, self.y + outro.y)
action __str__():
yield $"({self.x}, {self.y})"
action __eq__(outro):
yield self.x is outro.x and self.y is outro.y
action __len__():
yield 2
out spawn Vetor(1, 2) + spawn Vetor(3, 4) // imprime (4, 6)
assert len(spawn Vetor(1, 2)) is 2Por que o nome com dois sublinhados#
Porque é o que quem chega do Python já conhece, e porque o sublinhado duplo sinaliza isto não é para você chamar: ele é chamado pela linguagem, no momento da operação. v.__add__(outro) funciona, mas escrever isso é o mesmo que escrever v + outro de um jeito pior.
Um decorador que devolve void não substitui o alvo#
Vale lembrar aqui porque é a regra que permite @Rota("/x") apenas anotar: se um decorador devolvesse void e isso virasse o novo valor, a ação decorada sumiria.
Construção (6)#
Nascer, morrer e copiar.
| Método | Parâmetros | Chamado por |
|---|---|---|
__init__ | 0 | roda no spawn; sinonimo de 'setup' |
__new__ | 0 | cria a instancia antes de '__init__' |
__del__ | 0 | roda quando o objeto e descartado |
__copy__ | 0 | copia rasa |
__deepcopy__ | 0 | copia profunda |
__clone__ | 0 | copia, no vocabulario do DataForge |
Texto (5)#
O que out, str() e a interpolação chamam.
| Método | Parâmetros | Chamado por |
|---|---|---|
__str__ | 0 | o texto que 'out' imprime |
__repr__ | 0 | o texto para quem depura |
__format__ | 1 | formatacao com especificador |
__bytes__ | 0 | a representacao em bytes |
__doc__ | 0 | a documentacao do objeto |
Comparação (7)#
is, isnt, <, <=, >, >= e a ordenação.
| Método | Parâmetros | Chamado por |
|---|---|---|
__eq__ | 1 | a == b (e 'a is b') |
__ne__ | 1 | a != b (e 'a isnt b') |
__lt__ | 1 | a < b (e 'a smaller b') |
__le__ | 1 | a <= b |
__gt__ | 1 | a > b (e 'a bigger b') |
__ge__ | 1 | a >= b |
__cmp__ | 1 | -1, 0 ou 1; cobre os seis de uma vez |
Aritmética (9)#
+ - * / ~/ % **.
| Método | Parâmetros | Chamado por |
|---|---|---|
__add__ | 1 | a + b |
__sub__ | 1 | a - b |
__mul__ | 1 | a * b |
__truediv__ | 1 | a / b |
__floordiv__ | 1 | a ~/ b |
__mod__ | 1 | a % b |
__pow__ | 1 | a ** b |
__divmod__ | 1 | quociente e resto de uma vez |
__matmul__ | 1 | a @ b — multiplicacao de matriz |
Aritmética refletida (8)#
Quando o objeto está à direita do operador.
| Método | Parâmetros | Chamado por |
|---|---|---|
__radd__ | 1 | b + a, quando 'b' nao sabe somar |
__rsub__ | 1 | b - a |
__rmul__ | 1 | b * a |
__rtruediv__ | 1 | b / a |
__rfloordiv__ | 1 | b ~/ a |
__rmod__ | 1 | b % a |
__rpow__ | 1 | b ** a |
__rmatmul__ | 1 | b @ a |
Aritmética no lugar (7)#
+=, -= e as outras compostas.
| Método | Parâmetros | Chamado por |
|---|---|---|
__iadd__ | 1 | a += b, alterando 'a' |
__isub__ | 1 | a -= b |
__imul__ | 1 | a *= b |
__itruediv__ | 1 | a /= b |
__ifloordiv__ | 1 | a ~/= b |
__imod__ | 1 | a %= b |
__ipow__ | 1 | a **= b |
Unários (8)#
-x, +x, abs(x), round(x).
| Método | Parâmetros | Chamado por |
|---|---|---|
__neg__ | 0 | -a |
__pos__ | 0 | +a |
__abs__ | 0 | abs(a) |
__invert__ | 0 | ~a |
__round__ | 1 | round(a, casas) |
__floor__ | 0 | floor(a) |
__ceil__ | 0 | ceil(a) |
__trunc__ | 0 | trunc(a) |
Bits (8)#
& | ^ ~ << >>.
| Método | Parâmetros | Chamado por |
|---|---|---|
__and__ | 1 | a & b |
__or__ | 1 | a | b |
__xor__ | 1 | a ^ b |
__lshift__ | 1 | a << b |
__rshift__ | 1 | a >> b |
__rand__ | 1 | b & a |
__ror__ | 1 | b | a |
__rxor__ | 1 | b ^ a |
Conversão (6)#
int(), float(), bool(), len(), hash().
| Método | Parâmetros | Chamado por |
|---|---|---|
__bool__ | 0 | o que 'given obj:' decide |
__int__ | 0 | int(obj) |
__float__ | 0 | float(obj) |
__complex__ | 0 | complex(obj) |
__index__ | 0 | o objeto como indice de colecao |
__hash__ | 0 | a chave de vault que este objeto vira |
Coleção (10)#
[], in, percurso e tamanho.
| Método | Parâmetros | Chamado por |
|---|---|---|
__len__ | 0 | len(obj) |
__getitem__ | 1 | obj[chave] |
__setitem__ | 2 | obj[chave] := valor |
__delitem__ | 1 | delete obj[chave] |
__contains__ | 1 | item in obj |
__iter__ | 0 | 'cycle x in obj' |
__next__ | 0 | o proximo item do percurso |
__reversed__ | 0 | percurso de tras para frente |
__missing__ | 1 | chave ausente, antes de dar erro |
__length_hint__ | 0 | tamanho aproximado, para alocar antes |
Chamada (1)#
Fazer a instância ser chamável.
| Método | Parâmetros | Chamado por |
|---|---|---|
__call__ | -1 | obj(argumentos) |
Atributo (5)#
Ler, escrever e remover campo.
| Método | Parâmetros | Chamado por |
|---|---|---|
__getattr__ | 1 | obj.campo, quando o campo nao existe |
__getattribute__ | 1 | obj.campo, SEMPRE |
__setattr__ | 2 | obj.campo := valor |
__delattr__ | 1 | delete obj.campo |
__dir__ | 0 | a lista de nomes do objeto |
Descritor (4)#
Um campo cujo acesso é controlado por outro objeto.
| Método | Parâmetros | Chamado por |
|---|---|---|
__get__ | 2 | leitura do campo que este objeto guarda |
__set__ | 2 | escrita nele |
__delete__ | 1 | remocao |
__set_name__ | 2 | o nome que ele recebeu na classe |
Contexto (2)#
Entrar e sair de um bloco com limpeza garantida.
| Método | Parâmetros | Chamado por |
|---|---|---|
__enter__ | 0 | 'with obj as x:' — o que 'x' recebe |
__exit__ | 0 | o fim do bloco, mesmo com erro |
Assíncrono (5)#
await e percurso assíncrono.
| Método | Parâmetros | Chamado por |
|---|---|---|
__await__ | 0 | 'await obj' |
__aiter__ | 0 | percurso assincrono |
__anext__ | 0 | o proximo item dele |
__aenter__ | 0 | 'with' assincrono |
__aexit__ | 0 | o fim dele |
Tipo (4)#
Como o objeto responde a perguntas sobre si mesmo.
| Método | Parâmetros | Chamado por |
|---|---|---|
__instancecheck__ | 1 | 'e_um(x, Isto)' |
__subclasscheck__ | 1 | se um blueprint descende deste |
__class_getitem__ | 1 | Blueprint[Tipo] — generics |
__init_subclass__ | 1 | roda quando alguem herda deste |
O que não existe#
- Não há verificação de contrato. Declarar
__iter__sem__next__só falha quando alguém tenta percorrer o objeto. - `__slots__` não é um método mágico — é uma declaração; veja slots.
- Um mágico que devolve o tipo errado não é corrigido.
__len__devolvendo texto quebra nolen(), não na declaração.