python基础第二十四节
魔法方法: Python中的魔法方法是一类特殊的方法, 它们以双下划线 __ 开头和结尾, 用于实现类的特殊行为.这些魔法方法在Python中具有特殊的含义, 可以让你自定义类的行为, 使其更符合你的需求, 它们一般是自动调用, 也可以通过内置函数来显式调用.
24.1 __new__和__del__
__new__ 是 Python 中的一个特殊魔法方法, 用于创建对象实例.它在对象实例被创建之前被调用, 通常用于控制对象的创建过程和自定义对象的创建方式.与之相对的是 __init__ 方法, 它在对象实例创建后进行初始化操作.
__new__的注意点:
- 返回实例对象:
__new__方法必须返回一个类的实例对象.通常情况下, 它会调用父类的__new__方法来创建实例, 并返回实例对象. - 第一个参数是类:
__new__方法的第一个参数是类本身, 通常命名为cls.在调用时, Python 会自动传递类作为第一个参数. - 控制实例创建过程:
__new__方法允许你控制实例的创建过程.你可以在这个方法中实现自定义的逻辑.
__del__当对象被释放的时候, 会执行. 它通常用于执行一些资源释放或清理操作, 如关闭文件、释放网络连接等. 但是, 但并不保证一定会调用, 因为垃圾回收可能由不同的策略来管理. python中对象的释放是一个比较复杂的过程. 一个对象有可能在引用到0的时候被释放, 且这个释放是可能在任意一个地方发生.
注意:
__del__跟python中的关键字del是没有关系的.del并不一定会触发__del__
24.2 __repr__和__len__
__repr__ 用于定义对象的字符串表示形式.
__str__和__repr__都返回一个对象的字符串描述, 不过两者的用途不同, str可以理解是给人阅读的, 而repr是给程序使用的.
print(obj)、str(obj)方法调用对象的str方法;交互式CLI、repr(obj)、gdb调试时查看对象值返回的是repr, 不过和多情况下程序员把str和repr设置为一样__str__ == __repr__.
如果没有定义 __str__ 方法, 调用 print() 时会默认使用 __repr__ 方法.
__len__: 用于定义对象的长度(大小).当你在一个对象上调用内置的 len() 函数时, Python 会查找该对象是否定义了 __len__ 方法, 如果有则调用该方法并返回长度值.
24.3 __enter__和__exit__
上下文协议是一组特殊方法, 允许你创建可用于 with 语句的上下文管理器.使用上下文管理器可以在进入和退出代码块时执行特定操作, 如资源的分配和释放.Python 的上下文协议涉及两个主要的特殊方法:__enter__ 和 __exit__.
-
方法:__enter__(self)- 在进入代码块前被调用, 用于执行一些准备操作.
- 可以返回一个值, 该值将被赋给
as关键字之后的变量.
-
方法:__exit__(self, exc_type, exc_value, exc_traceback)- 在退出代码块时调用, 无论代码块是否发生异常.
- 可以用于执行一些清理操作, 如资源的释放.
- 如果代码块内没有异常发生, 参数为
None, None, None.如果有异常, 参数包含异常类型、异常实例和跟踪信息. - 如果
__exit__方法返回True, 异常不会向上继续传播.返回False则异常会继续向上抛.
上下文协议的使用案例:可以使用with语句来管理文件的打开和关闭, 确保文件资源在退出代码块时被正确释放.
24.4 可迭代对象和迭代器
可迭代对象和迭代器是 Python 中用于遍历数据集合的概念.它们在很多情况下都用于实现数据的迭代操作, 如循环.
可迭代对象(Iterable)
可迭代对象是一种数据类型, 可以通过迭代获取其中的元素.在 Python 中, 任何实现了 __iter__() 方法的对象都被视为可迭代对象.常见的可迭代对象包括列表、元组、字典、集合、字符串等.
可迭代对象的特点:
- 可以使用
for循环遍历元素. - 可以通过
iter()函数将其转换为迭代器.
迭代器Iterator
迭代器是一个实现了__iter__()和__next__()方法的对象.__iter__()方法返回迭代器对象自身, 而__next__()方法返回迭代器的下一个元素, 如果没有元素了, 抛出StopIteration异常.
迭代器的特点: - 可以使用
for循环遍历元素, 也可以使用next()函数逐个获取元素. - 只能遍历一次, 遍历完成后就不能再次使用.
总结:
- 可迭代对象是具有迭代性质的对象, 而迭代器是一个实现了迭代协议的对象.
- 可迭代对象可以通过
iter()函数转换为迭代器. - 迭代器是一种一次性的数据获取方式, 每次调用
next()都会获取下一个元素.
24.5 中括号[]数据操作
__getitem__、__setitem__ 和 __delitem__ 用于自定义对象的索引访问和操作.它们在创建自定义的容器类时非常有用, 允许你实现类似字典或列表的行为.
__getitem__(self, key):
这个方法定义了使用索引访问对象时的行为.当你像obj[key]这样使用索引操作时, Python 会调用对象的__getitem__方法, 并将索引key作为参数传递给这个方法.你可以在这个方法中实现对应的行为, 比如从内部数据结构中获取相应的值.__setitem__(self, key, value):
这个方法定义了使用索引赋值操作时的行为.当你像obj[key] = value这样进行索引赋值操作时, Python 会调用对象的__setitem__方法, 并将索引key和值value作为参数传递给这个方法.你可以在这个方法中实现对应的赋值行为.__delitem__(self, key):
这个方法定义了使用del obj[key]进行索引删除操作时的行为.当你使用del删除索引时, Python 会调用对象的__delitem__方法, 并将索引key作为参数传递给这个方法.你可以在这个方法中实现删除操作的逻辑.
这些方法的使用可以使你的自定义类更具像内置容器类型(如字典和列表)的行为, 从而实现更灵活和符合预期的数据操作.
25.6 __getattr__、__setattr__ 和 __delattr__
__getattr__、__setattr__ 和 __delattr__ 是 Python 中的魔法方法, 用于自定义对象的属性访问和操作.它们允许你控制属性的获取、设置和删除行为, 从而实现自定义的属性操作逻辑.
__getattr__(self, name):
当你访问一个不存在的属性时, Python 会调用对象的__getattr__方法, 并将属性名name作为参数传递给这个方法.你可以在这个方法中实现对应的行为, 比如返回一个默认值或者抛出异常.__setattr__(self, name, value):
当你设置属性的值时, Python 会调用对象的__setattr__方法, 并将属性名name和值value作为参数传递给这个方法.你可以在这个方法中实现对应的赋值行为, 比如进行值的验证或修改.__delattr__(self, name):
当你删除属性时, Python 会调用对象的__delattr__方法, 并将属性名name作为参数传递给这个方法.你可以在这个方法中实现删除属性的逻辑.
这些方法的使用可以使你的自定义类的属性操作更具控制性和灵活性.
24.7 可调用的
不仅 Python 函数是真正的可调用的, 任何 Python 对象都可以表现得像函数.为此, 只需实现魔法方法 __call__.
__call__ 是 Python 中的一个特殊魔法方法, 用于使对象可以像函数一样被调用.当一个对象被调用时, Python 会检查对象是否定义了 __call__ 方法, 如果定义了, 就会调用该方法, 从而实现对象的可调用行为.
这使得你可以将一个类的实例像函数一样使用, 提供更多的灵活性和自定义操作.
24.8 运算符
运算符魔法方法是用于实现对象之间的比较和关系运算的.它们允许你定义自定义的比较操作, 使你的对象可以像内置类型一样进行大小比较、相等性检查等操作.
下面是一些常用的运算符类型的魔法方法及其解释:
__lt__(self, other): 小于运算符<的魔法方法.定义对象小于另一个对象时的行为.__le__(self, other): 小于等于运算符<=的魔法方法.定义对象小于等于另一个对象时的行为.__eq__(self, other): 等于运算符 "==" 的魔法方法.定义对象相等时的行为.__ne__(self, other): 不等于运算符!=的魔法方法.定义对象不等于另一个对象时的行为.__gt__(self, other): 大于运算符>的魔法方法.定义对象大于另一个对象时的行为.__ge__(self, other): 大于等于运算符>=的魔法方法.定义对象大于等于另一个对象时的行为.