当前位置:   article > 正文

Python魔法之旅-魔法方法(11)

Python魔法之旅-魔法方法(11)

目录

一、概述

1、定义

2、作用

二、应用场景

1、构造和析构

2、操作符重载

3、字符串和表示

4、容器管理

5、可调用对象

6、上下文管理

7、属性访问和描述符

8、迭代器和生成器

9、数值类型

10、复制和序列化

11、自定义元类行为

12、自定义类行为

13、类型检查和转换

14、自定义异常

三、学习方法

1、理解基础

2、查阅文档

3、编写示例

4、实践应用

5、阅读他人代码

6、参加社区讨论

7、持续学习

8、练习与总结

9、注意兼容性

10、避免过度使用

四、魔法方法

35、__instancecheck__方法

35-1、语法

35-2、参数

35-3、功能

35-4、返回值

35-5、说明

35-6、用法

36、__int__方法

36-1、语法

36-2、参数

36-3、功能

36-4、返回值

36-5、说明

36-6、用法

37、__invert__方法

37-1、语法

37-2、参数

37-3、功能

37-4、返回值

37-5、说明

37-6、用法

五、推荐阅读

1、Python筑基之旅

2、Python函数之旅

3、Python算法之旅

4、博客个人主页

一、概述

1、定义

        魔法方法(Magic Methods/Special Methods,也称特殊方法或双下划线方法)是Python中一类具有特殊命名规则的方法,它们的名称通常以双下划线(`__`)开头和结尾

        魔法方法用于在特定情况下自动被Python解释器调用,而不需要显式地调用它们,它们提供了一种机制,让你可以定义自定义类时具有与内置类型相似的行为。

2、作用

        魔法方法允许开发者重载Python中的一些内置操作或函数的行为,从而为自定义的类添加特殊的功能

二、应用场景

1、构造和析构

1-1、__init__(self, [args...]):在创建对象时初始化属性。
1-2、__new__(cls, [args...]):在创建对象时控制实例的创建过程(通常与元类一起使用)。
1-3、__del__(self):在对象被销毁前执行清理操作,如关闭文件或释放资源。

2、操作符重载

2-1、__add__(self, other)、__sub__(self, other)、__mul__(self, other)等:自定义对象之间的算术运算。
2-2、__eq__(self, other)、__ne__(self, other)、__lt__(self, other)等:定义对象之间的比较操作。

3、字符串和表示

3-1、__str__(self):定义对象的字符串表示,常用于print()函数。
3-2、__repr__(self):定义对象的官方字符串表示,用于repr()函数和交互式解释器。

4、容器管理

4-1、__getitem__(self, key)、__setitem__(self, key, value)、__delitem__(self, key):用于实现类似列表或字典的索引访问、设置和删除操作。
4-2、__len__(self):返回对象的长度或元素个数。

5、可调用对象

5-1、__call__(self, [args...]):允许对象像函数一样被调用。

6、上下文管理

6-1、__enter__(self)、__exit__(self, exc_type, exc_val, exc_tb):用于实现上下文管理器,如with语句中的对象。

7、属性访问和描述符

7-1、__getattr__, __setattr__, __delattr__:这些方法允许对象在访问或修改不存在的属性时执行自定义操作。
7-2、描述符(Descriptors)是实现了__get__, __set__, 和__delete__方法的对象,它们可以控制对另一个对象属性的访问。

8、迭代器和生成器

8-1、__iter__和__next__:这些方法允许对象支持迭代操作,如使用for循环遍历对象。
8-2、__aiter__, __anext__:这些是异步迭代器的魔法方法,用于支持异步迭代。

9、数值类型

9-1、__int__(self)、__float__(self)、__complex__(self):定义对象到数值类型的转换。
9-2、__index__(self):定义对象用于切片时的整数转换。

10、复制和序列化

10-1、__copy__和__deepcopy__:允许对象支持浅复制和深复制操作。
10-2、__getstate__和__setstate__:用于自定义对象的序列化和反序列化过程。

11、自定义元类行为

11-1、__metaclass__(Python 2)或元类本身(Python 3):允许自定义类的创建过程,如动态创建类、修改类的定义等。

12、自定义类行为

12-1、__init__和__new__:用于初始化对象或控制对象的创建过程。
12-2、__init_subclass__:在子类被创建时调用,允许在子类中执行一些额外的操作。

13、类型检查和转换

13-1、__instancecheck__和__subclasscheck__:用于自定义isinstance()和issubclass()函数的行为。

14、自定义异常

14-1、你可以通过继承内置的Exception类来创建自定义的异常类,并定义其特定的行为。

三、学习方法

        要学好Python的魔法方法,你可以遵循以下方法及步骤:

1、理解基础

        首先确保你对Python的基本语法、数据类型、类和对象等概念有深入的理解,这些是理解魔法方法的基础。

2、查阅文档

        仔细阅读Python官方文档中关于魔法方法的部分,文档会详细解释每个魔法方法的作用、参数和返回值。你可以通过访问Python的官方网站或使用help()函数在Python解释器中查看文档。

3、编写示例

        为每个魔法方法编写简单的示例代码,以便更好地理解其用法和效果,通过实际编写和运行代码,你可以更直观地感受到魔法方法如何改变对象的行为。

4、实践应用

        在实际项目中尝试使用魔法方法。如,你可以创建一个自定义的集合类,使用__getitem__、__setitem__和__delitem__方法来实现索引操作。只有通过实践应用,你才能更深入地理解魔法方法的用途和重要性。

5、阅读他人代码

        阅读开源项目或他人编写的代码,特别是那些使用了魔法方法的代码,这可以帮助你学习如何在实际项目中使用魔法方法。通过分析他人代码中的魔法方法使用方式,你可以学习到一些新的技巧和最佳实践。

6、参加社区讨论

        参与Python社区的讨论,与其他开发者交流关于魔法方法的使用经验和技巧,在社区中提问或回答关于魔法方法的问题,这可以帮助你更深入地理解魔法方法并发现新的应用场景。

7、持续学习

        Python语言和其生态系统不断发展,新的魔法方法和功能可能会不断被引入,保持对Python社区的关注,及时学习新的魔法方法和最佳实践。

8、练习与总结

        多做练习,通过编写各种使用魔法方法的代码来巩固你的理解,定期总结你学到的知识和经验,形成自己的知识体系。

9、注意兼容性

        在使用魔法方法时,要注意不同Python版本之间的兼容性差异,确保你的代码在不同版本的Python中都能正常工作。

10、避免过度使用

        虽然魔法方法非常强大,但过度使用可能会导致代码难以理解和维护,在编写代码时,要权衡使用魔法方法的利弊,避免滥用。

        总之,学好Python的魔法方法需要不断地学习、实践和总结,只有通过不断地练习和积累经验,你才能更好地掌握这些强大的工具,并在实际项目中灵活运用它们。

四、魔法方法

35、__instancecheck__方法

35-1、语法
  1. __instancecheck__(self, instance, /)
  2. Check if an object is an instance
35-2、参数

35-2-1、self(必须)一个对实例对象本身的引用,在类的所有方法中都会自动传递。

35-2-2、 instance(必须)表示你正在检查其类型或类的对象。

35-2-3、/(可选)这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。

35-3、功能

        确定一个给定的instance是否被认为是某个类(或其元类)的一个实例。

35-4、返回值

        返回一个布尔值。如果instance被认为是class_or_type的一个实例,返回True;反之,则返回False。

35-5、说明

        当你想要自定义类型检查的逻辑时,你可以在你的元类中重写这个方法。

