还不清楚魔术方法?
可以看看本系列开篇:【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 大三小白新手菜鸟咸鱼本科生长期更新强烈建议不要关注!