首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

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

  • 25-03-03 05:09
  • 3511
  • 8742
blog.csdn.net

目录

一、概述

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、避免过度使用

四、魔法方法

71、__str__方法

71-1、语法

71-2、参数

71-3、功能

71-4、返回值

71-5、说明

71-6、用法

72、__sub__方法:

72-1、语法

72-2、参数

72-3、功能

72-4、返回值

72-5、说明

72-6、用法

73、__subclasscheck__方法:

73-1、语法

73-2、参数

73-3、功能

73-4、返回值

73-5、说明

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

四、魔法方法

71、__str__方法

71-1、语法
  1. __str__(self, /)
  2. Return str(self)
71-2、参数

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

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

71-3、功能

        用于定义当对象被转换为字符串时应该返回什么样的值。

71-4、返回值

       返回一个字符串,其代表了对象的“官方”字符串表示。

71-5、说明

        无

71-6、用法
  1. # 071、__str__方法:
  2. # 1、基本字符串表示
  3. class Person:
  4. def __init__(self, name, age):
  5. self.name = name
  6. self.age = age
  7. def __str__(self):
  8. return f"Person(name={self.name}, age={self.age})"
  9. if __name__ == '__main__':
  10. p = Person('Myelsa', 18)
  11. print(p) # 输出:Person(name=Myelsa, age=18)
  12. # 2、格式化输出
  13. class Circle:
  14. def __init__(self, radius):
  15. self.radius = radius
  16. def __str__(self):
  17. return f"Circle with radius {self.radius} has area {self.area()}"
  18. def area(self):
  19. import math
  20. return math.pi * (self.radius ** 2)
  21. if __name__ == '__main__':
  22. c = Circle(5)
  23. print(c) # 输出:Circle with radius 5 has area 78.53981633974483
  24. # 3、列表元素的字符串表示
  25. class Item:
  26. def __init__(self, id, name):
  27. self.id = id
  28. self.name = name
  29. def __str__(self):
  30. return f"Item {self.id}: {self.name}"
  31. if __name__ == '__main__':
  32. items = [Item(1, "Apple"), Item(2, "Banana")]
  33. print(items)
  34. # 4、字典值的字符串表示
  35. class User:
  36. def __init__(self, username, email):
  37. self.username = username
  38. self.email = email
  39. def __str__(self):
  40. return f"User({self.username}, {self.email})"
  41. if __name__ == '__main__':
  42. users = {"admin": User("admin", "[email protected]")}
  43. print(users)
  44. # 5、日期和时间
  45. from datetime import datetime
  46. class Event:
  47. def __init__(self, name, time):
  48. self.name = name
  49. self.time = time
  50. def __str__(self):
  51. return f"{self.name} happens at {self.time.strftime('%Y-%m-%d %H:%M:%S')}"
  52. if __name__ == '__main__':
  53. event = Event("Meeting", datetime.now())
  54. print(event) # 输出:类似于Meeting happens at 2024-06-08 09:41:58
  55. # 6、文件路径
  56. import os
  57. class FilePath:
  58. def __init__(self, path):
  59. self.path = path
  60. def __str__(self):
  61. return self.path.replace(os.sep, '/') # 标准化路径分隔符
  62. if __name__ == '__main__':
  63. path = FilePath("/test.txt")
  64. print(path)
  65. # 7、分数
  66. from fractions import Fraction
  67. class Score:
  68. def __init__(self, numerator, denominator):
  69. self.fraction = Fraction(numerator, denominator)
  70. def __str__(self):
  71. return str(self.fraction)
  72. if __name__ == '__main__':
  73. score = Score(2, 3)
  74. print(score)
  75. # 8、复数
  76. class ComplexNumber:
  77. def __init__(self, real, imag):
  78. self.real = real
  79. self.imag = imag
  80. def __str__(self):
  81. return f"{self.real} + {self.imag}j"
  82. if __name__ == '__main__':
  83. c = ComplexNumber(3, 4)
  84. print(c)
  85. # 9、自定义列表
  86. class MyList:
  87. def __init__(self, *args):
  88. self.items = list(args)
  89. def __str__(self):
  90. return "[" + ", ".join(map(str, self.items)) + "]"
  91. if __name__ == '__main__':
  92. lst = MyList(3, 5, 6, 8, 10, 11, 24)
  93. print(lst) # 输出:[3, 5, 6, 8, 10, 11, 24]
  94. # 10、二维坐标点
  95. class Point2D:
  96. def __init__(self, x, y):
  97. self.x = x
  98. self.y = y
  99. def __str__(self):
  100. return f"({self.x}, {self.y})"
  101. if __name__ == '__main__':
  102. p = Point2D(1, 2)
  103. print(p) # 输出:(1, 2)
  104. # 11、矩形类
  105. class Rectangle:
  106. def __init__(self, width, height):
  107. self.width = width
  108. self.height = height
  109. def __str__(self):
  110. return f"Rectangle({self.width} wide x {self.height} tall)"
  111. if __name__ == '__main__':
  112. rect = Rectangle(10, 24)
  113. print(rect) # 输出:Rectangle(10 wide x 24 tall)
  114. # 12、学生信息
  115. class Student:
  116. def __init__(self, id, name, grade):
  117. self.id = id
  118. self.name = name
  119. self.grade = grade
  120. def __str__(self):
  121. return f"Student {self.id}: {self.name} - Grade {self.grade}"
  122. if __name__ == '__main__':
  123. student = Student(123, "John Doe", "A")
  124. print(student) # 输出:Student 123: John Doe - Grade A
  125. # 13、图书信息
  126. class Book:
  127. def __init__(self, title, author, isbn):
  128. self.title = title
  129. self.author = author
  130. self.isbn = isbn
  131. def __str__(self):
  132. return f"{self.title} by {self.author} (ISBN: {self.isbn})"
  133. if __name__ == '__main__':
  134. book = Book("The Great Gatsby", "F. Scott Fitzgerald", "1234567890")
  135. print(book) # 输出:The Great Gatsby by F. Scott Fitzgerald (ISBN: 1234567890)
  136. # 14、电子邮件消息
  137. class EmailMessage:
  138. def __init__(self, sender, recipients, subject, body):
  139. self.sender = sender
  140. self.recipients = recipients
  141. self.subject = subject
  142. self.body = body
  143. def __str__(self):
  144. return f"From: {self.sender}\nTo: {', '.join(self.recipients)}\nSubject: {self.subject}\n\n{self.body}"
  145. if __name__ == '__main__':
  146. email = EmailMessage("[email protected]", ["[email protected]"], "Hello", "How are you?")
  147. print(email)
  148. # From: [email protected]
  149. # To: [email protected]
  150. # Subject: Hello
  151. #
  152. # How are you?
  153. # 15、订单详情
  154. class Order:
  155. def __init__(self, order_id, products, total_price):
  156. self.order_id = order_id
  157. self.products = products
  158. self.total_price = total_price
  159. def __str__(self):
  160. return f"Order {self.order_id}: {', '.join(self.products)} - Total: ${self.total_price}"
  161. if __name__ == '__main__':
  162. order = Order(1001, ["Product A", "Product B"], 100.0)
  163. print(order) # 输出:Order 1001: Product A, Product B - Total: $100.0
  164. # 16、车辆信息
  165. class Car:
  166. def __init__(self, make, model, year):
  167. self.make = make
  168. self.model = model
  169. self.year = year
  170. def __str__(self):
  171. return f"{self.year} {self.make} {self.model}"
  172. if __name__ == '__main__':
  173. car = Car("Toyota", "Corolla", 2023)
  174. print(car) # 输出:2023 Toyota Corolla
  175. # 17、动物信息
  176. class Animal:
  177. def __init__(self, name, species, age):
  178. self.name = name
  179. self.species = species
  180. self.age = age
  181. def __str__(self):
  182. return f"{self.name} is a {self.species} and is {self.age} years old."
  183. if __name__ == '__main__':
  184. animal = Animal("Buddy", "Dog", 5)
  185. print(animal) # 输出:Buddy is a Dog and is 5 years old.
  186. # 18、综合案例
  187. class Employee:
  188. def __init__(self, name, position, salary):
  189. self.name = name
  190. self.position = position
  191. self.salary = salary
  192. self.bonus = 0 # 初始时没有年终奖
  193. def adjust_salary(self, percentage):
  194. """调整薪资,增加或减少指定百分比"""
  195. self.salary *= (1 + percentage / 100)
  196. def calculate_bonus(self, percentage):
  197. """计算年终奖"""
  198. self.bonus = self.salary * (percentage / 100)
  199. def __str__(self):
  200. """返回员工的字符串表示"""
  201. return f"Employee: {self.name}\n" \
  202. f"Position: {self.position}\n" \
  203. f"Salary: ${self.salary:.2f}\n" \
  204. f"Bonus: ${self.bonus:.2f}"
  205. if __name__ == '__main__':
  206. employee = Employee("Myelsa", "Software Engineer", 50000)
  207. employee.calculate_bonus(10) # 假设年终奖是薪资的10%
  208. print(employee)
  209. # Employee: Myelsa
  210. # Position: Software Engineer
  211. # Salary: $50000.00
  212. # Bonus: $5000.00

