O que é __init__ em Python? [With Examples]

Procurando começar com o design orientado a objetos em Python? Dê os primeiros passos hoje aprendendo sobre o método __init__ do Python.

Neste tutorial, examinaremos os fundamentos das classes e objetos do Python e, em seguida, aprenderemos sobre o método __init__.

Ao final deste tutorial, você será capaz de responder às seguintes perguntas:

  • O que são variáveis ​​de instância ou atributos de instância?
  • Como o método init ajuda na inicialização dos atributos da instância?
  • Como podemos definir valores padrão para atributos?
  • Como podemos usar métodos de classe como construtores para criar objetos?

Vamos começar.

Classes e objetos do Python

As classes são fundamentais para a programação orientada a objetos em Python. Podemos criar uma classe e definir atributos e métodos — para vincular dados e funcionalidades associadas.

Depois de criar uma classe, podemos usá-la como um projeto (ou modelo) para criar objetos (instâncias).

👩‍🏫Tempo de exemplo! Vamos criar uma classe Employee onde cada objeto desta classe possui os seguintes atributos:

  • full_name: o nome completo do funcionário no formato firstName lastName
  • emp_id: o id do funcionário
  • departamento: o departamento a que pertencem
  • experiência: o número de anos de experiência que eles têm

O que isto significa? 🤔

Cada funcionário individual será uma instância ou objeto da classe Employee. E cada objeto terá seu próprio valor para full_name, emp_id, departamento e experiência.

Esses atributos também são chamados de variáveis ​​de instância e usaremos os termos atributos e variáveis ​​de instância de forma intercambiável.

Em breve adicionaremos atributos. Por enquanto, criamos uma classe Employee da seguinte forma:

class Employee:
    pass

Usar pass (como espaço reservado) nos ajuda a evitar erros ao executar o script.

Embora a versão atual da classe Employee não seja muito útil, ainda é uma classe válida. Assim podemos criar objetos da classe Employee:

employee_1 = Employee()

print(employee_1)
#Output: <__main__.Employee object at 0x00FEE7F0>

Podemos também adicionar atributos e inicializá-los com valores como mostrado:

employee_1.full_name="Amy Bell"
employee_1.department="HR"

Mas essa abordagem para adicionar atributos de instância é ineficiente e propensa a erros. Além disso, isso não permite o uso de classe como modelo para criar objetos. Aqui é onde o método __init__ ajuda.

Compreendendo o papel do método __init__ em uma classe Python

Devemos ser capazes de inicializar as variáveis ​​de instância ao instanciar um objeto e o método __init__ nos ajuda a fazer isso. O método __init__ é chamado toda vez que um novo objeto da classe é criado para inicializar os valores das variáveis ​​de instância.

  O que é LOI e quando é usado?

Se você programou em uma linguagem como C++, verá que o método __init__ funciona de maneira semelhante aos construtores.

Definindo o método __init__

Vamos adicionar o método __init__ à classe Employee:

class Employee:
    def __init__(self, full_name,emp_id,department,experience):
        self.full_name = full_name
        self.emp_id = emp_id
        self.department = department
        self.experience = experience

O parâmetro self refere-se à instância da classe e self.attribute inicializa o atributo de instância com o valor do lado direito.

Agora podemos criar objetos assim:

employee_2 = Employee('Bella Joy','M007','Marketing',3)
print(employee_2)
# Output: <__main__.Employee object at 0x017F88B0>

Quando imprimimos os objetos empregados, não obtemos nenhuma informação útil, exceto a classe a que pertencem. Vamos adicionar um método __repr__ que define uma string de representação para a classe:

 def __repr__(self):
        return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."

Adicionando o __repr__ à classe Employee, temos:

class Employee:
    def __init__(self, full_name,emp_id,department,experience):
        self.full_name = full_name
        self.emp_id = emp_id
        self.department = department
        self.experience = experience
    
     def __repr__(self):
        return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."

Agora os objetos do funcionário têm uma string de representação útil:

print(employee_2)
# Output: Bella Joy,M007 from Marketing with 3 years of experience.

Algumas Convenções

Antes de prosseguirmos, aqui estão algumas notas:

  • Usamos self como o primeiro parâmetro no método __init__ para nos referirmos à própria instância da classe e usamos self.attribute_name para inicializar os vários atributos. Usar self é a convenção preferida (você pode usar qualquer outro nome).
  • Ao definir o método __init__, definimos os nomes dos parâmetros nas definições __init__ para corresponder aos nomes dos atributos. Isso melhora a legibilidade.

Como adicionar valores padrão para atributos

No exemplo que codificamos até agora, todos os atributos são obrigatórios. Significa que a criação do objeto é bem-sucedida somente se passarmos os valores de todos os campos para o construtor.

Tente instanciar um objeto da classe Employee sem passar o valor para o atributo experience:

employee_3 = Employee('Jake Lee','E001','Engineering')

Você obterá o seguinte erro:

Traceback (most recent call last):
  File "main.py", line 22, in <module>
    employee_3 = Employee('Jake Lee','E001','Engineering')
TypeError: __init__() missing 1 required positional argument: 'experience'

Mas se você quiser tornar determinados atributos opcionais, poderá fazê-lo fornecendo valores padrão para esses atributos ao definir o método __init__.

Aqui fornecemos um valor padrão de 0 para o atributo de experiência:

class Employee:
    def __init__(self, full_name,emp_id,department,experience=0):
        self.full_name = full_name
        self.emp_id = emp_id
        self.department = department
        self.experience = experience
    
     def __repr__(self):
        return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."

O objeto employee_3 é criado sem valor para o atributo experience; o valor padrão de 0 é usado para experiência.

