【Python】魔法方法是真的魔法! (第一期)

还不清楚魔术方法?
可以看看本系列开篇:【Python】小子!是魔术方法!-CSDN博客

第一期

__new____init__这两个魔术方法有什么作用,它们的区别是什么?

  • __new__函数用于从一个class创建一个object的过程——有返回值,返回新建的object实例
  • __init__函数则无返回值,是在创建出object后对其进行初始化的过程。
  • 如果只需要初始化object而不需要客制化创建过程,通常只用到__init__;而当需要控制object创建逻辑,例如实现单例或者与metaclass相关的功能时,则需要用到__new__
class Singleton:
    _instance = None
    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super().__new__(cls)
        return cls._instance  # 永远返回同一个实例
    def __init__(self, value):
        self.value = value  # 每次初始化都会执行!
a = Singleton(1)
b = Singleton(2)
print(a is b)  # True (是同一个实例)
print(a.value) # 2 (但初始化被多次执行!)

__str____repr__这两个魔术方法有什么区别,它们一般在什么场景下被调用?__format__魔术方法在何时被调用,有何用途?

__str____repr__都是返回object字符串表示的魔术方法,但语义不同:

  • __str__返回的是人类易读的字符串,注重可读性;
  • __repr__返回的信息更详细。

通常print()会使用__str__方法,若未定义__str__,则会自动调用__repr__方法。当尝试以特定格式打印object或使用format指定格式化方式时,可能会调用__format__魔术方法。它提供了一种处理并生成格式化字符串的方法,例如根据不同的基数转换整数的打印样式。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
    def __str__(self):
        return f"{self.name} ({self.age}岁)"  # 友好展示
    
    def __repr__(self):
        return f"Person('{self.name}', {self.age})"  # 开发者视角
    
    def __format__(self, format_spec):
        if format_spec == 'verbose':
            return f"{self.name} is {self.age} years old"
        return str(self)

# 测试
p = Person('张三', 25)
print(str(p))    # 输出: 张三 (25岁) -> 调用__str__
print(repr(p))   # 输出: Person('张三', 25) -> 调用__repr__
print(f"{p}")    # 输出: 张三 (25岁) -> 默认调用__str__
print(f"{p:verbose}")  # 输出: 张三是 25 years old -> 调用__format__

__bin__魔术方法的作用是什么?

__bin__魔术方法在尝试用自定义class建立binary(二进制)表示时会被调用,它返回该object的二进制表示。除非需要自定义object的二进制表示,否则这个方法通常也不会被直接使用。

class BinaryNumber:
    def __init__(self, value):
        self.value = value
        
    def __bin__(self):
        return bin(self.value)  # 返回二进制表示
    
    # 通常也实现相关数值魔术方法
    def __add__(self, other):
        return BinaryNumber(self.value + other.value)

# 测试
num = BinaryNumber(10)
print(bin(num))  # 输出: 0b1010 -> 调用__bin__

num2 = BinaryNumber(5)
result = num + num2
print(bin(result))  # 输出: 0b1111 (15的二进制)

__del__函数在Python中是如何工作的,它的应用场景有哪些?

__del__函数可以粗略理解为一个析构函数,当对象被释放时可以执行相应的清理工作。然而,由于Python中对象释放机制的复杂性(如引用计数和垃圾回收),__del__函数的实际使用并不直观且可控性较差。

class ResourceLogger:
    def __init__(self, name):
        self.name = name
        print(f"资源 {self.name} 已分配")
        
    def close(self):
        print(f"资源 {self.name} 已显式释放")
    
    def __del__(self):
        print(f"警告:资源 {self.name} 通过__del__释放 (非确定性)")
        self.close()

# 测试
def test():
    res = ResourceLogger("数据库连接")
    res.close()  # 显式释放优于__del__

print("--- 测试开始 ---")
test()
print("--- 测试结束 ---")
# 可能输出:
# 资源 数据库连接 已分配
# 资源 数据库连接 已显式释放
# 警告:资源 数据库连接 通过__del__释放 (非确定性)
# 资源 数据库连接 已显式释放

关于作者

  • CSDN 大三小白新手菜鸟咸鱼本科生长期更新强烈建议不要关注

更多关于Python

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Sonetto1999

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

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

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

打赏作者

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

抵扣说明:

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

余额充值