Introdução
Neste tutorial, exploraremos como acessar e modificar atributos de objetos Python. Compreender como trabalhar com propriedades de objetos é uma habilidade fundamental para a programação em Python. Ao final deste laboratório, você será capaz de criar objetos, acessar seus atributos usando diferentes métodos e modificar esses atributos para alterar o comportamento do objeto.
Python é uma linguagem de programação orientada a objetos, o que significa que tudo em Python é um objeto com propriedades e métodos. Aprender a interagir com esses objetos é essencial para construir aplicações Python eficazes.
Criando uma Classe Python Simples
Vamos começar entendendo o que são classes e objetos Python e como criá-los.
O que são Classes e Objetos?
Em Python, uma classe é um modelo para criar objetos. Objetos são instâncias de classes, que contêm:
- Atributos (Attributes): Variáveis que armazenam dados
- Métodos (Methods): Funções que definem ações que o objeto pode realizar
Pense em uma classe como um modelo e em um objeto como algo criado a partir desse modelo.
Criando Sua Primeira Classe
Vamos criar uma classe Person simples com alguns atributos básicos. Abra o editor de código e crie um novo arquivo chamado person.py no diretório /home/labex/project:
## Define a Person class with name and age attributes
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
return f"Hello, my name is {self.name} and I am {self.age} years old."
## Create a Person object
john = Person("John", 30)
## Print the object
print(john)
print(f"Type of john: {type(john)}")
Este código define uma classe Person com dois atributos (name e age) e um método (greet). Vamos entender os componentes-chave:
class Person:- Esta linha declara uma nova classe chamadaPerson__init__- Este é um método especial chamado construtor, que inicializa um novo objeto quando ele é criadoself- Este parâmetro se refere ao objeto que está sendo criado ou manipuladoself.name = name- Isso cria um atributo chamadonamepara o objeto e atribui a ele o valor passado para o construtor
Agora, vamos executar este código para ver o que acontece:
python3 /home/labex/project/person.py
Você deve ver uma saída semelhante a:
<__main__.Person object at 0x7f8b2c3d9d90>
Type of john: <class '__main__.Person'>
Esta saída nos diz que john é um objeto da classe Person. O número hexadecimal é o endereço de memória onde o objeto está armazenado.
Criando Múltiplos Objetos
Podemos criar múltiplos objetos a partir de uma única classe. Vamos modificar nosso arquivo person.py para criar outro objeto Person:
## Define a Person class with name and age attributes
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
return f"Hello, my name is {self.name} and I am {self.age} years old."
## Create two Person objects
john = Person("John", 30)
alice = Person("Alice", 25)
## Print information about both objects
print(f"First person: {john.name}, {john.age}")
print(f"Second person: {alice.name}, {alice.age}")
Execute o código atualizado:
python3 /home/labex/project/person.py
Você deve ver:
First person: John, 30
Second person: Alice, 25
Agora, criamos dois objetos Person diferentes, cada um com seus próprios atributos name e age.
Acessando Atributos de Objetos
Agora que criamos objetos com atributos, vamos aprender diferentes maneiras de acessar esses atributos.
Usando Notação de Ponto
A maneira mais comum de acessar atributos de objetos é usando a notação de ponto: object.attribute.
Vamos criar um novo arquivo chamado access_attributes.py no diretório /home/labex/project:
class Person:
def __init__(self, name, age, job):
self.name = name
self.age = age
self.job = job
def greet(self):
return f"Hello, my name is {self.name} and I am {self.age} years old."
## Create a Person object
john = Person("John", 30, "Developer")
## Access attributes using dot notation
print(f"Name: {john.name}")
print(f"Age: {john.age}")
print(f"Job: {john.job}")
## Access and call a method
greeting = john.greet()
print(f"Greeting: {greeting}")
Execute este código:
python3 /home/labex/project/access_attributes.py
Você deve ver:
Name: John
Age: 30
Job: Developer
Greeting: Hello, my name is John and I am 30 years old.
Acessando Atributos Usando Variáveis
Às vezes, você pode precisar acessar um atributo quando você só tem seu nome como uma string. Isso pode ser útil quando você está trabalhando com nomes de atributos determinados dinamicamente.
Vamos modificar nosso arquivo access_attributes.py:
class Person:
def __init__(self, name, age, job):
self.name = name
self.age = age
self.job = job
def greet(self):
return f"Hello, my name is {self.name} and I am {self.age} years old."
## Create a Person object
john = Person("John", 30, "Developer")
## List of attributes to access
attributes = ["name", "age", "job"]
## Access attributes using a loop and dot notation
print("Accessing attributes using dot notation:")
for attr in attributes:
if attr == "name":
print(f"Name: {john.name}")
elif attr == "age":
print(f"Age: {john.age}")
elif attr == "job":
print(f"Job: {john.job}")
## Call a method
greeting = john.greet()
print(f"Greeting: {greeting}")
Execute o código:
python3 /home/labex/project/access_attributes.py
Você deve ver:
Accessing attributes using dot notation:
Name: John
Age: 30
Job: Developer
Greeting: Hello, my name is John and I am 30 years old.
Isso é um pouco complicado. No próximo passo, aprenderemos uma maneira mais elegante de acessar atributos dinamicamente.
Usando as Funções getattr() e setattr()
Python fornece funções embutidas para acessar e modificar atributos de objetos dinamicamente. Elas são particularmente úteis quando você deseja trabalhar com nomes de atributos que não são conhecidos até o tempo de execução.
A Função getattr()
A função getattr() permite que você acesse um atributo usando seu nome como uma string. A sintaxe é:
getattr(object, attribute_name, default_value)
object: O objeto cujo atributo você deseja acessarattribute_name: Uma string contendo o nome do atributodefault_value: Um valor opcional para retornar se o atributo não existir
Vamos criar um novo arquivo chamado dynamic_attributes.py no diretório /home/labex/project:
class Person:
def __init__(self, name, age, job):
self.name = name
self.age = age
self.job = job
def greet(self):
return f"Hello, my name is {self.name} and I am {self.age} years old."
## Create a Person object
john = Person("John", 30, "Developer")
## List of attributes to access
attributes = ["name", "age", "job", "address"]
## Access attributes using getattr()
print("Accessing attributes using getattr():")
for attr in attributes:
## The third parameter is the default value if the attribute doesn't exist
value = getattr(john, attr, "Not available")
print(f"{attr.capitalize()}: {value}")
## Call a method using getattr
greet_method = getattr(john, "greet")
greeting = greet_method()
print(f"Greeting: {greeting}")
Execute este código:
python3 /home/labex/project/dynamic_attributes.py
Você deve ver:
Accessing attributes using getattr():
Name: John
Age: 30
Job: Developer
Address: Not available
Greeting: Hello, my name is John and I am 30 years old.
Observe que, para o atributo address, que não existe, getattr() retorna nosso valor padrão "Not available" em vez de gerar um erro.
A Função setattr()
A função setattr() permite que você defina um atributo usando seu nome como uma string. A sintaxe é:
setattr(object, attribute_name, value)
object: O objeto cujo atributo você deseja definirattribute_name: Uma string contendo o nome do atributovalue: O valor a ser atribuído ao atributo
Vamos modificar nosso arquivo dynamic_attributes.py para incluir exemplos de uso de setattr():
class Person:
def __init__(self, name, age, job):
self.name = name
self.age = age
self.job = job
def greet(self):
return f"Hello, my name is {self.name} and I am {self.age} years old."
## Create a Person object
john = Person("John", 30, "Developer")
print("Original attributes:")
print(f"Name: {john.name}")
print(f"Age: {john.age}")
print(f"Job: {john.job}")
## Modify attributes using setattr()
print("\nModifying attributes using setattr():")
setattr(john, "name", "John Smith")
setattr(john, "age", 31)
setattr(john, "job", "Senior Developer")
## Add a new attribute using setattr()
setattr(john, "address", "123 Main St")
## Print the modified attributes
print("\nModified attributes:")
print(f"Name: {john.name}")
print(f"Age: {john.age}")
print(f"Job: {john.job}")
print(f"Address: {john.address}")
## Access attributes using getattr()
print("\nAccessing attributes using getattr():")
for attr in ["name", "age", "job", "address"]:
value = getattr(john, attr, "Not available")
print(f"{attr.capitalize()}: {value}")
Execute o código atualizado:
python3 /home/labex/project/dynamic_attributes.py
Você deve ver:
Original attributes:
Name: John
Age: 30
Job: Developer
Modifying attributes using setattr():
Modified attributes:
Name: John Smith
Age: 31
Job: Senior Developer
Address: 123 Main St
Accessing attributes using getattr():
Name: John Smith
Age: 31
Job: Senior Developer
Address: 123 Main St
Observe que fomos capazes de modificar atributos existentes e também adicionar um atributo completamente novo (address) que não foi definido na classe.
Exemplo Prático
Vamos criar um exemplo mais prático onde o acesso e a modificação de atributos dinâmicos são úteis. Crie um arquivo chamado data_processor.py no diretório /home/labex/project:
class DataRecord:
def __init__(self):
## Start with no attributes
pass
## Create a function to process a dictionary into an object
def dict_to_object(data_dict):
record = DataRecord()
for key, value in data_dict.items():
setattr(record, key, value)
return record
## Sample data (could come from a database, API, etc.)
user_data = {
"user_id": 12345,
"username": "johndoe",
"email": "john@example.com",
"active": True,
"login_count": 27
}
## Convert the dictionary to an object
user = dict_to_object(user_data)
## Access the attributes
print(f"User ID: {user.user_id}")
print(f"Username: {user.username}")
print(f"Email: {user.email}")
print(f"Active: {user.active}")
print(f"Login Count: {user.login_count}")
## We can also add or modify attributes
setattr(user, "last_login", "2023-09-15")
setattr(user, "login_count", 28)
print("\nAfter modifications:")
print(f"Login Count: {user.login_count}")
print(f"Last Login: {user.last_login}")
## We can also access all attributes dynamically
print("\nAll attributes:")
for attr in ["user_id", "username", "email", "active", "login_count", "last_login"]:
value = getattr(user, attr, None)
print(f"{attr}: {value}")
Execute este código:
python3 /home/labex/project/data_processor.py
Você deve ver:
User ID: 12345
Username: johndoe
Email: john@example.com
Active: True
Login Count: 27
After modifications:
Login Count: 28
Last Login: 2023-09-15
All attributes:
user_id: 12345
username: johndoe
email: john@example.com
active: True
login_count: 28
last_login: 2023-09-15
Este exemplo mostra como você pode converter dados de um dicionário (que pode vir de um banco de dados, API ou arquivo) em um objeto e, em seguida, acessar ou modificar seus atributos dinamicamente.
Aplicações Práticas de Atributos de Objetos
Agora que entendemos como acessar e modificar atributos de objetos, vamos explorar algumas aplicações práticas desses conceitos. Criaremos um sistema simples de gerenciamento de inventário para demonstrar como os atributos de objetos podem ser usados em aplicações do mundo real.
Criando um Sistema de Inventário
Vamos criar um arquivo chamado inventory.py no diretório /home/labex/project:
class Product:
def __init__(self, product_id, name, price, quantity):
self.product_id = product_id
self.name = name
self.price = price
self.quantity = quantity
def total_value(self):
return self.price * self.quantity
def display_info(self):
return f"Product: {self.name} (ID: {self.product_id})\nPrice: ${self.price:.2f}\nQuantity: {self.quantity}\nTotal Value: ${self.total_value():.2f}"
class Inventory:
def __init__(self):
self.products = {}
def add_product(self, product):
self.products[product.product_id] = product
print(f"Added: {product.name}")
def remove_product(self, product_id):
if product_id in self.products:
product = self.products.pop(product_id)
print(f"Removed: {product.name}")
return True
print(f"Product with ID {product_id} not found.")
return False
def update_quantity(self, product_id, new_quantity):
if product_id in self.products:
product = self.products[product_id]
old_quantity = product.quantity
product.quantity = new_quantity
print(f"Updated quantity of {product.name} from {old_quantity} to {new_quantity}")
return True
print(f"Product with ID {product_id} not found.")
return False
def display_inventory(self):
if not self.products:
print("Inventory is empty.")
return
print("\n===== Current Inventory =====")
total_value = 0
for product in self.products.values():
print(f"\n{product.display_info()}")
total_value += product.total_value()
print(f"\nTotal Inventory Value: ${total_value:.2f}")
print("============================")
## Create an inventory
inventory = Inventory()
## Create some products
laptop = Product(1, "Laptop", 999.99, 5)
phone = Product(2, "Smartphone", 499.95, 10)
headphones = Product(3, "Wireless Headphones", 149.99, 15)
## Add products to inventory
inventory.add_product(laptop)
inventory.add_product(phone)
inventory.add_product(headphones)
## Display the inventory
inventory.display_inventory()
## Update quantities
inventory.update_quantity(1, 7) ## Increase laptop quantity
inventory.update_quantity(3, 10) ## Decrease headphones quantity
## Display the updated inventory
inventory.display_inventory()
## Remove a product
inventory.remove_product(2) ## Remove smartphones
## Display the final inventory
inventory.display_inventory()
Execute este código:
python3 /home/labex/project/inventory.py
Você deve ver uma saída semelhante a:
Added: Laptop
Added: Smartphone
Added: Wireless Headphones
===== Current Inventory =====
Product: Laptop (ID: 1)
Price: $999.99
Quantity: 5
Total Value: $4999.95
Product: Smartphone (ID: 2)
Price: $499.95
Quantity: 10
Total Value: $4999.50
Product: Wireless Headphones (ID: 3)
Price: $149.99
Quantity: 15
Total Value: $2249.85
Total Inventory Value: $12249.30
============================
Updated quantity of Laptop from 5 to 7
Updated quantity of Wireless Headphones from 15 to 10
===== Current Inventory =====
Product: Laptop (ID: 1)
Price: $999.99
Quantity: 7
Total Value: $6999.93
Product: Smartphone (ID: 2)
Price: $499.95
Quantity: 10
Total Value: $4999.50
Product: Wireless Headphones (ID: 3)
Price: $149.99
Quantity: 10
Total Value: $1499.90
Total Inventory Value: $13499.33
============================
Removed: Smartphone
===== Current Inventory =====
Product: Laptop (ID: 1)
Price: $999.99
Quantity: 7
Total Value: $6999.93
Product: Wireless Headphones (ID: 3)
Price: $149.99
Quantity: 10
Total Value: $1499.90
Total Inventory Value: $8499.83
============================
Trabalhando com Atributos Dinâmicos
Vamos aprimorar nosso sistema de inventário para lidar com atributos dinâmicos usando getattr() e setattr(). Crie um arquivo chamado enhanced_inventory.py no diretório /home/labex/project:
class Product:
def __init__(self, product_id, name, price, quantity, **kwargs):
self.product_id = product_id
self.name = name
self.price = price
self.quantity = quantity
## Add any additional attributes provided
for key, value in kwargs.items():
setattr(self, key, value)
def total_value(self):
return self.price * self.quantity
def display_info(self):
result = [f"Product: {self.name} (ID: {self.product_id})",
f"Price: ${self.price:.2f}",
f"Quantity: {self.quantity}",
f"Total Value: ${self.total_value():.2f}"]
## Display additional attributes
standard_attrs = {'product_id', 'name', 'price', 'quantity'}
for attr in dir(self):
if not attr.startswith('__') and not callable(getattr(self, attr)) and attr not in standard_attrs:
value = getattr(self, attr)
result.append(f"{attr.replace('_', ' ').title()}: {value}")
return '\n'.join(result)
class Inventory:
def __init__(self):
self.products = {}
def add_product(self, product):
self.products[product.product_id] = product
print(f"Added: {product.name}")
def update_attribute(self, product_id, attribute, value):
if product_id in self.products:
product = self.products[product_id]
old_value = getattr(product, attribute, None)
setattr(product, attribute, value)
print(f"Updated {attribute} of {product.name} from {old_value} to {value}")
return True
print(f"Product with ID {product_id} not found.")
return False
def display_inventory(self):
if not self.products:
print("Inventory is empty.")
return
print("\n===== Current Inventory =====")
total_value = 0
for product in self.products.values():
print(f"\n{product.display_info()}")
total_value += product.total_value()
print(f"\nTotal Inventory Value: ${total_value:.2f}")
print("============================")
## Create an inventory
inventory = Inventory()
## Create products with additional attributes
laptop = Product(1, "Laptop", 999.99, 5, brand="TechPro", model="X5", color="Silver", warranty_years=2)
phone = Product(2, "Smartphone", 499.95, 10, brand="MobiCom", model="Galaxy", color="Black", has_5g=True)
headphones = Product(3, "Wireless Headphones", 149.99, 15, brand="AudioMax", battery_life_hours=20, is_noise_cancelling=True)
## Add products to inventory
inventory.add_product(laptop)
inventory.add_product(phone)
inventory.add_product(headphones)
## Display the inventory
inventory.display_inventory()
## Update a standard attribute
inventory.update_attribute(1, "price", 1099.99)
## Update a custom attribute
inventory.update_attribute(3, "battery_life_hours", 25)
## Add a new attribute to an existing product
inventory.update_attribute(2, "water_resistant", True)
## Display the updated inventory
inventory.display_inventory()
Execute este código:
python3 /home/labex/project/enhanced_inventory.py
Você deve ver uma saída semelhante a:
Added: Laptop
Added: Smartphone
Added: Wireless Headphones
===== Current Inventory =====
Product: Laptop (ID: 1)
Price: $999.99
Quantity: 5
Total Value: $4999.95
Brand: TechPro
Color: Silver
Model: X5
Warranty Years: 2
Product: Smartphone (ID: 2)
Price: $499.95
Quantity: 10
Total Value: $4999.50
Brand: MobiCom
Color: Black
Has 5g: True
Model: Galaxy
Product: Wireless Headphones (ID: 3)
Price: $149.99
Quantity: 15
Total Value: $2249.85
Battery Life Hours: 20
Brand: AudioMax
Is Noise Cancelling: True
Total Inventory Value: $12249.30
============================
Updated price of Laptop from 999.99 to 1099.99
Updated battery_life_hours of Wireless Headphones from 20 to 25
Updated water_resistant of Smartphone from None to True
===== Current Inventory =====
Product: Laptop (ID: 1)
Price: $1099.99
Quantity: 5
Total Value: $5499.95
Brand: TechPro
Color: Silver
Model: X5
Warranty Years: 2
Product: Smartphone (ID: 2)
Price: $499.95
Quantity: 10
Total Value: $4999.50
Brand: MobiCom
Color: Black
Has 5g: True
Model: Galaxy
Water Resistant: True
Product: Wireless Headphones (ID: 3)
Price: $149.99
Quantity: 15
Total Value: $2249.85
Battery Life Hours: 25
Brand: AudioMax
Is Noise Cancelling: True
Total Inventory Value: $12749.30
============================
Neste sistema de inventário aprimorado, demonstramos como usar getattr() e setattr() em uma aplicação mais complexa:
- A classe
Productaceita atributos adicionais através de**kwargse os define dinamicamente comsetattr() - O método
display_info()usagetattr()para exibir todos os atributos do produto - O método
update_attribute()na classeInventoryusagetattr()para recuperar o valor atual esetattr()para atualizá-lo
Essa abordagem oferece grande flexibilidade, permitindo-nos lidar com produtos com diferentes conjuntos de atributos sem modificar a definição da classe.
Resumo
Neste laboratório, você aprendeu a trabalhar com atributos de objetos Python, uma habilidade fundamental para uma programação Python eficaz. Aqui está um resumo do que você realizou:
Criando Classes e Objetos: Você aprendeu a criar classes Python com atributos e métodos, e como instanciar objetos a partir dessas classes.
Acessando Atributos de Objetos: Você explorou várias maneiras de acessar atributos de objetos, incluindo:
- Usando a notação de ponto (
object.attribute) - Usando a função
getattr()para acesso dinâmico
- Usando a notação de ponto (
Modificando Atributos de Objetos: Você aprendeu a alterar atributos de objetos usando:
- Atribuição direta com notação de ponto (
object.attribute = value) - A função
setattr()para modificação dinâmica
- Atribuição direta com notação de ponto (
Aplicações Práticas: Você aplicou esses conceitos para construir aplicações práticas:
- Um sistema simples de gerenciamento de inventário
- Um sistema aprimorado com tratamento de atributos dinâmicos
Essas habilidades o ajudarão a construir aplicações Python mais flexíveis e poderosas. Entender como trabalhar com atributos de objetos é essencial para tarefas como processamento de dados, gerenciamento de configuração e criação de sistemas de software extensíveis.
Para prática adicional, considere expandir o sistema de gerenciamento de inventário com recursos adicionais, como:
- Filtrar produtos com base em atributos
- Classificar produtos por diferentes critérios
- Adicionar validação para modificações de atributos
- Implementar serialização para salvar e carregar dados de inventário