35-6、用法
  1. # 035、__instancecheck__方法:
  2. # 1、检查是否为正整数
  3. from abc import ABCMeta
  4. class PositiveIntChecker(type):
  5. def __instancecheck__(self, instance):
  6. return isinstance(instance, int) and instance > 0
  7. class PositiveInt(metaclass=PositiveIntChecker):
  8. __class__ = PositiveIntChecker('PositiveInt', (object,), {})
  9. if __name__ == '__main__':
  10. print(isinstance(10, PositiveInt)) # 输出:True
  11. print(isinstance(-1, PositiveInt)) # 输出:False
  12. # 2、检查是否为偶数
  13. from abc import ABCMeta
  14. class EvenChecker(type(type), metaclass=ABCMeta):
  15. def __instancecheck__(self, instance):
  16. return isinstance(instance, int) and instance % 2 == 0
  17. class Even(metaclass=EvenChecker):
  18. __class__ = EvenChecker('Even', (object,), {})
  19. if __name__ == '__main__':
  20. print(isinstance(2, Even)) # 输出:True
  21. print(isinstance(3, Even)) # 输出:False
  22. # 3、检查字典的键是否都是字符串
  23. from abc import ABCMeta
  24. class DictKeysAreStrChecker(ABCMeta):
  25. def __instancecheck__(self, instance):
  26. return isinstance(instance, dict) and all(isinstance(k, str) for k in instance.keys())
  27. # 使用元类来创建一个类型提示,而不是一个真正的类
  28. DictWithStrKeys = DictKeysAreStrChecker('DictWithStrKeys', (object,), {})
  29. # 注意:这里的 DictWithStrKeys 不是一个类,而是一个元类的实例(类型)
  30. # 我们可以使用它作为一个类型提示,但不能用它实例化对象
  31. if __name__ == '__main__':
  32. print(isinstance({'a': 1, 'b': 2}, DictWithStrKeys)) # 输出:True
  33. print(isinstance({'a': 1, 2: 'b'}, DictWithStrKeys)) # 输出:False
  34. # 4、检查对象是否为可迭代对象
  35. from abc import ABCMeta
  36. class IterableChecker(type(type), metaclass=ABCMeta):
  37. def __instancecheck__(self, instance):
  38. return hasattr(instance, '__iter__')
  39. class IsIterable(metaclass=IterableChecker):
  40. __class__ = IterableChecker('IsIterable', (object,), {})
  41. if __name__ == '__main__':
  42. print(isinstance([1, 2, 3], IsIterable)) # 输出:True
  43. print(isinstance(5, IsIterable)) # 输出:False

36、__int__方法

36-1、语法
  1. __int__(self, /)
  2. int(self)
36-2、参数

36-2-1、self(必须)一个对实例对象本身的引用,在类的所有方法中都会自动传递。

36-2-2、/(可选)这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。

36-3、功能

        用于定义一个对象到整数类型的转换。

36-4、返回值

        返回一个整数,即对象转换后的结果。

36-5、说明

        如果对象不能被转换为一个整数,或者转换过程中发生了错误,那么 __int__ 方法应该引发一个异常(通常是TypeError或ValueError)。

