Python __novo__

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 objectclasse. Possui a seguinte assinatura:

object.__new__(class, *args, **kwargs)Linguagem de código:  Python  ( python )

O primeiro argumento do __new__método é o classdo novo objeto que você deseja criar.

Os parâmetros *argse **kwargsdevem 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 objectclasse. 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 Personclasse com o nameatributo e cria uma nova instância da Personclasse:

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 personapó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 nameatributo 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 SquareNumberclasse que herda do tipo int integrado:

class SquareNumber(int):
    def __new__(cls, value):
        return super().__new__(cls, value ** 2)


x = SquareNumber(3)
print(x)  # 9Linguagem de código:  Python  ( python )

Neste exemplo, o __new__()método da SquareNumberclasse aceita um número inteiro e retorna o número quadrado. xé uma instância da SquareNumberclasse e também uma instância do inttipo interno:

print(isinstance(x, int)) # TrueLinguagem de código:  Python  ( python )

Observe que você não pode fazer isso usando o __init__()método porque o __init__()método interno intnã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 Personclasse e usa o __new__método para injetar o full_nameatributo 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 da objectclasse.
  • 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.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *