南通市文章资讯

Python双下划线开头的具体使用

2026-03-24 23:59:02 浏览次数:0
详细信息

Python中以双下划线开头的方法和属性(如 __init__)称为特殊方法魔法方法(magic methods),它们的命名和使用遵循严格的约定。以下是详细分类和具体用法:

一、核心用途分类

1. 对象生命周期控制

class MyClass:
    def __init__(self, value):      # 构造器
        self.value = value

    def __del__(self):              # 析构器(谨慎使用)
        print("对象被销毁")

obj = MyClass(10)  # 触发 __init__
del obj           # 触发 __del__

2. 运算符重载

class Vector:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __add__(self, other):        # 重载 + 运算符
        return Vector(self.x + other.x, self.y + other.y)

    def __str__(self):              # 重载 print()
        return f"Vector({self.x}, {self.y})"

v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2)  # Vector(4, 6)

3. 容器类型模拟

class Stack:
    def __init__(self):
        self._items = []

    def __len__(self):              # 重载 len()
        return len(self._items)

    def __getitem__(self, index):   # 重载 []
        return self._items[index]

    def __setitem__(self, index, value):  # 支持 s[0]=x
        self._items[index] = value

s = Stack()
s._items = [1, 2, 3]
print(len(s))    # 3
print(s[1])      # 2

4. 属性访问控制

class Secret:
    def __init__(self):
        self.public = "公开"
        self._protected = "受保护"
        self.__private = "私有"      # 名称修饰(name mangling)

    def __getattr__(self, name):    # 访问不存在的属性时触发
        return f"{name} 不存在"

s = Secret()
print(s.public)           # "公开"
print(s._protected)       # "受保护"
print(s._Secret__private) # "私有"(实际被重命名为 _Secret__private)
print(s.abc)              # "abc 不存在"(触发 __getattr__)

二、常见魔法方法速查表

分类 方法 触发场景
构造/析构 __new__ 创建实例时第一个调用
__init__ 对象初始化
__del__ 对象销毁
字符串表示 __str__ print(obj)str(obj)
__repr__ repr(obj)、交互式显示
运算符 __add__/__sub__ +/- 运算
__eq__/__lt__ ==/< 比较
容器操作 __len__ len(obj)
__getitem__ obj[key]
__iter__ for x in obj
属性管理 __getattr__ 访问不存在的属性
__setattr__ 设置属性时
__getattribute__ 所有属性访问时
上下文管理 __enter__/__exit__ with 语句

三、重要细节

1. 名称修饰(Name Mangling)

class Test:
    def __init__(self):
        self.__secret = 10     # 实际变为 _Test__secret

t = Test()
print(t._Test__secret)  # 可以访问
print(t.__secret)       # AttributeError

2. 避免无限递归

class Demo:
    def __init__(self):
        self.__dict__['x'] = 1  # 绕过 __setattr__

    def __setattr__(self, name, value):
        # 错误:self.name = value 会再次调用 __setattr__ 导致递归
        # 正确:
        self.__dict__[name] = value

3. 上下文管理器示例

class FileManager:
    def __init__(self, filename):
        self.filename = filename

    def __enter__(self):
        self.file = open(self.filename, 'w')
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

with FileManager("test.txt") as f:
    f.write("Hello")

四、使用建议

不要随意创建自定义双下划线方法,除非需要特殊行为 优先使用公开接口,私有属性用单下划线 _var 魔法方法不是设计模式替代品,避免过度使用 阅读内置类型源码(如 collections.abc)学习标准实现

五、示例:完整类设计

class Rational:
    """有理数类示例"""
    def __init__(self, numerator, denominator=1):
        self.n = numerator
        self.d = denominator

    def __add__(self, other):
        # 简化版加法
        return Rational(self.n + other.n, self.d)

    def __str__(self):
        return f"{self.n}/{self.d}"

    def __repr__(self):
        return f"Rational({self.n}, {self.d})"

    def __float__(self):
        return self.n / self.d

r1 = Rational(1, 2)
r2 = Rational(3, 2)
print(r1 + r2)    # 4/2
print(float(r1))  # 0.5

记住:双下划线方法让Python对象能够集成到语言基础设施中,正确使用它们可以创建出行为类似内置类型的优雅对象。

相关推荐