Programação orientada a objetos - Parte 3#
Self#
Com a palavra-chave self conseguimos acessar os atributos e métodos de uma classe em Python. Ela é responsável por vincular os atributos com os argumentos enviados para uma função ou método.
O python utiliza essa palavra pois não há a sintaxe @ ou this para referenciar os atributos de instância. O self é sempre o primeiro parâmetro de todos os métodos chamados por uma instância de uma classe (ou seja, um objeto).
Self está sempre apontando para o objeto atual.
Vejamos nosso primeiro exemplo abaixo. A classe teste tem dentro do seu construtor uma mensagem para imprimir o endereço da variável self:
class teste:
def __init__(self):
print("Referência do self= ",id(self))
obj = teste()
print("Referência do objeto classe teste=", id(obj))
Referência do self= 2461971144080
Referência do objeto classe teste= 2461971144080
O init é o construtor da classe teste, significa que sempre que um novo objeto for instanciado a mensagem “Endereço do self: “ será executado. Nesse exemplo conseguimos comprovar que a variável self e o objeto obj possuem o mesmo endereço de memória, ou seja, representam a mesma coisa.
Agora vamos estudar um exemplo com atributos na classe.
class carro():
def __init__(self, modelo, cor):
self.modelo = modelo
self.cor = cor
def mostrar(self):
print("O modelo é", self.modelo)
print("A cor é", self.cor)
audi = carro("audi A4", "azul")
ferrari = carro ("ferrari 488", "verde")
audi.mostrar()
O modelo é audi A4
A cor é azul
ferrari.mostrar()
O modelo é ferrari 488
A cor é verde
Definimos a classe carro com dois parâmetros, modelo e cor. Podemos observar que a palavra self é sempre utilizada como primeiro argumento, tanto do construtor quanto do método mostrar. Nem quando instanciamos os objetos, nem quando chamamos o método mostrar utilizamos esse primeiro argumento self, o python passa essa chamada do método como se estivesse chamando carro.mostrar(audi) ou carro.mostrar(ferrari), vejam os exemplos abaixo:
Portanto, apesar de utilizarmos o self como primeiro argumento na definição de classes e métodos, não precisamos utilizá-lo na chamada. Mas o que acontece se não declararmos o self como primeiro parâmetro na definição? Será que essa palavra é opcional, servindo apenas para melhorar a legibilidade?
Vamos testar:
class teste_2:
def __init__():
print("Esse é o construtor")
objeto_2 = teste_2()
print("deu certo")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[10], line 5
2 def __init__():
3 print("Esse é o construtor")
----> 5 objeto_2 = teste_2()
6 print("deu certo")
TypeError: teste_2.__init__() takes 0 positional arguments but 1 was given
Vejam que o python não aceitou o construtor sem o self. Assim chegamos a uma conclusão:
O self é sempre o primeiro argumento a ser passado em um construtor e nos métodos de instâncias.
O último teste que faremos é a utilização de outro parâmetro no lugar do self, será que self é uma palavra reservada e teremos erro?
class teste_3:
def __init__(outro_self):
print("Usando outro parâmetro no lugar de self")
objeto_3 = teste_3()
print("deu certo")
Usando outro parâmetro no lugar de self
deu certo
Não teremos nenhum erro, pois a realidade é que o self não é uma palavra reservada, é apenas uma convenção de boa prática. Melhora a legibilidade.
O self é uma convenção e não uma palavra reservada
É possível utilizar outras palavras no lugar do self, mas preste atenção de utilizá-la em todos os lugares daquele método onde o self iria aparecer. Vejam os dois casos abaixo:
class carro():
def __init__(outro, modelo, cor):
self.modelo = modelo
self.cor = cor
def mostrar(self):
print("O modelo é", self.modelo)
print("A cor é", self.cor)
fusca = carro('fusca','amarelo')
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[13], line 10
7 print("O modelo é", self.modelo)
8 print("A cor é", self.cor)
---> 10 fusca = carro('fusca','amarelo')
Cell In[13], line 3, in carro.__init__(outro, modelo, cor)
2 def __init__(outro, modelo, cor):
----> 3 self.modelo = modelo
4 self.cor = cor
NameError: name 'self' is not defined
E aqui a execução funcionaria sem problemas:
class carro():
def __init__(outro, modelo, cor):
outro.modelo = modelo
outro.cor = cor
def mostrar(self):
print("O modelo é", self.modelo)
print("A cor é", self.cor)
fusca = carro('fusca','amarelo')
fusca.mostrar()
O modelo é fusca
A cor é amarelo