1
Current Location:
>
Object-Oriented Programming
Learning Python Object-Oriented Programming from Scratch
Release time:2024-11-07 13:07:01 read: 30
Copyright Statement: This article is an original work of the website and follows the CC 4.0 BY-SA copyright agreement. Please include the original source link and this statement when reprinting.

Article link: https://melooy.com/en/content/aid/399?s=en%2Fcontent%2Faid%2F399

What is Object-Oriented Programming

Python, as an object-oriented programming language, supports both procedural and object-oriented programming paradigms. Procedural programming is centered around processes, executing a series of operations step by step, while object-oriented programming focuses on objects, encapsulating data and methods that operate on the data together to form independent objects. You can think of objects as things in real life, for example, a car is an object with its own attributes (color, weight, etc.) and behaviors (start, accelerate, etc.).

Object-oriented programming has three main characteristics: encapsulation, inheritance, and polymorphism. Encapsulation refers to binding an object's attributes and behaviors together, hiding internal details from the outside world. Inheritance allows subclasses to inherit attributes and methods from parent classes, achieving code reuse. Polymorphism means different objects can have different responses to the same method.

The advantages of object-oriented programming lie in its clear code structure, ease of maintenance, and extensibility. Let's learn step by step how to implement object-oriented programming in Python.

Creating Objects

In Python, we use the class keyword to define a class, which is a template or blueprint for creating objects. Let's start by defining a simple Person class:

class Person:
    def __init__(self, name, age):
        self.name = name  # attribute
        self.age = age

    def say_hello(self):  # method
        print(f"Hello, my name is {self.name}, and I'm {self.age} years old.")

Here we defined a Person class with two attributes name and age, and a say_hello method. Note that the __init__ method is a special method used to initialize the object's attributes when creating the object. The self parameter represents the current instance object, through which we can access and modify the object's attributes and methods.

Creating an object is simple, just instantiate the class:

person1 = Person("John", 25)
person2 = Person("Jane", 30)

We created two Person objects person1 and person2, and assigned them different name and age attribute values. Now we can call the object's methods:

person1.say_hello()  # Output: Hello, my name is John, and I'm 25 years old.
person2.say_hello()  # Output: Hello, my name is Jane, and I'm 30 years old.

As you can see, each object has a different response to the same say_hello method, demonstrating the feature of polymorphism.

Inheritance

Inheritance is a major feature of object-oriented programming, allowing subclasses to inherit attributes and methods from parent classes, achieving code reuse. Let's look at an example:

class Student(Person):
    def __init__(self, name, age, student_id):
        super().__init__(name, age)  # Call the __init__ method of the parent class
        self.student_id = student_id

    def say_hello(self):
        print(f"Hello, I'm a student, my student ID is {self.student_id}.")

Here we defined a Student class that inherits from the Person class. In the __init__ method of the Student class, we called the __init__ method of the parent class Person to initialize the name and age attributes, and then initialized its own student_id attribute.

The Student class also overrides the say_hello method of the parent class, so when we create a Student object and call the say_hello method, it will execute the method implementation of the subclass.

student = Student("Tom", 20, "20220001")
student.say_hello()  # Output: Hello, I'm a student, my student ID is 20220001.

Through inheritance, we can reuse the code of the parent class, while also adding new attributes and methods in the subclass, or overriding the method implementation of the parent class, achieving code reuse and extension.

Encapsulation

Encapsulation is another important feature of object-oriented programming, which packages the object's attributes and methods together, hiding internal implementation details from the outside world. This can improve the security and maintainability of the code.

In Python, we usually use attribute and method names starting with double underscores (__) to implement encapsulation. These attributes and methods are called "private" and cannot be directly accessed externally. Let's look at an example:

class BankAccount:
    def __init__(self, account_number, balance):
        self.__account_number = account_number  # private attribute
        self.__balance = balance

    def deposit(self, amount):
        self.__balance += amount
        print(f"Deposited ${amount}, current balance is ${self.__balance}.")

    def withdraw(self, amount):
        if amount > self.__balance:
            print("Insufficient balance, unable to withdraw.")
        else:
            self.__balance -= amount
            print(f"Withdrew ${amount}, current balance is ${self.__balance}.")

    def get_balance(self):
        return self.__balance

In this BankAccount class, we set the account_number and balance attributes as private, which cannot be directly accessed or modified externally. Correspondingly, we provide deposit and withdraw methods to modify the balance attribute, and a get_balance method to get the value of the balance attribute.