72、__sub__方法:

72-1、语法
  1. __sub__(self, other, /)
  2. Return self - other
72-2、参数

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

72-2-2、other(必须):表示与self进行减法操作的另一个对象。

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

72-3、功能

        用于实现自定义类型的减法操作。

72-4、返回值

        返回值通常是减法操作的结果。

72-5、说明

        返回值可以是任何类型,但最好是与操作数(即self和other)具有相似性质的类型,以保持类型的一致性。

72-5-1、对于数字类型,返回值通常是一个数字。
72-5-2、对于向量类型,返回值通常是一个新的向量实例,表示两个向量的差。
72-5-3、对于集合或列表类型,返回值通常是一个新的集合或列表实例,表示差集。

72-6、用法
  1. # 072、__sub__方法:
  2. # 1、简单的数值相减
  3. class Number:
  4. def __init__(self, value):
  5. self.value = value
  6. def __sub__(self, other):
  7. if isinstance(other, Number):
  8. return Number(self.value - other.value)
  9. else:
  10. raise TypeError("Unsupported operand type")
  11. def __str__(self):
  12. return str(self.value)
  13. if __name__ == '__main__':
  14. a = Number(10)
  15. b = Number(5)
  16. c = a - b
  17. print(c) # 输出:5
  18. # 2、二维向量相减
  19. class Vector2D:
  20. def __init__(self, x, y):
  21. self.x = x
  22. self.y = y
  23. def __sub__(self, other):
  24. return Vector2D(self.x - other.x, self.y - other.y)
  25. def __str__(self):
  26. return f"({self.x}, {self.y})"
  27. if __name__ == '__main__':
  28. v1 = Vector2D(3, 6)
  29. v2 = Vector2D(5, 11)
  30. v3 = v1 - v2
  31. print(v3) # 输出:(-2, -5)
  32. # 3、时间差计算
  33. from datetime import datetime, timedelta
  34. class MyDateTime:
  35. def __init__(self, year, month, day):
  36. self.datetime = datetime(year, month, day)
  37. def __sub__(self, other):
  38. if isinstance(other, MyDateTime):
  39. delta = self.datetime - other.datetime
  40. return delta.days
  41. else:
  42. raise TypeError("Unsupported operand type")
  43. if __name__ == '__main__':
  44. date1 = MyDateTime(2019, 3, 13)
  45. date2 = MyDateTime(2024, 6, 8)
  46. days_difference = date2 - date1
  47. print(days_difference) # 输出:1914
  48. # 4、复数相减
  49. class ComplexNumber:
  50. def __init__(self, real, imag):
  51. self.real = real
  52. self.imag = imag
  53. def __sub__(self, other):
  54. return ComplexNumber(self.real - other.real, self.imag - other.imag)
  55. def __str__(self):
  56. return f"{self.real} + {self.imag}i"
  57. if __name__ == '__main__':
  58. c1 = ComplexNumber(3, 6)
  59. c2 = ComplexNumber(10, 24)
  60. c3 = c1 - c2
  61. print(c3) # 输出:-7 + -18i
  62. # 5、矩阵相减
  63. class Matrix:
  64. def __init__(self, data):
  65. self.data = data
  66. def __sub__(self, other):
  67. result = []
  68. for i in range(len(self.data)):
  69. row = []
  70. for j in range(len(self.data[0])):
  71. row.append(self.data[i][j] - other.data[i][j])
  72. result.append(row)
  73. return Matrix(result)
  74. def __str__(self):
  75. return str(self.data)
  76. if __name__ == '__main__':
  77. m1 = Matrix([[1, 2], [3, 4]])
  78. m2 = Matrix([[5, 6], [7, 8]])
  79. m3 = m1 - m2
  80. print(m3) # 输出: [[-4, -4], [-4, -4]]
  81. # 6、温度差计算
  82. class Temperature:
  83. def __init__(self, celsius):
  84. self.celsius = celsius
  85. def __sub__(self, other):
  86. return self.celsius - other.celsius
  87. if __name__ == '__main__':
  88. t1 = Temperature(25)
  89. t2 = Temperature(10)
  90. diff = t1 - t2
  91. print(diff) # 输出: 15
  92. # 7、货币值相减
  93. class Money:
  94. def __init__(self, amount, currency):
  95. self.amount = amount
  96. self.currency = currency
  97. def __sub__(self, other):
  98. if self.currency != other.currency:
  99. raise ValueError("Currencies must be the same")
  100. return Money(self.amount - other.amount, self.currency)
  101. if __name__ == '__main__':
  102. m1 = Money(100, "USD")
  103. m2 = Money(50, "USD")
  104. m3 = m1 - m2
  105. print(m3.amount, m3.currency) # 输出: 50 USD
  106. # 8、物理向量力的合成与分解(简化版)
  107. import math
  108. class ForceVector:
  109. def __init__(self, magnitude, angle):
  110. self.magnitude = magnitude
  111. self.angle = angle # 假设是相对于x轴的角度
  112. def __sub__(self, other):
  113. # 这里简化处理,只考虑x轴分量
  114. x1 = self.magnitude * math.cos(math.radians(self.angle))
  115. x2 = other.magnitude * math.cos(math.radians(other.angle))
  116. return ForceVector(x1 - x2, 0) # 假设只考虑x轴分量
  117. if __name__ == '__main__':
  118. f1 = ForceVector(10, 45)
  119. f2 = ForceVector(5, 0)
  120. f3 = f1 - f2
  121. print(f3)
  122. # f3现在是沿着x轴的简化后的合力,需要进一步的数学计算来处理角度和完整的二维或三维向量
  123. # 9、图像坐标点的差值
  124. class Point:
  125. def __init__(self, x, y):
  126. self.x = x
  127. self.y = y
  128. def __sub__(self, other):
  129. return Point(self.x - other.x, self.y - other.y)
  130. if __name__ == '__main__':
  131. p1 = Point(10, 20)
  132. p2 = Point(5, 10)
  133. p_diff = p1 - p2
  134. print(p_diff.x, p_diff.y) # 输出: 5 10
  135. # 10、电信号强度的差值计算
  136. class SignalStrength:
  137. def __init__(self, value):
  138. self.value = value
  139. def __sub__(self, other):
  140. return self.value - other.value
  141. if __name__ == '__main__':
  142. s1 = SignalStrength(100)
  143. s2 = SignalStrength(80)
  144. diff = s1 - s2
  145. print(diff) # 输出: 20
  146. # 11、综合案例
  147. class Account:
  148. def __init__(self, account_number, balance):
  149. self.account_number = account_number
  150. self.balance = balance
  151. def deposit(self, amount):
  152. self.balance += amount
  153. def withdraw(self, amount):
  154. if amount > self.balance:
  155. raise ValueError("Insufficient funds")
  156. self.balance -= amount
  157. def __sub__(self, other):
  158. # 假设这是一个转账操作,从self账户向other账户转账
  159. # 转账金额是self账户的当前余额
  160. if self.balance < 0:
  161. raise ValueError("Source account has negative balance")
  162. if not isinstance(other, Account):
  163. raise TypeError("Unsupported operand type")
  164. # 转账操作
  165. transfer_amount = self.balance
  166. self.withdraw(transfer_amount) # 从self账户扣款
  167. other.deposit(transfer_amount) # 向other账户存款
  168. # 返回一个包含两个账户新余额的元组
  169. return (self.balance, other.balance)
  170. def __str__(self):
  171. return f"Account {self.account_number} with balance {self.balance}"
  172. if __name__ == '__main__':
  173. account_a = Account("123456", 1000)
  174. account_b = Account("789012", 500)
  175. # 转账操作
  176. transfer_result = account_a - account_b
  177. print(f"After transfer, account_a: {account_a}, account_b: {account_b}")
  178. print(f"Transfer result: {transfer_result}")
  179. # After transfer, account_a: Account 123456 with balance 0, account_b: Account 789012 with balance 1500
  180. # Transfer result: (0, 1500)

