Classes e Objetos em Python
Aprenda como classes e objetos funcionam em Python: defina classes, use __init__, crie instâncias, trabalhe com atributos e métodos, e entenda herança.
Python é uma linguagem de programação orientada a objetos (POO), o que significa que organiza o código em torno de objetos em vez de apenas funções. Uma classe é o modelo que descreve quais dados um objeto contém e o que ele pode fazer. Um objeto é uma instância específica criada a partir desse modelo.
Este capítulo aborda:
- O que são classes e objetos, e por que são importantes
- Definir uma classe com
__init__, atributos de instância e métodos - Atributos de classe versus atributos de instância
- Criar e usar objetos
- Modificar e excluir atributos
- Verificar tipos de objetos com
isinstance() - Uma primeira visão sobre herança
Para um aprofundamento em herança, veja Herança em Python. Para padrões de POO mais avançados, veja Classes Base Abstratas em Python.
O que é uma Classe?
Pense em uma classe como um cortador de biscoitos e em um objeto como o biscoito. Você define o formato uma vez (a classe) e então produz quantos biscoitos (objetos) precisar. Cada objeto compartilha a mesma estrutura, mas armazena seus próprios dados.
class Dog:
pass # an empty class — valid but not very useful yetA palavra-chave class seguida de um nome e dois-pontos cria uma nova classe. Por convenção, nomes de classes usam CapWords (também chamado de PascalCase): MyClass, BankAccount, HttpRequest.
O Método __init__
O método __init__ (abreviação de initialise) é executado automaticamente toda vez que você cria um novo objeto. Ele configura o estado inicial do objeto atribuindo valores aos seus atributos de instância.
class Dog:
def __init__(self, name, age):
self.name = name # instance attribute
self.age = age # instance attributeO primeiro parâmetro é sempre self — ele se refere ao objeto sendo criado. Python o passa automaticamente; você nunca o fornece por conta própria.
Atributos de Instância vs. Atributos de Classe
| Tipo | Definido dentro de | Pertence a | Compartilhado? |
|---|---|---|---|
| Atributo de instância | __init__ (via self) | Cada objeto | Não — cada objeto tem sua própria cópia |
| Atributo de classe | Corpo da classe (fora de qualquer método) | A própria classe | Sim — todos os objetos compartilham uma cópia |
class Dog:
species = "Canis familiaris" # class attribute — shared by all Dogs
def __init__(self, name, age):
self.name = name # instance attribute
self.age = age # instance attribute
fido = Dog("Fido", 3)
bella = Dog("Bella", 5)
print(fido.species) # Canis familiaris
print(bella.species) # Canis familiaris (same class attribute)
print(fido.name) # Fido
print(bella.name) # Bella (different instance attributes)Use um atributo de classe quando um valor é o mesmo para todos os objetos daquele tipo (por exemplo, a espécie de todos os Dogs). Use atributos de instância para dados que variam por objeto.
Definindo Métodos
Um método é uma função definida dentro de uma classe. Assim como __init__, ele sempre recebe self como primeiro parâmetro para que possa acessar os próprios atributos do objeto.
class Dog:
species = "Canis familiaris"
def __init__(self, name, age):
self.name = name
self.age = age
def bark(self):
return f"{self.name} says: Woof!"
def description(self):
return f"{self.name} is {self.age} years old."Você chama um método em um objeto usando a notação de ponto — Python passa automaticamente o objeto como self:
fido = Dog("Fido", 3)
print(fido.bark()) # Fido says: Woof!
print(fido.description()) # Fido is 3 years old.O Método __str__
Python chama __str__ quando você passa um objeto para print() ou str(). Sem ele, você obtém um endereço pouco útil como <__main__.Dog object at 0x...>. Defini-lo torna a depuração muito mais fácil.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"Dog(name={self.name!r}, age={self.age})"
fido = Dog("Fido", 3)
print(fido) # Dog(name='Fido', age=3)Criando e Usando Objetos
Criar um objeto é chamado de instanciação. Você chama a classe como uma função, passando quaisquer argumentos que __init__ espera (excluindo self):
Você pode criar quantos objetos precisar a partir da mesma classe — cada um é independente:
class Rectangle:
def __init__(self, width, height=1):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
r1 = Rectangle(4, 3)
r2 = Rectangle(5) # height defaults to 1
print(r1.area()) # 12
print(r1.perimeter()) # 14
print(r2.area()) # 5Note que height=1 fornece um valor padrão: se você omitir o segundo argumento, Python usa 1 automaticamente.
Modificando e Excluindo Atributos
Você pode alterar ou adicionar atributos a um objeto após ele ter sido criado, e excluí-los com del:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 30)
print(p.age) # 30
p.age = 31 # modify an existing attribute
print(p.age) # 31
p.email = "[email protected]" # add a new attribute at runtime
print(p.email) # [email protected]
del p.email # delete the attribute
# print(p.email) # would raise AttributeErrorEmbora Python permita adicionar atributos livremente, é mais limpo declarar todos os atributos dentro de __init__ para que a estrutura da classe seja evidente de relance.
Verificando Tipos de Objetos
Use isinstance() para verificar se um objeto é uma instância de uma determinada classe. Ela retorna True para a própria classe e qualquer uma de suas classes pai:
class Animal:
pass
class Dog(Animal):
pass
rex = Dog()
print(isinstance(rex, Dog)) # True
print(isinstance(rex, Animal)) # True — Dog is a subclass of Animal
print(type(rex) is Dog) # True
print(type(rex) is Animal) # False — type() does not climb the hierarchyPrefira isinstance() em vez de type() is na maioria do código porque ela lida corretamente com subclasses.
Uma Primeira Visão sobre Herança
A herança permite que uma nova classe reutilize e estenda o comportamento de uma existente. A nova classe (filha ou subclasse) automaticamente herda todos os atributos e métodos da classe pai:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"{self.name} makes a sound."
class Dog(Animal):
def speak(self): # override the parent method
return f"{self.name} says: Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says: Meow!"
dog = Dog("Rex")
cat = Cat("Whiskers")
print(dog.speak()) # Rex says: Woof!
print(cat.speak()) # Whiskers says: Meow!
print(isinstance(dog, Animal)) # TrueTanto Dog quanto Cat herdam __init__ de Animal, então não precisam repeti-lo. Eles apenas sobrescrevem speak() para fornecer um comportamento específico da raça.
Para um tratamento completo da herança — incluindo super(), herança múltipla e ordem de resolução de métodos — veja Herança em Python.
Quando Usar uma Classe?
As classes fazem mais sentido quando:
- Você tem dados e comportamento que pertencem juntos (uma conta bancária que sabe como depositar e sacar).
- Você precisa de múltiplos objetos independentes do mesmo tipo (muitos objetos
Dog, cada um com nomes e idades diferentes). - Você quer modelar entidades do mundo real com uma identidade clara.
Funções utilitárias simples que apenas transformam entrada em saída são muitas vezes melhores como funções simples. Python não exige que tudo esteja em uma classe.
Resumo
| Conceito | O que faz |
|---|---|
class | Define um novo tipo |
__init__ | Inicializa atributos de instância quando um objeto é criado |
self | Refere-se ao objeto atual dentro de um método |
| Atributo de instância | Dados pertencentes a um objeto específico |
| Atributo de classe | Dados compartilhados entre todos os objetos da classe |
| Método | Uma função definida dentro de uma classe; sempre recebe self |
__str__ | Controla como print() exibe o objeto |
isinstance() | Verifica se um objeto é uma instância de uma classe ou suas subclasses |
| Herança | Permite que uma classe filha reutilize e estenda uma classe pai |