基础魔法方法

PythonPythonIntermediate
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

在本教程中,我们将探索 Python 中的基本魔法方法(magic methods)。魔法方法,也称为 "dunder" 方法(双下划线方法),允许你定义 Python 对象在特定情况下的行为,从而实现高级和自定义的对象操作。


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/ObjectOrientedProgrammingGroup -.-> python/classes_objects("Classes and Objects") python/ObjectOrientedProgrammingGroup -.-> python/constructor("Constructor") python/ObjectOrientedProgrammingGroup -.-> python/polymorphism("Polymorphism") python/ObjectOrientedProgrammingGroup -.-> python/encapsulation("Encapsulation") subgraph Lab Skills python/function_definition -.-> lab-7836{{"基础魔法方法"}} python/classes_objects -.-> lab-7836{{"基础魔法方法"}} python/constructor -.-> lab-7836{{"基础魔法方法"}} python/polymorphism -.-> lab-7836{{"基础魔法方法"}} python/encapsulation -.-> lab-7836{{"基础魔法方法"}} end

对象初始化与表示

在本节中,我们将探索 Python 中的对象初始化和表示魔法方法。这些方法允许你为创建对象和将其表示为人类可读且明确的字符串定义自定义行为。

__init__

__init__ 方法在对象创建时被调用。它用于初始化对象的属性。

让我们从一个简单的对象开始。在 person.py 中,创建一个名为 Person 的类,该类具有两个属性。

class Person:
    def __init__(self, name: str, age: int):
        """
        使用名称和年龄初始化 Person 对象。

        :param name: 人的名称。
        :param age: 人的年龄。
        """
        self.name = name
        self.age = age

__str__

__str__ 方法由内置函数 str()print() 函数调用,以获取对象的人类可读字符串表示。

    ## ... (person.py 中的先前代码)

    def __str__(self) -> str:
        """
        返回 Person 对象的人类可读字符串表示。

        :return: 描述人的字符串。
        """
        return f"{self.name} is {self.age} years old."

__repr__

__repr__ 方法由内置函数 repr() 调用,并在交互式解释器中使用,以获取一个字符串表示,如果可能,该字符串可用于重新创建对象。

    ## ... (person.py 中的先前代码)

    def __repr__(self) -> str:
        """
        返回 Person 对象的字符串表示,该字符串可用于重新创建对象。

        :return: 格式为 'Person(name, age)' 的字符串。
        """
        return f"Person('{self.name}', {self.age})"

示例:使用基本魔法方法

现在我们已经为 Person 类定义了基本的魔法方法,让我们看看它们在 init_repr_example.py 中是如何工作的:

from person import Person

## 创建一个新的 Person 对象
p = Person("Alice", 30)

## 使用 print 函数调用 __str__ 方法
print(p)  ## 输出:Alice is 30 years old.

## 在交互式解释器中使用 __repr__ 方法
print(repr(p))  ## 输出:Person('Alice', 30)

然后在终端中输入以下命令以执行脚本。

python init_repr_example.py

对象比较

在本节中,我们将探索 Python 中用于对象比较的魔法方法。这些方法允许你为类的对象定义自定义的比较逻辑。

__eq__

__eq__ 方法用于判断两个对象是否相等。它由 == 运算符调用。

    ## ... (person.py 中的先前代码)

    def __eq__(self, other: "Person") -> bool:
        """
        比较两个 Person 对象是否相等。

        :param other: 要比较的另一个 Person 对象。
        :return: 如果两个对象具有相同的名称和年龄,则返回 True,否则返回 False。
        """
        if isinstance(other, Person):
            return self.name == other.name and self.age == other.age
        return False

__ne__

__ne__ 方法用于判断两个对象是否不相等。它由 != 运算符调用。

    ## ... (person.py 中的先前代码)

    def __ne__(self, other: "Person") -> bool:
        """
        比较两个 Person 对象是否不相等。

        :param other: 要比较的另一个 Person 对象。
        :return: 如果对象的名称或年龄不同,则返回 True,否则返回 False。
        """
        return not self.__eq__(other)

__lt__

