3
respostas

Python - Atributo de Uma Classe

Para definir atributos de uma classe devo colocá-los sempre no método "init" ou tem outro jeito ou lugar?

3 respostas

Carlos, o método __init__ do Python é por definição o inicializador de uma instância da sua classe.

Por exemplo:

class Cachorros:
    def __init__(self, patas, cor):
        self.patas = patas
        self.cor = cor

fido = Cachorros(4, "preto")
bidu = Cachorros(3, "marrom")

Fido e bidu são instâncias (objetos) da sua classe Cachorros, e ao definí-los caracterizando suas patas e suas cores, o Python, por meio do init "inicializou" instâncias da classe. O self se refere à instância, ou seja, o self de fido é o próprio fido.

Ou seja, você tem a classe Cachorros e fido e bidu são instâncias da sua classe que foram inicializadas pelo __init__ quando você criou as instâncias.

Se você quiser saber os atributos de cada objeto, pode fazer:

fido.cor

retorna 'preto'

Por definição você deve usar o __init__ para criar objetos (instâncias) das suas classes. E por isso geralmente a primeira função que você cria ao criar uma classe é o __init__. Não sei se fui claro, é meio confuso mesmo no início. Se continuar com dúvida posta aí.

Entendi seu exemplo mas a minha pergunta é se um atributo pode ser criado fora do init Entendo que o init inicializa um atributo, mas eu quero saber se os atributos podem ser declarados fora do init Agradeço pela primeira resposta mas, se possível, espero por uma outra. Talvez o código abaixo dê sentido na minha pergunta.

class Cachorros:
    # Atributos:
    patas = 0
    cor = ""

Ah, perdão se não entendi direito a pergunta e expliquei outra coisa.

Se o atributo pode ser criado fora do __init__: Mesmo exemplo acima, mas de outra forma:

class Cachorros:
    def __init__(self, patas):
        self.patas = patas


    def define_cor(self, cor):
        self.cor = cor

No console:

bidu = Cachorros(4)
bidu.patas

O retorno do pedido é 4 Agora, para definir a cor, você tem que chamar a nova função e passar a cor como parâmetro:

bidu.define_cor("preto")
bidu.cor

O retorno é "preto".

O mesmo exemplo sem __init__:

class Cachorros:
    def define_cachorro(self, patas, cor):
        self.patas = patas
        self.cor = cor

No console você deve criar a instância primeiro para só depois passar os atributos da instância. Você acaba escrevendo mais para no final ter o mesmo resultado:

bidu = Cachorros()
bidu.define_cachorro(4, "preto")
bidu.cor

O retorno dos atributo "cor" trará "preto" normalmente no console, mas assim você digitou uma linha a mais de código para obter o mesmo resultado. Usar o __init__ é uma boa prática de programação em Python. Não usá-lo deixa seu código mais "hardcoded" e você precisa digitar mais código pra obter o mesmo resultado.

Então, via de regra, ao criar um objeto de sua classe você usa o __init__ e já passa os parâmetros iniciais para o objeto no momento de criação da instância.

Entretanto, no seu exemplo, você já criou cor e pata por default, o que pode ser feito sem problema. Você pode criar a classe assim:

class Cachorros:
    cor = "preto"
    patas = 4

E ao instanciar qualquer objeto sem passar parâmetro algum, ele já trará a cor preta e 4 patas como atributos dele.

bidu.patas

retorna 4 por default Você pode alterar o atributo dessa forma:

bidu.patas = 5

E o retorno trará 5 normalmente, mas isso, o ato de "forçar" uma mudança em atributo no console sem usar uma função setter para tal, não é considerado uma boa prática em Python. Para fazer isso você terá que definir um setter na classe, que será assunto abordado no decorrer do curso de Programação Orientada a Objetos em Python.

Em resumo: Se seus atributos são variáveis de acordo com o objeto instanciado (por exemplo, nem todo cachorro é preto), o ideal é usar o __init__ e passar os atributos ao instanciar o objeto da classe. Entretanto, você pode definir que todos os objetos da sua classe vão ter sempre o mesmo atributo por padrão (como definir que todo cachorro tem 4 patas) e passar esse atributo fora de qualquer função mas dentro da classe, o que pode ser feito sem problema. Mas alterar esse atributo "à força" sem um setter é considerado má prática.

Essa resposta era mais o menos o que você queria saber? Espero que dessa vez eu tenha entendido a pergunta haha