73、__subclasscheck__方法:

73-1、语法
  1. __subclasscheck__(self, subclass, /)
  2. Check if a class is a subclass
73-2、参数

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

73-2-2、subclass(必须):表示你正在检查是否为self子类的类。

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

73-3、功能

        用于在Python的issubclass()函数中检查一个类是否是另一个类的子类。

73-4、返回值

        返回一个布尔值。

73-5、说明

 73-5-1、如果subclass被视为self的子类(根据自定义逻辑),则该方法应返回True。

 73-5-2、如果subclass不被视为self的子类,则该方法应返回False。

73-6、用法
  1. # 073、__subclasscheck__方法:
  2. # 1、简单的子类检查
  3. class Meta(type):
  4. def __subclasscheck__(cls, subclass):
  5. print(f"Checking if {subclass.__name__} is a subclass of {cls.__name__}")
  6. return super().__subclasscheck__(subclass)
  7. class Base(metaclass=Meta):
  8. pass
  9. class Derived(Base):
  10. pass
  11. print(issubclass(Derived, Base)) # 输出: Checking if Derived is a subclass of Base
  12. # 2、基于注解的子类检查
  13. class Meta(type):
  14. def __subclasscheck__(cls, subclass):
  15. if hasattr(subclass, 'annotation') and subclass.annotation == 'special':
  16. return True
  17. return super().__subclasscheck__(subclass)
  18. class Base(metaclass=Meta):
  19. pass
  20. class Derived(Base):
  21. annotation = 'special'
  22. class AnotherDerived(Base):
  23. pass
  24. print(issubclass(Derived, Base)) # 输出: True
  25. print(issubclass(AnotherDerived, Base)) # 输出: True
  26. # 3、自定义继承关系
  27. class Meta(type):
  28. def __subclasscheck__(cls, subclass):
  29. if subclass.__name__ == 'SpecialDerived':
  30. return True
  31. return super().__subclasscheck__(subclass)
  32. class Base(metaclass=Meta):
  33. pass
  34. class SpecialDerived:
  35. pass
  36. class NormalDerived(Base):
  37. pass
  38. print(issubclass(SpecialDerived, Base)) # 输出: True,尽管SpecialDerived不是Base的直接子类
  39. print(issubclass(NormalDerived, Base)) # 输出: True
  40. # 4、基于元类的抽象基类检查
  41. from abc import ABCMeta, abstractmethod
  42. class AbstractMeta(ABCMeta):
  43. def __subclasscheck__(cls, subclass):
  44. if not super().__subclasscheck__(subclass):
  45. return False
  46. for method in cls.__abstractmethods__:
  47. if not any(method in base.__dict__ for base in subclass.__mro__):
  48. return False
  49. return True
  50. class AbstractBase(metaclass=AbstractMeta):
  51. @abstractmethod
  52. def required_method(self):
  53. pass
  54. class GoodDerived(AbstractBase):
  55. def required_method(self):
  56. pass
  57. class BadDerived(AbstractBase):
  58. pass
  59. print(issubclass(GoodDerived, AbstractBase)) # 输出: True
  60. print(issubclass(BadDerived, AbstractBase)) # 输出: True
  61. # 5、标记子类为“已注册”
  62. class RegistryMeta(type):
  63. registry = []
  64. def __subclasscheck__(cls, subclass):
  65. if super().__subclasscheck__(subclass):
  66. if subclass not in cls.registry:
  67. cls.registry.append(subclass)
  68. print(f"Registered {subclass.__name__}")
  69. return True
  70. class Base(metaclass=RegistryMeta):
  71. pass
  72. class Derived1(Base):
  73. pass
  74. class Derived2(Base):
  75. pass
  76. print(Base.registry)

五、推荐阅读

1、Python筑基之旅

2、Python函数之旅

3、Python算法之旅

4、博客个人主页

文章知识点与官方知识档案匹配,可进一步学习相关知识
Python入门技能树首页概览425874 人正在系统学习中
遨游码海,我心飞扬
微信名片
注:本文转载自blog.csdn.net的神奇夜光杯的文章"https://myelsa1024.blog.csdn.net/article/details/139539394"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2491) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top