account = BankAccount("6217001234567890", 1000)
account.deposit(500)  # Deposited $500, current balance is $1500.
account.withdraw(2000)  # Insufficient balance, unable to withdraw.
balance = account.get_balance()
print(f"The account balance is ${balance}.")  # The account balance is $1500.

Through encapsulation, we can control access to the object's attributes and methods, preventing external code from directly modifying the internal state of the object, thereby improving the security and maintainability of the code.

Design Patterns

Design patterns are typical solutions to common problems in software design. They provide reusable code templates that can help us write more flexible, maintainable, and extensible code. There are 23 common design patterns, divided into three categories: creational, structural, and behavioral.

Here we'll use the Singleton pattern as an example to introduce how to apply design patterns in Python. The Singleton pattern ensures that a class has only one instance and provides a global access point to it. For example, we can use the Singleton pattern to create a global configuration manager:

class ConfigManager(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self, config_file):
        self.config = self.load_config(config_file)

    def load_config(self, config_file):
        # Specific implementation of loading configuration file
        pass

    def get_config(self, key):
        return self.config.get(key)


config_manager1 = ConfigManager("config.ini")
config_manager2 = ConfigManager("config.ini")

print(config_manager1 is config_manager2)  # True

In this example, we overrode the __new__ method to ensure that the same object is returned each time a ConfigManager instance is created. Through the Singleton pattern, we can ensure that there is only one ConfigManager instance in the entire program, thereby saving memory and improving efficiency.

Design patterns are not limited to object-oriented programming; they can also be applied to functional programming and other programming paradigms. Mastering design patterns can help us write more elegant, maintainable, and extensible code.

Practice: Game Development

Finally, let's practice object-oriented programming through a simple text adventure game. This game has two rooms, the player can move between rooms and interact with items in the rooms.

class Room:
    def __init__(self, name, description):
        self.name = name
        self.description = description
        self.items = []

    def add_item(self, item):
        self.items.append(item)

    def remove_item(self, item):
        self.items.remove(item)

    def interact(self, action):
        if action == "look":
            print(f"You are now in {self.name}. {self.description}")
            if self.items:
                print("There are the following items here:")
                for item in self.items:
                    print(f"- {item}")
            else:
                print("There are no items here.")
        else:
            print("Unrecognized command.")


class WhiteRoom(Room):
    def __init__(self):
        super().__init__("White Room", "This is an empty white room.")
        self.add_item("key")

    def interact(self, action):
        if action == "take key":
            if "key" in self.items:
                print("You picked up the key.")
                self.remove_item("key")
            else:
                print("There is no key here.")
        else:
            super().interact(action)


class RedRoom(Room):
    def __init__(self):
        super().__init__("Red Room", "This is a strange red room, covered with weird symbols.")
        self.add_item("chest")
        self.has_key = False

    def interact(self, action):
        if action == "open chest":
            if self.has_key:
                print("Congratulations, you opened the chest and won!")
            else:
                print("You need a key to open the chest.")
        else:
            super().interact(action)


current_room = WhiteRoom()


def play_game():
    while True:
        action = input("Please enter a command (look/take key/open chest/quit): ").strip().lower()
        if action == "quit":
            break
        elif action in ("go red", "go white"):
            if action == "go red":
                if current_room.__class__.__name__ == "WhiteRoom" and "key" not in current_room.items:
                    print("You need to get the key first before entering the Red Room.")
                else:
                    current_room = RedRoom()
                    current_room.has_key = "key" not in current_room.items
            else:
                current_room = WhiteRoom()
        else:
            current_room.interact(action)


def reset_game():
    global current_room
    current_room = WhiteRoom()


play_game()

In this game, we defined a base class Room and two subclasses WhiteRoom and RedRoom. Each room has its own name, description, and list of items. The interact method is used to handle the player's input commands.

There's a key in the WhiteRoom, and the player needs to get the key before entering the RedRoom. In the RedRoom, if the player has the key, they can open the chest to win.

The play_game function controls the main loop of the game, and the reset_game function is used to reset the game state.

Through this simple example, you should be able to appreciate the advantages and flexibility of object-oriented programming. Using classes and objects can better organize code structure and improve code maintainability and extensibility. You can try adding more rooms, items, and interactions to enrich this game.

In conclusion, Python's object-oriented programming provides us with a powerful programming paradigm that can help us build more robust, flexible, and easy-to-maintain software systems. After mastering the basics of object-oriented programming, you can continue to explore more advanced topics such as design patterns, metaprogramming, etc., to continuously improve your programming skills. The road of programming is long and arduous, but I hope this article can open a door to object-oriented programming for you. Happy learning!

Python Object-Oriented Programming Basics
2024-11-07 10:05:01
Next
Related articles