employee_3 = Employee('Jake Lee','E001','Engineering')
print(employee_3.experience)
# Output: 0

Construtores de classe alternativos usando métodos de classe

Até agora, vimos apenas como definir o método __init__ e definir valores padrão para atributos quando necessário. Também sabemos que precisamos passar os valores para os atributos necessários no construtor.

  Executar a folha de pagamento para seu negócio em crescimento é fácil com o Zoho Payroll

Às vezes, no entanto, os valores dessas variáveis ​​de instância (ou atributos) podem estar disponíveis em uma estrutura de dados diferente, como uma tupla, um dicionário ou uma string JSON.

Então, o que fazemos?

Vamos dar um exemplo. Suponha que tenhamos valores da variável de instância em um dicionário Python:

dict_fanny = {'name':'Fanny Walker','id':'H203','dept':'HR','exp':2}

Podemos acessar o dicionário e obter todos os atributos da seguinte forma:

name = dict_fanny['name']
id = dict_fanny['id']
dept = dict_fanny['dept']
exp = dict_fanny['exp']

Depois disso, você pode criar um objeto passando esses valores para o construtor da classe:

employee_4 = Employee(name, id, dept, exp)
print(employee_4)
# Output: Fanny Walker,H203 from HR with 2 years of experience.

Lembre-se: você precisa fazer isso para cada novo objeto que criar. Essa abordagem é ineficiente e definitivamente podemos fazer melhor. Mas como?

Em Python, podemos usar métodos de classe como construtores para criar objetos da classe. Para criar um método de classe, usamos o decorador @classmethod.

Vamos definir um método que analise o dicionário, obtenha os valores das variáveis ​​de instância e os use para construir objetos Employee.

    @classmethod
    def from_dict(cls,data_dict):
        full_name = data_dict['name']
        emp_id = data_dict['id']
        department = data_dict['dept']
        experience = data_dict['exp']
        return cls(full_name, emp_id, department, experience)

Quando precisamos criar objetos usando dados do dicionário, podemos usar o método da classe from_dict().

💡 Observe o uso de cls no método da classe ao invés de self. Da mesma forma que usamos self para nos referirmos à instância, cls é usado para nos referirmos à classe. Além disso, os métodos de classe são vinculados à classe e não aos objetos.

Então, quando chamamos o método de classe from_dict() para criar objetos, nós o chamamos na classe Employee:

emp_dict = {'name':'Tia Bell','id':'S270','dept':'Sales','exp':3}
employee_5 = Employee.from_dict(emp_dict)
print(employee_5)
# Output: Tia Bell,S270 from Sales with 3 years of experience.

Agora, se tivermos um dicionário para cada um dos n funcionários, podemos usar o método de classe from_dict() como um construtor para instanciar objetos — sem precisar recuperar os valores de variáveis ​​instantâneas do dicionário.

📝Uma observação sobre variáveis ​​de classe

Aqui definimos o método de classe que está vinculado à classe e não às instâncias individuais. Semelhante aos métodos de classe, também podemos ter variáveis ​​de classe.

  Como recuperar um e-mail no Gmail

Assim como os métodos de classe, as variáveis ​​de classe são vinculadas à classe e não a uma instância. Quando um atributo assume um valor fixo para todas as instâncias da classe, podemos considerar defini-los como variáveis ​​de classe.

perguntas frequentes

1. Por que você precisa do método __init__ em Python?

O método __init__ em uma definição de classe nos permite inicializar os atributos ou variáveis ​​de instância de todas as instâncias da classe. O método __init__ é chamado sempre que uma nova instância da classe é criada.

2. Você pode ter vários métodos __init__ em uma classe Python?

O objetivo de ter vários métodos __init__ em uma classe Python é fornecer vários construtores que instanciam objetos. Mas você não pode definir vários métodos __init__. Se você definir vários métodos __init__, a segunda e mais recente implementação substituirá a primeira. No entanto, você pode usar o decorador @classmethod para definir métodos de classe que podem ser usados ​​como construtores para instanciar objetos.

3. O que acontece se você não definir o método __init__ em uma classe?

Se você não definir o método __init__, ainda poderá instanciar objetos. No entanto, você terá que adicionar variáveis ​​de instância manualmente e atribuir valores a cada uma delas. Você não poderá passar os valores para as variáveis ​​de instância no construtor. Isso não apenas é propenso a erros, mas também anula o propósito de ter a classe como um modelo a partir do qual podemos instanciar objetos.

4. Você pode ter valores padrão para argumentos no método __init__?

Sim, é possível fornecer valores padrão para um ou mais atributos ao definir o método __init__. Fornecer valores padrão ajuda a tornar esses atributos opcionais no construtor. Os atributos assumem os valores padrão quando não passamos os valores para esses atributos no construtor.

5. Você pode modificar atributos fora do método __init__?

Sim, você sempre pode atualizar o valor de um atributo fora do método __init__. Você também pode adicionar novos atributos dinamicamente a uma instância depois de criar a instância específica.

Conclusão

Neste tutorial, aprendemos como usar o método __init__ para inicializar os valores das variáveis ​​de instância. Embora isso seja direto, pode ser repetitivo – especialmente quando você tem muitos atributos.

Se estiver interessado, você pode explorar o módulo dataclasses. No Python 3.7 e posterior, você pode usar o módulo integrado de classes de dados para criar classes de dados que armazenam dados. Além das implementações padrão do __init__ e outros métodos comumente usados; eles vêm com muitos recursos interessantes para dicas de tipo, valores padrão complexos e otimização.

A seguir, aprenda mais sobre if __name__==’__main__’ em Python.