__lt__ 方法用于判断一个对象是否小于另一个对象。它由 < 运算符调用。

    ## ... (person.py 中的先前代码)

    def __lt__(self, other: "Person") -> bool:
        """
        比较两个 Person 对象,判断一个是否小于另一个(基于年龄)。

        :param other: 要比较的另一个 Person 对象。
        :return: 如果当前对象的年龄小于另一个对象的年龄,则返回 True,否则返回 False。
        """
        if isinstance(other, Person):
            return self.age < other.age
        return NotImplemented

__le__

__le__ 方法用于判断一个对象是否小于或等于另一个对象。它由 <= 运算符调用。

    ## ... (person.py 中的先前代码)

    def __le__(self, other: "Person") -> bool:
        """
        比较两个 Person 对象,判断一个是否小于或等于另一个(基于年龄)。

        :param other: 要比较的另一个 Person 对象。
        :return: 如果当前对象的年龄小于或等于另一个对象的年龄,则返回 True,否则返回 False。
        """
        if isinstance(other, Person):
            return self.age <= other.age
        return NotImplemented

__gt__

__gt__ 方法用于判断一个对象是否大于另一个对象。它由 > 运算符调用。

    ## ... (person.py 中的先前代码)

    def __gt__(self, other: "Person") -> bool:
        """
        比较两个 Person 对象,判断一个是否大于另一个(基于年龄)。

        :param other: 要比较的另一个 Person 对象。
        :return: 如果当前对象的年龄大于另一个对象的年龄,则返回 True,否则返回 False。
        """
        if isinstance(other, Person):
            return self.age > other.age
        return NotImplemented

__ge__

__ge__ 方法用于判断一个对象是否大于或等于另一个对象。它由 >= 运算符调用。

    ## ... (person.py 中的先前代码)

    def __ge__(self, other: "Person") -> bool:
        """
        比较两个 Person 对象,判断一个是否大于或等于另一个(基于年龄)。

        :param other: 要比较的另一个 Person 对象。
        :return: 如果当前对象的年龄大于或等于另一个对象的年龄,则返回 True,否则返回 False。
        """
        if isinstance(other, Person):
            return self.age >= other.age
        return NotImplemented

示例:使用对象比较魔法方法

现在我们已经为 Person 类定义了对象比较魔法方法,让我们看看它们在 compare_example.py 中是如何工作的:

from person import Person

## 创建两个 Person 对象
p1 = Person("Alice", 30)
p2 = Person("Bob", 35)

## 使用 __eq__ 和 __ne__ 方法
print(p1 == p2)  ## 输出:False
print(p1 != p2)  ## 输出:True

## 使用 __lt__、__le__、__gt__ 和 __ge__ 方法
print(p1 < p2)  ## 输出:True
print(p1 <= p2)  ## 输出:True
print(p1 > p2)  ## 输出:False
print(p1 >= p2)  ## 输出:False

然后在终端中输入以下命令以执行脚本。

python compare_example.py

对象销毁

在本节中,我们将探索 Python 中的对象销毁魔法方法。该方法允许你在对象即将被销毁时定义自定义行为。

__del__

__del__ 方法在对象即将被销毁时调用。它允许你在对象被垃圾回收之前执行清理任务,例如关闭文件句柄或释放资源。

    ## ... (person.py 中的先前代码)

    def __del__(self):
        """
        在 Person 对象被销毁之前进行清理。
        """
        print(f"Person '{self.name}' is being deleted.")

示例:使用对象销毁魔法方法

现在我们已经为 Person 类定义了对象销毁魔法方法,让我们看看它在 del_example.py 中是如何工作的:

from person import Person

## 创建一个 Person 对象,然后删除它
p = Person("Alice", 30)
del p  ## 输出:Person 'Alice' is being deleted.

然后在终端中输入以下命令以执行脚本。

python del_example.py

需要注意的是,__del__ 方法并不保证在对象不再需要时立即调用。对象的实际删除取决于 Python 解释器的垃圾回收机制。__del__ 方法在垃圾回收器决定从内存中移除对象时被调用。

总结

在本系列教程中,我们探索了 Python 的魔法方法,也称为 "dunder" 方法(双下划线方法),它们允许你在各种情况下为对象定义自定义行为。

通过掌握这些魔法方法,你可以创建更强大和可定制的 Python 类和对象。理解并实现这些方法将使你能够编写更高效、简洁和符合 Python 风格的代码,从而使你的程序更加健壮和易于维护。