Python的魔术方法

Python里面有一些以双下划线的(_)开头和结尾的方法,他们被称为魔术方法或者特殊方法,他虽然不是必须的,但是因为它能够自动执行而不用像普通方法一样调用。这样神奇的功能为面向对象编程提供了丰富的扩展性,让我们能够自定义自己的数据类型、算术运算等等。

使用魔术方法要注意避免与Python内置的魔术方法发生冲突,最好检查一下官方文档

Python内置常用魔术方法

1. 初始化与销毁

__init__

用于初始化新创建的对象。

class MyClass:  
    def __init__(self, value):  
        self.value = value  
  
# 使用  
obj = MyClass(10)  
print(obj.value)  # 输出: 10
__del__

当对象即将被销毁时调用。

class MyClass:  
    def __init__(self):  
        print("Object created")  
      
    def __del__(self):  
        print("Object destroyed")  
  
# 使用  
obj = MyClass()  # 输出: Object created  
del obj  # 输出: Object destroyed

2. 字符串表示

__str__

返回对象的字符串表示形式。

class Person:  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age  
      
    def __str__(self):  
        return f"Person(name={self.name}, age={self.age})"  
  
# 使用  
p = Person("Alice", 30)  
print(p)  # 输出: Person(name=Alice, age=30)
__repr__

返回对象的官方字符串表示形式,通常用于调试。

class Person:  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age  
      
    def __repr__(self):  
        return f"Person({self.name!r}, {self.age})"  
  
# 使用  
p = Person("Alice", 30)  
print(repr(p))  # 输出: Person('Alice', 30)

3. 算术运算符

__add__

定义对象加法运算的行为。

class Vector:  
    def __init__(self, x, y):  
        self.x = x  
        self.y = y  
      
    def __add__(self, other):  
        return Vector(self.x + other.x, self.y + other.y)  
  
# 使用  
v1 = Vector(1, 2)  
v2 = Vector(3, 4)  
v3 = v1 + v2  
print(v3.x, v3.y)  # 输出: 4 6

4. 比较运算符

__eq__

定义对象相等性的比较。

class Person:  
    def __init__(self, name):  
        self.name = name  
      
    def __eq__(self, other):  
        if isinstance(other, Person):  
            return self.name == other.name  
        return False  
  
# 使用  
p1 = Person("Alice")  
p2 = Person("Alice")  
print(p1 == p2)  # 输出: True

5. 容器相关

__len__

返回容器(如列表或自定义容器)的长度。

class MyList:  
    def __init__(self, *args):  
        self.items = list(args)  
      
    def __len__(self):  
        return len(self.items)  
  
# 使用  
my_list = MyList(1, 2, 3, 4)  
print(len(my_list))  # 输出: 4

6. 迭代器与生成器

__iter__

返回迭代器对象,使对象可以用于迭代(如在for循环中)。

class MyRange:  
    def __init__(self, start, end):  
        self.value = start  
        self.end = end  
      
    def __iter__(self):  
        return self  
      
    def __next__(self):  
        if self.value < self.end:  
            current = self.value  
            self.value += 1  
            return current  
        else:  
            raise StopIteration  
  
# 使用  
for i in MyRange(0, 5):  
    print(i)  # 输出: 0

7. 上下文管理

__enter__ 和 __exit__

定义对象作为上下文管理器时的行为,通常与with语句一起使用。

class ManagedFile:  
    def __init__(self, filename):  
        self.filename = filename  
      
    def __enter__(self):  
        self.file = open(self.filename, 'r')  
        return self.file  
      
    def __exit__(self, exc_type, exc_value, traceback):  
        self.file.close()  
  
# 使用  
with ManagedFile('example.txt') as file:  
    data = file.read()  
    print(data)  
# 文件在with块结束后自动关闭

8. 属性访问

__getattr__

当尝试访问不存在的属性时调用。

class MyObject:  
    def __init__(self):  
        self.existing_attribute = 'Hello'  
      
    def __getattr__(self, name):  
        return f"Unknown attribute: {name}"  
  
# 使用  
obj = MyObject()  
print(obj.existing_attribute)  # 输出: Hello  
print(obj.non_existing_attribute)  # 输出: Unknown attribute: non_existing_attribute
__setattr__

当为对象设置属性时调用。

class MyObject:  
    def __init__(self):  
        self._internal_state = {}  
      
    def __setattr__(self, name, value):  
        if name.startswith('_'):  
            super().__setattr__(name, value)  
        else:  
            self._internal_state[name] = value  
  
# 使用  
obj = MyObject()  
obj.my_attribute = 'value'  
print(obj._internal_state)  # 输出: {'my_attribute': 'value'}
__delattr__

当删除对象属性时调用。

class MyObject:  
    def __init__(self):  
        self.existing_attribute = 'Hello'  
      
    def __delattr__(self, name):  
        if hasattr(self, name):  
            delattr(super(MyObject, self), name)  
        else:  
            raise AttributeError(f"No attribute named {name}")  
  
# 使用  
obj = MyObject()  
del obj.existing_attribute  
print(hasattr(obj, 'existing_attribute'))  # 输出: False

9. 转换

__int__

定义到整数的转换。

class Temperature:  
    def __init__(self, celsius):  
        self.celsius = celsius  
      
    def __int__(self):  
        return self.celsius  
  
# 使用  
temp = Temperature(25)  
celsius = int(temp)  
print(celsius)  # 输出: 25
__float__

定义到浮点数的转换。

class Fraction:  
    def __init__(self, numerator, denominator):  
        self.numerator = numerator  
        self.denominator = denominator  
      
    def __float__(self):  
        return self.numerator / self.denominator  
  
# 使用  
fraction = Fraction(1, 2)  
float_value = float(fraction)  
print(float_value)  # 输出: 0.5

这些只是Python中魔术方法的一部分,实际上还有很多其他魔术方法可用于定义对象的不同行为。使用魔术方法时,需要确保遵循它们的预期用途,并仔细阅读官方文档以获取更详细的信息和最佳实践。

注意不存过度使用魔术方法,因为

1.并不是所有Python都熟悉,所以会影响可读性与可维护性,

2.此外因为其自动调用,尤其是哪些修改对象状态的方法(如__setattr__),可能会导致代码中出现意外的副作用,从而增加调试和排查问题的难度。

3.虽然魔术方法在某些情况下可以提高代码的灵活性和便利性,但它们也可能引入额外的性能开销

4.魔术方法通常允许开发者深入对象的内部状态和行为。然而,过度使用魔术方法可能会破坏对象的封装性,使得对象的状态和行为变得更容易被外部代码修改和干扰。这可能导致代码的健壮性和可重用性降低。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是阿尘呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值