36-6、用法
  1. # 036、__int__方法:
  2. # 1、基本整数转换
  3. class IntegerWrapper:
  4. def __init__(self, value):
  5. self.value = int(value)
  6. def __int__(self):
  7. return self.value
  8. if __name__ == '__main__':
  9. w = IntegerWrapper(123)
  10. print(int(w)) # 输出: 123
  11. # 2、从浮点数转换
  12. class FloatToInt:
  13. def __init__(self, value):
  14. self.value = float(value)
  15. def __int__(self):
  16. return int(self.value)
  17. if __name__ == '__main__':
  18. f = FloatToInt(123.45)
  19. print(int(f)) # 输出: 123
  20. # 3、从字符串转换
  21. class StringToInt:
  22. def __init__(self, value):
  23. self.value = value
  24. def __int__(self):
  25. return int(self.value)
  26. if __name__ == '__main__':
  27. s = StringToInt("123")
  28. print(int(s)) # 输出: 123
  29. # 4、四舍五入转换
  30. class RoundedInt:
  31. def __init__(self, value):
  32. self.value = float(value)
  33. def __int__(self):
  34. return round(self.value)
  35. if __name__ == '__main__':
  36. r = RoundedInt(123.456)
  37. print(int(r)) # 输出: 123
  38. # 5、截断小数部分
  39. class TruncateDecimal:
  40. def __init__(self, value):
  41. self.value = float(value)
  42. def __int__(self):
  43. return int(self.value // 1)
  44. if __name__ == '__main__':
  45. t = TruncateDecimal(123.999)
  46. print(int(t)) # 输出: 123
  47. # 6、取绝对值后转换
  48. class AbsoluteInt:
  49. def __init__(self, value):
  50. self.value = int(value)
  51. def __int__(self):
  52. return abs(self.value)
  53. if __name__ == '__main__':
  54. a = AbsoluteInt(-123)
  55. print(int(a)) # 输出: 123
  56. # 7、自定义数字转换
  57. class CustomNumber:
  58. def __init__(self, value):
  59. self.value = value
  60. def __int__(self):
  61. return self.value * 2 # 示例:将值乘以 2
  62. if __name__ == '__main__':
  63. c = CustomNumber(5)
  64. print(int(c)) # 输出: 10
  65. # 8、从分数转换
  66. from fractions import Fraction
  67. class FractionToInt:
  68. def __init__(self, numerator, denominator):
  69. self.fraction = Fraction(numerator, denominator)
  70. def __int__(self):
  71. return int(self.fraction)
  72. if __name__ == '__main__':
  73. fr = FractionToInt(3, 2)
  74. print(int(fr)) # 输出: 1(因为 3/2 向下取整为 1)
  75. # 9、从日期获取年份
  76. from datetime import date
  77. class YearFromInt:
  78. def __init__(self, year):
  79. self.date = date(year, 1, 1)
  80. def __int__(self):
  81. return self.date.year
  82. if __name__ == '__main__':
  83. y = YearFromInt(2024)
  84. print(int(y)) # 输出: 2024
  85. # 10、从复数取实部并转换为整数
  86. class ComplexToInt:
  87. def __init__(self, complex_num):
  88. self.complex_num = complex(complex_num)
  89. def __int__(self):
  90. return int(self.complex_num.real)
  91. if __name__ == '__main__':
  92. c = ComplexToInt(3 + 4j)
  93. print(int(c)) # 输出: 3
  94. # 11、从罗马数字转换
  95. class RomanToInt:
  96. def __init__(self, roman_num):
  97. self.roman_num = roman_num
  98. def __int__(self):
  99. # 这是一个简化的罗马数字到整数的转换,仅支持几种基本的罗马数字表示
  100. roman_values = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000}
  101. total = 0
  102. prev_value = 0
  103. for char in reversed(self.roman_num):
  104. value = roman_values[char]
  105. if value < prev_value:
  106. total -= value
  107. else:
  108. total += value
  109. prev_value = value
  110. return total
  111. if __name__ == '__main__':
  112. r = RomanToInt("III")
  113. print(int(r)) # 输出: 3
  114. # 12、从时间戳获取秒数
  115. import time
  116. class TimestampWrapper:
  117. def __init__(self, timestamp):
  118. self.timestamp = timestamp
  119. def __int__(self):
  120. # 因为Unix时间戳本身就是整数,所以这里我们直接返回它
  121. return int(self.timestamp)
  122. def __str__(self):
  123. # 提供一个字符串表示,方便查看时间戳对应的本地时间
  124. return time.ctime(self.timestamp)
  125. if __name__ == '__main__':
  126. # 创建一个TimestampWrapper对象,假设时间戳为当前时间的时间戳
  127. now = int(time.time())
  128. tw = TimestampWrapper(now)
  129. # 使用__int__方法将对象转换为整数(即时间戳)
  130. timestamp_int = int(tw)
  131. print(f"Timestamp as integer: {timestamp_int}")
  132. # 使用__str__方法将对象转换为字符串(即本地时间)
  133. local_time = str(tw)
  134. print(f"Local time: {local_time}")

37、__invert__方法

37-1、语法
  1. __invert__(self, /)
  2. ~self
37-2、参数

37-2-1、self(必须)一个对实例对象本身的引用,在类的所有方法中都会自动传递。

37-2-2、/(可选)这是从Python 3.8开始引入的参数注解语法,它表示这个方法不接受任何位置参数(positional-only parameters)之后的关键字参数(keyword arguments)。

37-3、功能

        用于定义对象的按位取反(bitwise inversion)操作。

37-4、返回值

        返回一个对象,该对象表示了原对象的按位取反结果。

37-5、说明

        如果无法执行按位取反操作,或者操作过程中发生了错误,那么 __invert__ 方法应该引发一个异常(通常是TypeError或ValueError)。

