Wie man die Attribute eines Python-Objekts zugreift und modifiziert

PythonPythonBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Introduction

In this tutorial, we will explore how to access and modify attributes of Python objects. Understanding how to work with object properties is a fundamental skill for Python programming. By the end of this lab, you will be able to create objects, access their attributes using different methods, and modify those attributes to change object behavior.

Python is an object-oriented programming language, which means everything in Python is an object with properties and methods. Learning to interact with these objects is essential for building effective Python applications.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python(("Python")) -.-> python/ObjectOrientedProgrammingGroup(["Object-Oriented Programming"]) python/FunctionsGroup -.-> python/function_definition("Function Definition") python/FunctionsGroup -.-> python/scope("Scope") python/FunctionsGroup -.-> python/build_in_functions("Build-in Functions") python/ObjectOrientedProgrammingGroup -.-> python/classes_objects("Classes and Objects") python/ObjectOrientedProgrammingGroup -.-> python/constructor("Constructor") subgraph Lab Skills python/function_definition -.-> lab-395033{{"Wie man die Attribute eines Python-Objekts zugreift und modifiziert"}} python/scope -.-> lab-395033{{"Wie man die Attribute eines Python-Objekts zugreift und modifiziert"}} python/build_in_functions -.-> lab-395033{{"Wie man die Attribute eines Python-Objekts zugreift und modifiziert"}} python/classes_objects -.-> lab-395033{{"Wie man die Attribute eines Python-Objekts zugreift und modifiziert"}} python/constructor -.-> lab-395033{{"Wie man die Attribute eines Python-Objekts zugreift und modifiziert"}} end

Creating a Simple Python Class

Let us begin by understanding what Python classes and objects are, and how to create them.

What are Classes and Objects?

In Python, a class is a blueprint for creating objects. Objects are instances of classes, which contain:

  • Attributes: Variables that store data
  • Methods: Functions that define actions the object can perform

Think of a class as a template and an object as something created from that template.

Creating Your First Class

Let us create a simple Person class with some basic attributes. Open the code editor and create a new file called person.py in the /home/labex/project directory:

## 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)}")

This code defines a Person class with two attributes (name and age) and one method (greet). Let us understand the key components:

  • class Person: - This line declares a new class named Person
  • __init__ - This is a special method called a constructor, which initializes a new object when it is created
  • self - This parameter refers to the object being created or manipulated
  • self.name = name - This creates an attribute called name for the object and assigns it the value passed to the constructor

Now let us run this code to see what happens:

python3 /home/labex/project/person.py

You should see output similar to:

<__main__.Person object at 0x7f8b2c3d9d90>
Type of john: <class '__main__.Person'>

This output tells us that john is an object of the Person class. The hexadecimal number is the memory address where the object is stored.

Creating Multiple Objects

We can create multiple objects from a single class. Let us modify our person.py file to create another Person object:

## 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}")

Run the updated code:

python3 /home/labex/project/person.py

You should see:

First person: John, 30
Second person: Alice, 25

Now we have created two different Person objects, each with their own name and age attributes.

Accessing Object Attributes

Now that we have created objects with attributes, let us learn different ways to access these attributes.

Using Dot Notation

The most common way to access object attributes is using dot notation: object.attribute.

Let us create a new file called access_attributes.py in the /home/labex/project directory:

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}")

Run this code:

python3 /home/labex/project/access_attributes.py

You should see:

Name: John
Age: 30
Job: Developer
Greeting: Hello, my name is John and I am 30 years old.

Accessing Attributes Using Variables

Sometimes you might need to access an attribute when you only have its name as a string. This can be useful when you are working with dynamically determined attribute names.

Let us modify our access_attributes.py file:

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}")

Run the code:

python3 /home/labex/project/access_attributes.py

You should see:

Accessing attributes using dot notation:
Name: John
Age: 30
Job: Developer
Greeting: Hello, my name is John and I am 30 years old.

