forked from luizomf/cursopython2023
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaula155.py
68 lines (54 loc) · 2.05 KB
/
aula155.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# Metaclasses são o tipo das classes
# EM PYTHON, TUDO É UM OBJETO (CLASSES TAMBÉM)
# Então, qual é o tipo de uma classe? (type)
# Seu objeto é uma instância da sua classe
# Sua classe é uma instância de type (type é uma metaclass)
# type('Name', (Bases,), __dict__)
#
# Ao criar uma classe, coisas ocorrem por padrão nessa ordem:
# __new__ da metaclass é chamado e cria a nova classe
# __call__ da metaclass é chamado com os argumentos e chama:
# __new__ da class com os argumentos (cria a instância)
# __init__ da class com os argumentos
# __call__ da metaclass termina a execução
#
# Métodos importantes da metaclass
# __new__(mcs, name, bases, dct) (Cria a classe)
# __call__(cls, *args, **kwargs) (Cria e inicializa a instância)
#
# "Metaclasses são magias mais profundas do que 99% dos usuários
# deveriam se preocupar. Se você quer saber se precisa delas,
# não precisa (as pessoas que realmente precisam delas sabem
# com certeza que precisam delas e não precisam de uma explicação
# sobre o porquê)."
# — Tim Peters (CPython Core Developer)
def meu_repr(self):
return f'{type(self).__name__}({self.__dict__})'
class Meta(type):
def __new__(mcs, name, bases, dct):
print('METACLASS NEW')
cls = super().__new__(mcs, name, bases, dct)
cls.attr = 1234
cls.__repr__ = meu_repr
if 'falar' not in cls.__dict__ or \
not callable(cls.__dict__['falar']):
raise NotImplementedError('Implemente falar')
return cls
def __call__(cls, *args, **kwargs):
instancia = super().__call__(*args, **kwargs)
if 'nome' not in instancia.__dict__:
raise NotImplementedError('Crie o attr nome')
return instancia
class Pessoa(metaclass=Meta):
# falar = 123
def __new__(cls, *args, **kwargs):
print('MEU NEW')
instancia = super().__new__(cls)
return instancia
def __init__(self, nome):
print('MEU INIT')
# self.nome = nome
def falar(self):
print('FALANDO...')
p1 = Pessoa('Luiz')
p1.falar()