37-6、用法
  1. # 37、__invert__方法:
  2. # 1、基本按位取反(整数)
  3. class BitwiseInvertibleInt:
  4. def __init__(self, value):
  5. self.value = value
  6. def __invert__(self):
  7. return ~self.value
  8. if __name__ == '__main__':
  9. i = BitwiseInvertibleInt(5) # 5 in binary is 0101
  10. print(~i) # Outputs: -6 (because ~0101 is 1010 which is -6 in two's complement)
  11. # 2、自定义布尔取反
  12. class InvertibleBool:
  13. def __init__(self, value):
  14. self.value = bool(value)
  15. def __invert__(self):
  16. return not self.value
  17. if __name__ == '__main__':
  18. b = InvertibleBool(True)
  19. print(~b) # 输出: False
  20. # 3、列表索引取反(模拟)
  21. class InvertibleIndex:
  22. def __init__(self, index, max_index):
  23. self.index = index
  24. self.max_index = max_index
  25. def __invert__(self):
  26. return self.max_index - self.index - 1
  27. if __name__ == '__main__':
  28. idx = InvertibleIndex(2, 4) # Invert index 2 in a list of length 5 (indices 0-4)
  29. print(~idx) # Outputs: 1 (because 4 - 2 - 1 = 1, which is the "inverted" index)
  30. # 4、字符串位置取反(模拟)
  31. class InvertibleStringPosition:
  32. def __init__(self, position, string):
  33. self.position = position
  34. self.string = string
  35. def __invert__(self):
  36. return len(self.string) - self.position - 1
  37. if __name__ == '__main__':
  38. s = InvertibleStringPosition(2, "hello")
  39. print(~s)
  40. # 5、颜色通道取反(RGB)
  41. class InvertibleColor:
  42. def __init__(self, r, g, b):
  43. self.r = r
  44. self.g = g
  45. self.b = b
  46. def __invert__(self):
  47. return type(self)(255 - self.r, 255 - self.g, 255 - self.b)
  48. if __name__ == '__main__':
  49. c = InvertibleColor(100, 50, 200)
  50. print(~c)
  51. # 6、权限取反(模拟)
  52. class Permission:
  53. READ = 1
  54. WRITE = 2
  55. EXECUTE = 4
  56. def __init__(self, permissions):
  57. self.permissions = permissions
  58. def __invert__(self):
  59. return type(self)(~(self.permissions))
  60. if __name__ == '__main__':
  61. p = Permission(Permission.READ | Permission.WRITE) # 1 | 2 = 3
  62. print(~p)
  63. # 7、矩阵转置(模拟)
  64. class Matrix:
  65. # 简化示例,仅表示二维列表
  66. def __init__(self, data):
  67. self.data = data
  68. def __invert__(self):
  69. # 注意:这不是真正的矩阵转置,只是模拟
  70. return type(self)([list(row) for row in zip(*self.data[::-1])])
  71. if __name__ == '__main__':
  72. m = Matrix([[1, 2], [3, 4]])
  73. print(~m)
  74. # 8、自定义集合的取反(模拟)
  75. class InvertibleSet:
  76. def __init__(self, universe, elements):
  77. self.universe = set(universe)
  78. self.elements = set(elements)
  79. def __invert__(self):
  80. return self.universe - self.elements
  81. if __name__ == '__main__':
  82. s = InvertibleSet({1, 2, 3, 4, 5}, {2, 4})
  83. print(~s) # 输出: {1, 3, 5}
  84. # 9、自定义状态机的状态取反
  85. class StateMachine:
  86. def __init__(self, state):
  87. self.state = bool(state)
  88. def __invert__(self):
  89. return type(self)(not self.state)
  90. if __name__ == '__main__':
  91. sm = StateMachine(True)
  92. print(~sm.state) # 输出:-2
  93. # 10、颜色通道的模拟取反(HSV)
  94. class HSVColor:
  95. def __init__(self, h, s, v):
  96. self.h = h % 360 # 确保色调在 0-359 之间
  97. self.s = s
  98. self.v = v
  99. def __invert__(self):
  100. # 简单地取反色调(可能不是真正的颜色取反)
  101. return type(self)((360 - self.h) % 360, self.s, self.v)
  102. if __name__ == '__main__':
  103. c = HSVColor(120, 0.5, 1.0) # 绿色
  104. print(~c) # 输出: HSVColor(h=240, s=0.5, v=1.0) # 可能是某种紫色或洋红色
  105. # 11、模拟权限的“非”操作
  106. class Permissions:
  107. READ = 1
  108. WRITE = 2
  109. EXECUTE = 4
  110. def __init__(self, perms):
  111. self.perms = perms
  112. def __invert__(self):
  113. return type(self)(0) # 表示没有任何权限
  114. def __str__(self):
  115. perms_str = ""
  116. if self.perms & Permissions.READ:
  117. perms_str += "READ "
  118. if self.perms & Permissions.WRITE:
  119. perms_str += "WRITE "
  120. if self.perms & Permissions.EXECUTE:
  121. perms_str += "EXECUTE"
  122. return perms_str.strip()
  123. if __name__ == '__main__':
  124. p = Permissions(Permissions.READ | Permissions.WRITE)
  125. print(p) # 输出: READ WRITE
  126. print(~p) # 输出: (表示没有任何权限)

五、推荐阅读

1、Python筑基之旅

2、Python函数之旅

3、Python算法之旅

4、博客个人主页

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号