This is a bit cumbersome. In the next step, we will learn a more elegant way to access attributes dynamically.

Using getattr() and setattr() Functions

Python provides built-in functions to access and modify object attributes dynamically. These are particularly useful when you want to work with attribute names that are not known until runtime.

The getattr() Function

The getattr() function allows you to access an attribute using its name as a string. The syntax is:

getattr(object, attribute_name, default_value)
  • object: The object whose attribute you want to access
  • attribute_name: A string containing the name of the attribute
  • default_value: An optional value to return if the attribute does not exist

Let us create a new file called dynamic_attributes.py in the /home/labex/project directory:

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}")

Run this code:

python3 /home/labex/project/dynamic_attributes.py

You should see:

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.

Notice that for the address attribute, which does not exist, getattr() returns our default value "Not available" instead of raising an error.

The setattr() Function

The setattr() function allows you to set an attribute using its name as a string. The syntax is:

setattr(object, attribute_name, value)
  • object: The object whose attribute you want to set
  • attribute_name: A string containing the name of the attribute
  • value: The value to assign to the attribute

Let us modify our dynamic_attributes.py file to include examples of using 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}")

Run the updated code:

python3 /home/labex/project/dynamic_attributes.py

You should see:

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

Notice that we were able to modify existing attributes and also add a completely new attribute (address) that was not defined in the class.

Practical Example

Let us create a more practical example where dynamic attribute access and modification are useful. Create a file called data_processor.py in the /home/labex/project directory:

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}")

Run this code:

python3 /home/labex/project/data_processor.py

You should see:

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

This example shows how you can convert data from a dictionary (which might come from a database, API, or file) into an object, and then access or modify its attributes dynamically.

Practical Applications of Object Attributes

Now that we understand how to access and modify object attributes, let us explore some practical applications of these concepts. We will create a simple inventory management system to demonstrate how object attributes can be used in real-world applications.

Creating an Inventory System

Let us create a file called inventory.py in the /home/labex/project directory:

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()

Run this code:

python3 /home/labex/project/inventory.py

You should see output similar to:

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
============================

Working with Dynamic Attributes

Let us enhance our inventory system to handle dynamic attributes using getattr() and setattr(). Create a file called enhanced_inventory.py in the /home/labex/project directory:

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()

Run this code:

python3 /home/labex/project/enhanced_inventory.py

You should see output similar to:

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
============================

In this enhanced inventory system, we demonstrated how to use getattr() and setattr() in a more complex application:

  1. The Product class accepts additional attributes through **kwargs and sets them dynamically with setattr()
  2. The display_info() method uses getattr() to display all the attributes of the product
  3. The update_attribute() method in the Inventory class uses getattr() to retrieve the current value and setattr() to update it

This approach provides great flexibility, allowing us to handle products with different sets of attributes without modifying the class definition.

Summary

In this lab, you have learned how to work with Python object attributes, which is a fundamental skill for effective Python programming. Here is a summary of what you have accomplished:

  1. Creating Classes and Objects: You learned how to create Python classes with attributes and methods, and how to instantiate objects from these classes.

  2. Accessing Object Attributes: You explored various ways to access object attributes, including:

    • Using dot notation (object.attribute)
    • Using the getattr() function for dynamic access
  3. Modifying Object Attributes: You learned how to change object attributes using:

    • Direct assignment with dot notation (object.attribute = value)
    • The setattr() function for dynamic modification
  4. Practical Applications: You applied these concepts to build practical applications:

    • A simple inventory management system
    • An enhanced system with dynamic attribute handling

These skills will help you build more flexible and powerful Python applications. Understanding how to work with object attributes is essential for tasks such as data processing, configuration management, and creating extensible software systems.

For further practice, consider expanding the inventory management system with additional features, such as:

  • Filtering products based on attributes
  • Sorting products by different criteria
  • Adding validation for attribute modifications
  • Implementing serialization to save and load inventory data