Resumo : neste tutorial, você aprenderá sobre o método Python __new__ e entenderá como o Python o utiliza para criar um novo objeto.
Introdução ao método Python __new__
Quando você cria uma instância de uma classe , o Python primeiro chama o __new__()
método para criar o objeto e depois chama o __init__()
método para inicializar os atributos do objeto.
O __new__()
é um método estático da object
classe. Possui a seguinte assinatura:
object.__new__(class, *args, **kwargs)
Linguagem de código: Python ( python )
O primeiro argumento do __new__
método é o class
do novo objeto que você deseja criar.
Os parâmetros *args
e **kwargs
devem corresponder aos parâmetros da __init__()
classe. No entanto, o __new__()
método os utiliza.
O __new__()
método deve retornar um novo objeto da classe. Mas não é necessário.
Quando você define uma nova classe, essa classe herda implicitamente da object
classe. Isso significa que você pode substituir o __new__
método estático e fazer algo antes e depois de criar uma nova instância da classe.
Para criar o objeto de uma classe, você chama o super().__new__()
método.
Tecnicamente, você pode chamar o object.__new__()
método para criar um objeto manualmente. No entanto, você mesmo precisará ligar __init__()
manualmente depois. Python não chamará o __init__()
método automaticamente se você criar explicitamente um novo objeto usando o object.__new__()
método.
Exemplo de método Python __new__
O seguinte define a Person
classe com o name
atributo e cria uma nova instância da Person
classe:
class Person:
def __init__(self, name):
self.name = name
person = Person('John')
Linguagem de código: Python ( python )
Em Python, uma classe pode ser chamada . Quando você chama a classe para criar um novo objeto:
person = Person('John')
Linguagem de código: Python ( python )
Python chamará os métodos __new__()
e __init__()
. É equivalente às seguintes chamadas de método:
person = object.__new__(Person, 'John')
person.__init__('John')
Linguagem de código: Python ( python )
O seguinte mostra o conteúdo do __dict__
objeto person
após chamar os métodos __new__()
e __init__()
:
person = object.__new__(Person, 'John')
print(person.__dict__)
person.__init__('John')
print(person.__dict__)
Linguagem de código: Python ( python )
Saída:
{}
{'name': 'John'}
Linguagem de código: Python ( python )
Como você pode ver claramente na saída, depois de chamar o __new__()
método, o person.__dict__
está vazio. E depois de chamar o __init__()
método, person.__dict__
contém o name
atributo com o valor ‘ John'
.
O seguinte ilustra a sequência pela qual o Python chama o método __new__
and __init__
quando você cria um novo objeto chamando a classe:
class Person:
def __new__(cls, name):
print(f'Creating a new {cls.__name__} object...')
obj = object.__new__(cls)
return obj
def __init__(self, name):
print(f'Initializing the person object...')
self.name = name
person = Person('John')
Linguagem de código: Python ( python )
Saída:
Creating a new Person object...
Initializing the person object...
Linguagem de código: Python ( python )
Neste exemplo, Python chama o método __new__ e o método __init__ depois disso.
Ao usar o método __new__
O exemplo a seguir define a SquareNumber
classe que herda do tipo int integrado:
class SquareNumber(int):
def __new__(cls, value):
return super().__new__(cls, value ** 2)
x = SquareNumber(3)
print(x) # 9
Linguagem de código: Python ( python )
Neste exemplo, o __new__()
método da SquareNumber
classe aceita um número inteiro e retorna o número quadrado. x
é uma instância da SquareNumber
classe e também uma instância do int
tipo interno:
print(isinstance(x, int)) # True
Linguagem de código: Python ( python )
Observe que você não pode fazer isso usando o __init__()
método porque o __init__()
método interno int
não aceita argumentos. O código a seguir resultará em um erro:
class SquareNumber(int):
def __init__(self, value):
super().__init__(value ** 2)
x = SquareNumber(3)
Linguagem de código: Python ( python )
Erro:
TypeError: object.__init__() takes exactly one argument (the instance to initialize)
Linguagem de código: Python ( python )
Na prática, você usa o __new__()
método quando deseja ajustar o objeto no momento instanciado.
Por exemplo, o seguinte define a Person
classe e usa o __new__
método para injetar o full_name
atributo no objeto Person:
class Person:
def __new__(cls, first_name, last_name):
# create a new object
obj = super().__new__(cls)
# initialize attributes
obj.first_name = first_name
obj.last_name = last_name
# inject new attribute
obj.full_name = f'{first_name} {last_name}'
return obj
person = Person('John', 'Doe')
print(person.full_name)
print(person.__dict__)
Linguagem de código: Python ( python )
Saída:
John Doe
{'first_name': 'John', 'last_name': 'Doe', 'full_name': 'John Doe'}
Linguagem de código: Python ( python )
Normalmente, quando você substitui o __new__()
método, não precisa defini- __init__()
lo porque tudo o que você pode fazer no __init__()
método, você pode fazer no __new__()
método.
Resumo
- O
__new__()
é um método estático daobject
classe. - Quando você cria um novo objeto chamando a classe, Python chama
__new__()
primeiro o método para criar o objeto e depois chama o__init__()
método para inicializar os atributos do objeto. - Substitua o
__new__()
método se quiser ajustar o objeto no momento da criação.