python常用魔术方法
__new__
__new__
方法是在Python中用于创建对象实例的特殊方法。它通常用于自定义对象的创建和初始化过程。__new__
方法在对象创建之前被调用,而 __init__
方法则在对象创建之后进行初始化。
在以下示例中,我们定义了一个名为 Demo
的类,它是一个单例类,即只能创建一个实例。我们使用 __new__
方法来实现单例模式,确保只创建一个实例。__new__
方法中的逻辑检查了类的 _singleton
属性,如果没有实例存在,就创建一个新的实例,如果存在实例,则直接返回已存在的实例。
class Demo(object):
_singleton = None
def __new__(cls, *args, **kwargs):
"""创建新对象的方法,在类实例化时调用。通常用于定制类的创建方式。"""
if cls._singleton is None:
print("第一次实例化,进行实例化操作")
cls._singleton = super(Demo, cls).__new__(cls)
cls._singleton.initialized = False
else:
print("非第一次实例化,不做操作")
return cls._singleton
if __name__ == '__main__':
d1 = Demo()
d2 = Demo()
输出结果如下:
第一次实例化,进行实例化操作
非第一次实例化,不做操作
__init__
使用__init__
方法来初始化类的属性。
在以下示例中,当我们创建Demo
类的实例d
时,__init__
方法会自动调用,并为实例设置相关属性。之后,我们可以访问这些属性来获取实例的信息。
class Demo(object):
def __init__(self, name, age, *args, **kwargs):
"""构造函数,在对象创建时调用。用于初始化对象的属性。"""
self.name = name
self.age = age
self.args = args
self.kwargs = kwargs
if __name__ == '__main__':
d = Demo("ly", 18, 1, 2, 3, a=1, b=2, c=3)
print(d.name)
print(d.age)
print(d.args)
print(d.kwargs)
输出结果如下:
ly
18
(1, 2, 3)
{'a': 1, 'b': 2, 'c': 3}
__del__
__del__
是Python中的特殊方法,也称为析构方法。它在对象即将被销毁时自动调用,用于执行对象的清理和资源释放操作。当Python解释器退出但对象仍然存活的时候, __del__
并不会 执行。 所以养成一个手工清理的好习惯是很重要的,比如及时关闭连接。
__del__
方法和 del
关键字不是等价的,虽然它们都可以用于销毁对象,但它们的作用和调用时机有重要的不同:
-
__del__
方法:__del__
方法是一个特殊方法,当对象被销毁时(垃圾回收),它会自动调用。__del__
方法允许您在对象被销毁之前执行一些清理操作,例如释放资源或记录日志。- 它通常不应该显式调用,而是由Python的垃圾回收机制自动触发。
-
del
关键字:del
是一个Python关键字,用于删除对象引用或从容器(例如列表或字典)中删除元素。- 它的主要作用是释放变量名与对象之间的关联。当没有引用指向一个对象时,垃圾回收机制可能会在某个时刻销毁该对象。
del
通常用于删除引用,而不是直接销毁对象。对象销毁是由垃圾回收机制负责的,通常在引用计数下降到零时触发。
class Demo(object):
def __init__(self, name, age, *args, **kwargs):
"""构造函数,在对象创建时调用。用于初始化对象的属性。"""
self.name = name
self.age = age
self.args = args
self.kwargs = kwargs
if __name__ == '__main__':
d = Demo("ly", 18, 1, 2, 3, a=1, b=2, c=3)
print(d.name)
print(d.age)
print(d.args)
print(d.kwargs)
输出结果如下:
ly
18
(1, 2, 3)
{'a': 1, 'b': 2, 'c': 3}
__str__ 和 __repr__
__str__
和 __repr__
方法都用于定义类的字符串表示,但它们在用途和返回值上有一些重要的区别:
-
用途:
-
__str__
: 用于返回对象的可读性较好的字符串表示,通常用于用户友好的输出。它应该包含对象的关键信息,以便人类能够理解。 -
__repr__
: 用于返回对象的"官方"字符串表示,通常用于开发和调试目的。它应该包含足够的信息来唯一标识对象,并且通常是一个可以用于创建相同对象的表达式。
-
-
返回值:
-
__str__
: 返回一个字符串,通常是对象的可读性较好的描述。这个描述应该是用户友好的,适合直接显示给终端用户。 -
__repr__
: 返回一个字符串,通常是一个表达式,可以用来创建相同对象。这个字符串应该足够详细,以便能够精确重新创建对象。
-
-
调用时机:
-
__str__
: 当使用str(obj)
或print(obj)
函数时,会调用__str__
方法。 -
__repr__
: 当使用repr(obj)
函数、在交互式环境中输入对象名并回车时,或者在调试工具中查看对象时,会调用__repr__
方法。
-
-
默认实现:
-
如果您不定义
__str__
方法,Python会默认使用__repr__
方法的结果作为字符串表示。 -
如果您不定义
__repr__
方法,Python会默认提供一个通用的实现,通常返回对象的类名和内存地址。
-
class Demo(object):
def __init__(self, name, age, *args, **kwargs):
"""构造函数,在对象创建时调用。用于初始化对象的属性。"""
self.name = name
self.age = age
self.args = args
self.kwargs = kwargs
def __str__(self):
"""返回对象的字符串表示。通常用于 print(obj) 或 str(obj)。当你需要可读性较好的对象表示时,可以重写它。"""
return f"Demo(name: {self.name}, age: {self.age})"
def __repr__(self):
"""返回对象的“官方”字符串表示,通常是可以用于创建对象的表达式。在交互式环境中输入对象名并回车时,会调用该方法。"""
return f"Demo('{self.name}', {self.age})"
if __name__ == '__main__':
d = Demo("ly", 18, 1, 2, 3, a=1, b=2, c=3)
print(str(d)) # 调用__str__方法
print(repr(d)) # 调用__repr__方法
输出结果如下:
Demo(name: ly, age: 18)
Demo('ly', 18)
__len__
__len__
方法用于自定义类的长度,通常在实现容器类或可迭代对象时使用。
当我们创建Demo
类的实例并使用len()
函数来获取它的长度时,实际上是调用了__len__
方法。这使得我们可以使用len()
函数来获取自定义类的长度,就像对待内置的列表、元组等容器一样。
class Demo(object):
def __init__(self, name, age, *args, **kwargs):
"""构造函数,在对象创建时调用。用于初始化对象的属性。"""
self.name = name
self.age = age
self.args = args
self.kwargs = kwargs
def __len__(self):
"""返回对象的长度,通常在容器类中实现,如列表、字典等。可通过内置函数 len(obj) 获取对象的长度。"""
print("使用了len()函数,返回args和kwargs总长度")
return len(self.args) + len(self.kwargs)
if __name__ == '__main__':
d = Demo("ly", 18, 1, 2, 3, a=1, b=2, c=3)
print(len(d))
输出结果如下:
使用了len()函数,返回args和kwargs总长度
6
__getitem__、__setitem__、__delitem__
__getitem__
, __setitem__
, 和 __delitem__
是Python中用于实现索引操作的特殊方法,通常用于自定义类的行为,以使其支持索引访问和操作。
我们创建Demo
类包含了__getitem__
, __setitem__
, 和 __delitem__
方法,以支持索引访问、赋值和删除操作。这三个方法使Demo
对象可以像列表一样被操作。
__getitem__
方法用于获取索引位置的元素。在示例中,d1[2]
调用了__getitem__
方法来获取索引为2的元素。__setitem__
方法用于设置索引位置的元素。在示例中,d1[1] = 10
调用了__setitem__
方法来将索引为1的元素设置为10。__delitem__
方法用于删除索引位置的元素。在示例中,del d1[3]
调用了__delitem__
方法来删除索引为3的元素。
这些方法允许自定义类的行为,以支持索引操作,从而使自定义类更像内置的序列类型。需要注意的是,这些方法应该正确处理索引越界的情况,并引发适当的异常,以确保代码的健壮性。
class Demo(object):
def __init__(self, data):
self.data = data
def __getitem__(self, index):
if 0 <= index < len(self.data):
return self.data[index]
else:
raise IndexError("Index out of range")
def __setitem__(self, index, value):
if 0 <= index < len(self.data):
self.data[index] = value
else:
raise IndexError("Index out of range")
def __delitem__(self, index):
if 0 <= index < len(self.data):
del self.data[index]
else:
raise IndexError("Index out of range")
if __name__ == '__main__':
# 创建Demo类的实例
d1 = Demo([1, 2, 3, 4, 5])
# 使用__getitem__来获取元素
print("Element at index 2:", d1[2])
# 使用__setitem__来设置元素
d1[1] = 10
print("Updated data:", d1.data)
# 使用__delitem__来删除元素
del d1[3]
print("Data after deleting index 3:", d1.data)
输出结果如下:
Element at index 2: 3
Updated data: [1, 10, 3, 4, 5]
Data after deleting index 3: [1, 10, 3, 5]
__getattr__、__setattr__、__delattr__
``getattr,
setattr, 和
delattr` 是Python中用于实现属性访问的特殊方法,通常用于自定义类的属性操作。
我们创建Demo
类包含了__getattr__
, __setattr__
, 和 __delattr__
方法,以支持自定义属性访问和操作。这三个方法使Demo
对象可以像普通属性一样被访问、设置和删除。
__getattr__
方法用于获取属性的值。在示例中,d1.attr1
和d1.attr2
调用了__getattr__
方法来获取属性的值。__setattr__
方法用于设置属性的值。在示例中,d1.attr1 = "Value 1"
和d1.attr2 = "Value 2"
调用了__setattr__
方法来设置属性的值。__delattr__
方法用于删除属性。在示例中,del d1.attr1
调用了__delattr__
方法来删除属性。
这些方法允许自定义类的属性访问和操作。需要注意的是,当使用这些方法时,应该确保正确处理属性不存在和删除不存在的属性的情况,以提高代码的健壮性。在示例中,我们引发了AttributeError
异常以处理这些情况。
class Demo(object):
_data = {}
def __getattr__(self, name):
if name in self._data:
return self._data[name]
else:
raise AttributeError(f"'Demo' object has no attribute '{name}'")
def __setattr__(self, name, value):
self._data[name] = value
def __delattr__(self, name):
if name in self._data:
del self._data[name]
else:
raise AttributeError(f"'Demo' object has no attribute '{name}'")
if __name__ == '__main__':
d1 = Demo()
# 使用__setattr__来设置属性
d1.attr1 = "Value 1"
d1.attr2 = "Value 2"
# 使用__getattr__来获取属性
print("attr1:", d1.attr1)
print("attr2:", d1.attr2)
# 使用__delattr__来删除属性
del d1.attr1
# 尝试获取已删除的属性会引发异常
# print("attr1:", d1.attr1)
输出结果如下:
attr1: Value 1
attr2: Value 2
__iter__、__next__
__iter__
和 __next__
是Python中用于创建可迭代对象和定义迭代行为的两个特殊方法。
-
__iter__
方法:__iter__
方法用于返回一个迭代器对象,通常是self
(即当前对象本身)。- 在一个可迭代对象的类中,通常会定义一个
__iter__
方法,该方法返回一个实现了__next__
方法的迭代器对象。 - 迭代器对象是可迭代对象的一部分,它负责迭代操作的控制。
__iter__
方法应该返回一个迭代器对象。
-
__next__
方法:__next__
方法用于定义迭代操作的行为,它在每次迭代中返回下一个元素。__next__
方法通常包含一个迭代器内部的状态,以跟踪当前迭代的位置。- 当没有更多的元素可供迭代时,
__next__
方法应该引发StopIteration
异常,以指示迭代结束。 - 迭代器对象的
__next__
方法应该返回迭代中的下一个元素,或引发StopIteration
异常来终止迭代。
class Demo(object):
def __init__(self, data):
self.data = data
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.data):
result = self.data[self.index]
self.index += 1
return result
else:
raise StopIteration
d1 = Demo([1, 2, 3, 4, 5])
# 使用迭代器迭代访问元素
for item in d1:
print(item)
输出结果如下:
1
2
3
4
5
__call__
__call__
是Python中的一个特殊方法,它允许将对象像函数一样调用。在调用对象时,实际上是调用了 __call__
方法。__call__
方法可以接受任意数量的位置参数 args
和关键字参数 kwargs
。
class Demo(object):
def __call__(self, *args, **kwargs):
"""使对象可调用,就像函数一样。可通过 obj() 进行调用。"""
print("调用了__call__")
d1 = Demo()
d1()
# 等价于以下操作
Demo()()
输出结果如下:
调用了__call__
调用了__call_
__enter__、__exit__
__enter__
和 __exit__
是Python中用于上下文管理的两个特殊方法,通常与 with
语句结合使用。它们用于创建和管理上下文,以确保资源的正确分配和释放。
-
__enter__
方法:__enter__
方法用于进入上下文,它在with
语句块的开始处被调用。- 这个方法通常用于执行一些初始化或资源分配操作,并返回一个对象,它可以被
as
子句赋值给一个变量(如果在with
语句中使用了as
)。 - 任何返回的对象都可以在
with
语句块中使用,以便处理上下文中的一些操作。
-
__exit__
方法:__exit__
方法用于退出上下文,它在with
语句块的结束处被调用。- 这个方法通常用于执行一些清理或资源释放操作。它接受三个参数:
exc_type
、exc_value
和traceback
,用于处理异常。 - 如果
with
语句块正常执行完毕,__exit__
方法可以返回True
,以表示一切正常。如果有异常发生,它可以返回False
,以表示异常已被处理。
当使用 with
语句创建上下文时,__enter__
方法被调用,允许进行一些初始化操作。__exit__
方法在 with
语句块结束后被调用,允许进行一些清理操作。如果在 with
语句块中发生异常,__exit__
方法会处理它并返回 False
,表示异常未被处理。如果没有异常发生,__exit__
方法可以返回 True
,表示一切正常。这使得您可以确保资源的正确管理和异常处理。
class Demo(object):
def __enter__(self):
"""用于上下文管理器的进入方法。用于设置资源。"""
print("Entering the context")
return self # 返回一个对象,可以在with语句块中使用
def __exit__(self, exc_type, exc_value, traceback):
"""用于上下文管理器的退出方法。用于释放资源。"""
if exc_type is None:
print("Exiting the context (no exceptions)")
else:
print(f"Exiting the context with an exception: {exc_type}, {exc_value}")
return False # 返回False表示异常未被处理
# 使用with语句创建上下文,并在with块内执行操作
with Demo() as d1:
print("Inside the context")
# Uncomment the following line to test exception handling
# raise Exception("An error occurred")
# 当with块结束后,会调用__exit__方法
输出结果如下:
Entering the context
Inside the context
Exiting the context (no exceptions)
其他
class Demo(object):
def __eq__(self, other):
"""等于运算符 == 的定义。用于比较对象是否相等。"""
def __ne__(self, other):
"""不等于运算符 != 的定义。用于比较对象是否不相等。"""
def __lt__(self, other):
"""小于运算符 < 的定义。用于比较对象大小。"""
def __le__(self, other):
"""小于或等于运算符 <= 的定义。用于比较对象大小。"""
def __gt__(self, other):
"""大于运算符 > 的定义。用于比较对象大小。"""
def __ge__(self, other):
"""大于或等于运算符 >= 的定义。用于比较对象大小。"""
def __add__(self, other):
"""加法运算符 + 的定义。用于支持对象的加法操作。"""
def __sub__(self, other):
"""减法运算符 - 的定义。用于支持对象的减法操作。"""
def __mul__(self, other):
"""乘法运算符 * 的定义。用于支持对象的乘法操作。"""
def __truediv__(self, other):
"""真除法运算符 / 的定义。用于支持对象的真除法操作。"""
def __floordiv__(self, other):
"""地板除法运算符 // 的定义。用于支持对象的地板除法操作。"""
def __mod__(self, other):
"""取模运算符 % 的定义。用于支持对象的取模操作。"""
def __pow__(self, other):
"""幂运算符 ** 的定义。用于支持对象的幂操作。"""
def __contains__(self, item):
"""用于 in 运算符的定义。用于检查对象是否包含某个元素。"""
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?