首页 最新 热门 推荐

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

Python-VBA函数之旅-super函数

  • 25-03-03 04:29
  • 3001
  • 11004
blog.csdn.net

目录

一、super函数的常见应用场景

二、super函数使用注意事项

三、如何用好super函数?

1、super函数:

1-1、Python:

1-2、VBA:

2、推荐阅读:

个人主页: https://myelsa1024.blog.csdn.net/

一、super函数的常见应用场景

        在Python中,super()函数在面向对象编程的继承关系中有着广泛的应用,常见的应用场景有:

1、构造函数调用:在子类的构造函数中,super()函数可以用于调用父类的构造函数,确保子类对象具有父类的属性和行为,这是通过super().__init__(...)实现的,其中`...`是传递给父类构造函数的参数。

2、方法调用:super()函数也可以在子类中用于调用父类的方法,这允许子类在需要时重用或扩展父类的方法。例如,super().method_name(...)会调用父类中定义的method_name方法。

3、混入类(Mixin):混入类是一种特殊类型的类,旨在通过多重继承为其他类提供额外的功能,在混入类中使用super()函数可以确保方法的调用顺序是按照继承链的顺序来执行的,从而保持代码的一致性和可维护性。

4、多重继承:在多重继承的场景中,super()函数特别有用,多重继承允许一个类继承自多个父类,但这也可能导致方法调用冲突或混淆,使用super()函数可以确保方法按照预定的顺序(即方法解析顺序,MRO)被调用,从而避免这些问题。

5、修改继承结构:通过动态地改变继承关系,可以使用super()函数来创建更灵活的类结构。例如,可以使用type()函数在运行时创建新类,并将它们添加到现有的继承结构中。

6、框架和库开发:在开发框架或库时,super()函数经常用于实现可扩展的API,框架可以定义一些基类,这些基类提供了一些默认的行为,而开发者可以通过继承这些基类并覆盖其中的方法来扩展这些行为。通过使用super()函数,子类可以确保在覆盖方法时不会丢失父类的功能。

7、设计模式实现:super()函数也可以用于实现一些设计模式,如模板方法模式、组合模式等,在这些模式中,super()函数可以帮助子类在扩展功能时保持与父类的一致性。

        注意,虽然super()函数提供了强大的功能,但在使用它时也需要谨慎;过度使用super()函数可能会导致代码难以理解和维护,因此,在决定是否使用super()函数时,应该仔细考虑其是否真正符合你的需求,并权衡其带来的好处和潜在的问题。

二、super函数使用注意事项

        在Python中使用super()函数时,需要注意以下几个事项:

1、确保使用在正确的方法中:super()函数通常用于调用父类(或兄弟类,在多重继承的情况下)的方法,尤其是在`__init__`、`__enter__`、`__exit__`以及其他一些你可能需要重写的特殊方法或常规方法中,不过,不是所有的方法都需要或应该使用super()函数。

2、在子类中始终使用super()函数:如果你决定在一个子类的某个方法中使用super()函数来调用父类的方法,那么在该子类的所有子类中,你也应该使用super()函数来调用该方法,以保持继承的一致性。

3、不要调用super()函数超过一次:在同一个方法内,不要多次调用super()函数来执行同一个父类方法,除非你有明确的理由要这样做,这可能会导致父类方法被多次执行,从而产生意外的副作用。

4、理解方法解析顺序(MRO):在多重继承的情况下,Python使用C3线性化算法来确定方法解析顺序(MRO),了解MRO的工作原理有助于你理解super()函数是如何工作的,以及为什么它会按照特定的顺序调用父类方法。

5、注意Python 2和Python 3的区别:Python 2和Python 3在super()函数的使用上有所不同:在Python 2中,super()通常需要传入两个参数:类本身和实例;而在Python 3中,super()可以不带参数调用,Python会自动推断出这两个参数。

6、避免直接引用父类:当你使用super()函数时,最好不要直接引用父类名来调用方法,这样做会破坏继承的灵活性,因为如果你更改了父类,或者类被继承自不同的父类,那么你的代码就需要进行更改,使用super()函数可以确保你的代码更加健壮和可维护。

7、不要在静态方法/类方法/属性上使用super()函数:super()函数用于在实例方法之间建立合作关系,以便在调用时正确地访问继承的层次结构,静态方法、类方法和属性与实例无关,因此它们不应该使用super()函数。

8、不要过度使用super()函数:虽然super()函数在某些情况下非常有用,但过度使用它可能会导致代码难以理解和维护,在决定使用super()函数之前,请确保它确实能够简化你的代码并提高可维护性。

三、如何用好super函数?

        在Python中,要正确地使用super()函数,需遵循以下建议:

1、理解继承和多态:在使用super()函数之前,确保你理解面向对象编程中的继承和多态概念,super()函数主要用于在子类中调用父类的方法,以支持继承和多态。

2、遵循Python的继承约定:在Python中,如果类要设计为被继承,那么它的构造函数(`__init__`方法)应该总是调用其基类的构造函数,这通常通过使用super().__init__()来完成,这样做可以确保基类中的任何初始化逻辑都能被执行,且子类可以在其基础上添加或修改状态。

3、避免直接引用父类:在子类中,尽量避免直接引用父类的类名来调用其方法,使用super()代替直接引用,可以增加代码的灵活性和可维护性,当类层次结构发生变化时(例如,更改了父类),使用super()函数的代码通常不需要修改。

4、理解方法解析顺序(MRO):在多重继承的情况下,了解Python的MRO(方法解析顺序)是非常重要的,这有助于你理解super()函数是如何在多个父类之间查找和调用方法的,Python使用C3线性化算法来确定MRO。

5、注意super()函数的调用上下文:在子类中调用super()时,它会自动绑定到当前实例和当前类,这意味着你不需要显式地传递这些参数,但是,请注意super()函数的调用上下文必须在类的定义内部,如果你在类外部(例如在实例方法或普通函数中)调用super()函数,它将无法正常工作。

6、谨慎使用super()在静态方法或类方法中:由于静态方法和类方法与实例无关,因此它们通常不需要使用`super()`来调用父类的方法,如果你需要在静态方法或类方法中访问父类的行为,请考虑将其重构为实例方法或使用其他设计模式。

7、不要过度使用super()函数:虽然super()函数在某些情况下非常有用,但过度使用它可能会导致代码变得复杂和难以理解,在决定是否使用super()函数时,请权衡其带来的好处和潜在的问题,如果可能的话,尽量保持代码简单和直观。

8、测试你的代码:在使用super()函数时,确保对你的代码进行充分的测试,这有助于确保你的代码在所有预期的情况下都能正常工作,并帮助你发现任何潜在的问题或错误。

9、阅读文档和示例:Python的官方文档和社区资源提供了大量关于super()函数的文档和示例,阅读这些资源可以帮助你更深入地了解super()函数的工作原理和最佳实践。

10、实践:最后但同样重要的是,通过实践来熟悉super()函数的使用,尝试在小型项目中使用它,并逐步扩展到更大的项目中;通过实践,你将能够更好地理解super()函数的用途和限制,并找到最适合你的编程风格和工作流程的方法。

1、super函数:
1-1、Python:
  1. # 1.函数:super
  2. # 2.功能:用于调用父类(超类)的一个方法,该方法多用来解决多重继承的问题
  3. # 3.语法:super([type[, object_or_type=None]])
  4. # 4.参数:
  5. # 4-1、type:类
  6. # 4-2、object_or_type:确定用于查找的顺序MRO(method resolution order),此时,搜索会从type所指定的类之后的类开始,通常情况下,设置为self
  7. # 5.返回值:返回一个代理对象,它会将方法调用委托给type的父类或兄弟类
  8. # 6.说明:
  9. # 6-1、单继承:可以直接使用类名调用父类方法
  10. # 6-2、多继承:涉及查找顺序MRO(method resolution order)、重复调用(钻石继承)等多种问题时,需要使用super()函数来调用
  11. # 7.示例:
  12. # 用dir()函数获取该函数内置的属性和方法
  13. print(dir(super))
  14. # ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__',
  15. # '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__',
  16. # '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__self_class__', '__setattr__', '__sizeof__', '__str__',
  17. # '__subclasshook__', '__thisclass__']
  18. # 用help()函数获取该函数的文档信息
  19. help(super)
  20. # 应用一:构造函数调用
  21. # 示例1:单继承示例
  22. class Parent:
  23. def __init__(self, parent_attr):
  24. self.parent_attr = parent_attr
  25. print(f"Parent.__init__ called with {parent_attr}")
  26. class Child(Parent):
  27. def __init__(self, parent_attr, child_attr):
  28. super().__init__(parent_attr) # 调用父类的构造函数
  29. self.child_attr = child_attr
  30. print(f"Child.__init__ called with {child_attr}")
  31. # 使用示例
  32. c = Child("parent", "child")
  33. # Parent.__init__ called with parent
  34. # Child.__init__ called with child
  35. # 示例2:多继承示例
  36. class Parent1:
  37. def __init__(self, attr1):
  38. self.attr1 = attr1
  39. print(f"Parent1.__init__ called with {attr1}")
  40. class Parent2:
  41. def __init__(self, attr2):
  42. self.attr2 = attr2
  43. print(f"Parent2.__init__ called with {attr2}")
  44. class Child(Parent1, Parent2):
  45. def __init__(self, attr1, attr2, child_attr):
  46. super().__init__(attr1) # 通常会调用方法解析顺序(MRO)中的第一个父类
  47. # 如果需要显式地调用第二个父类的构造函数,你可以这样做:
  48. # Parent2.__init__(self, attr2)
  49. # 但通常不推荐这样做,因为它打破了使用super()的初衷
  50. # 另一种方法是通过super()多次调用,但这取决于具体的MRO和Python版本
  51. # 例如,在Python 3中,你可以这样做(但这不是标准做法):
  52. # super(Parent1, self).__init__(attr2)
  53. # 在这个例子中,我们假设Parent2的初始化不依赖于Parent1,所以我们可以直接调用它
  54. Parent2.__init__(self, attr2)
  55. self.child_attr = child_attr
  56. print(f"Child.__init__ called with {child_attr}")
  57. # 使用示例
  58. c = Child("parent1", "parent2", "child")
  59. # Parent1.__init__ called with parent1
  60. # Parent2.__init__ called with parent2
  61. # Child.__init__ called with child
  62. # 应用二:方法调用
  63. # 示例1:单继承示例
  64. class Parent:
  65. def greet(self):
  66. print("Hello from Parent!")
  67. class Child(Parent):
  68. def greet(self):
  69. super().greet() # 调用父类的greet方法
  70. print("Hello from Child!")
  71. # 使用示例
  72. c = Child()
  73. c.greet()
  74. # Hello from Parent!
  75. # Hello from Child!
  76. # 示例2:多继承示例
  77. class Grandparent:
  78. def greet(self):
  79. print("Hello from Grandparent!")
  80. class Parent1(Grandparent):
  81. def greet(self):
  82. super().greet() # 调用Grandparent的greet方法
  83. print("Hello from Parent1!")
  84. class Parent2:
  85. def greet(self):
  86. print("Hello from Parent2!")
  87. class Child(Parent1, Parent2):
  88. def greet(self):
  89. super().greet() # 调用Parent1的greet方法,它会继续调用Grandparent的greet方法
  90. print("Hello from Child!")
  91. # 使用示例
  92. c = Child()
  93. c.greet()
  94. # Hello from Grandparent!
  95. # Hello from Parent1!
  96. # Hello from Child!
  97. # 应用三:混入类(Mixin)
  98. class LoggingMixin:
  99. def log(self, message):
  100. print(f"Logging: {message}")
  101. # 不再需要调用super().do_something(),因为LoggingMixin没有基类
  102. def do_something_after_logging(self):
  103. self.log("Something was done.")
  104. class BaseClass:
  105. def do_something(self):
  106. print("BaseClass: Doing something.")
  107. class MyClass(BaseClass, LoggingMixin):
  108. def __init__(self):
  109. super().__init__() # 注意:这里实际上并没有在BaseClass或LoggingMixin中定义__init__,但为了习惯还是调用了
  110. def do_something(self):
  111. super().do_something() # 调用BaseClass的do_something方法
  112. self.do_something_after_logging() # 调用LoggingMixin的do_something_after_logging方法来记录日志
  113. # 使用示例
  114. obj = MyClass()
  115. obj.do_something() # 输出:BaseClass: Doing something. 和 Logging: Something was done.
  116. # BaseClass: Doing something.
  117. # Logging: Something was done.
  118. # 应用四:多重继承
  119. class ParentA:
  120. def __init__(self):
  121. print("Initializing ParentA")
  122. super().__init__() # 通常情况下,ParentA没有父类,这行是可选的
  123. def feature(self):
  124. print("Feature from ParentA")
  125. class ParentB:
  126. def __init__(self):
  127. print("Initializing ParentB")
  128. super().__init__() # 通常情况下,ParentB没有父类,这行是可选的
  129. def feature(self):
  130. print("Feature from ParentB")
  131. class Child(ParentA, ParentB):
  132. def __init__(self):
  133. print("Initializing Child")
  134. super().__init__() # 调用MRO中的下一个类的__init__方法
  135. def feature(self):
  136. print("Starting Child feature")
  137. super().feature() # 调用MRO中的下一个类的feature方法
  138. print("Finishing Child feature")
  139. # 使用示例
  140. obj = Child()
  141. obj.feature()
  142. # Initializing Child
  143. # Initializing ParentA
  144. # Initializing ParentB
  145. # Starting Child feature
  146. # Feature from ParentA
  147. # Finishing Child feature
  148. # 应用五:修改继承结构
  149. class Grandparent:
  150. def __init__(self):
  151. print("Initializing Grandparent")
  152. def greet(self):
  153. print("Hello from Grandparent")
  154. class ParentA(Grandparent):
  155. def __init__(self):
  156. print("Initializing ParentA")
  157. super().__init__() # 调用Grandparent的__init__方法
  158. def greet(self):
  159. print("Hello from ParentA")
  160. super().greet() # 调用Grandparent的greet方法
  161. class ParentB(Grandparent):
  162. def __init__(self):
  163. print("Initializing ParentB")
  164. super().__init__() # 调用Grandparent的__init__方法
  165. def greet(self):
  166. print("Hello from ParentB")
  167. super().greet() # 调用Grandparent的greet方法
  168. class Child(ParentA, ParentB):
  169. def __init__(self):
  170. print("Initializing Child")
  171. super().__init__() # 这将调用ParentA的__init__,因为ParentA在MRO中排在前面
  172. def greet(self):
  173. print("Hello from Child")
  174. super().greet() # 这将首先调用ParentA的greet,然后是Grandparent的greet(如果ParentA中没有再次调用super())
  175. # 使用示例
  176. child = Child()
  177. child.greet()
  178. # Initializing Child
  179. # Initializing ParentA
  180. # Initializing ParentB
  181. # Initializing Grandparent
  182. # Hello from Child
  183. # Hello from ParentA
  184. # Hello from ParentB
  185. # Hello from Grandparent
  186. # 应用六:框架和库开发
  187. class PluginBase:
  188. def __init__(self):
  189. print("Initializing PluginBase")
  190. def activate(self):
  191. print("Activating PluginBase")
  192. self._specific_activation() # 假设有一个特定于插件的激活方法
  193. def _specific_activation(self):
  194. # 这是一个预期被子类覆盖的方法
  195. raise NotImplementedError("Subclasses must implement this method")
  196. class PluginA(PluginBase):
  197. def __init__(self):
  198. super().__init__() # 调用父类的初始化方法
  199. print("Initializing PluginA")
  200. def _specific_activation(self):
  201. # 实现特定于PluginA的激活逻辑
  202. print("Activating PluginA specific functionality")
  203. class PluginB(PluginBase):
  204. def __init__(self):
  205. super().__init__() # 调用父类的初始化方法
  206. print("Initializing PluginB")
  207. def _specific_activation(self):
  208. # 实现特定于PluginB的激活逻辑
  209. print("Activating PluginB specific functionality")
  210. # 框架的某部分,负责插件的管理和激活
  211. class PluginManager:
  212. def __init__(self):
  213. self.plugins = []
  214. def register(self, plugin):
  215. self.plugins.append(plugin)
  216. def activate_all(self):
  217. for plugin in self.plugins:
  218. plugin.activate() # 调用插件的激活方法
  219. # 使用示例
  220. manager = PluginManager()
  221. manager.register(PluginA())
  222. manager.register(PluginB())
  223. manager.activate_all() # 这将激活所有注册的插件
  224. # Initializing PluginBase
  225. # Initializing PluginA
  226. # Initializing PluginBase
  227. # Initializing PluginB
  228. # Activating PluginBase
  229. # Activating PluginA specific functionality
  230. # Activating PluginBase
  231. # Activating PluginB specific functionality
  232. # 应用七:设计模式实现
  233. # 定义一个抽象类,其中包含模板方法和一些具体方法
  234. class AbstractClass:
  235. # 模板方法,定义了算法框架
  236. def template_method(self):
  237. # 调用第一个具体方法
  238. self.specific_method1()
  239. # 调用钩子方法(可以被子类覆盖)
  240. self.hook_method()
  241. # 调用第二个具体方法
  242. self.specific_method2()
  243. # 第一个具体方法
  244. def specific_method1(self):
  245. print("Executing specific method 1 from AbstractClass")
  246. # 第二个具体方法
  247. def specific_method2(self):
  248. print("Executing specific method 2 from AbstractClass")
  249. # 钩子方法,默认不执行任何操作,但可以被子类覆盖
  250. def hook_method(self):
  251. pass
  252. # 定义一个继承自AbstractClass的类ConcreteClassA
  253. class ConcreteClassA(AbstractClass):
  254. # 覆盖父类的第一个具体方法
  255. def specific_method1(self):
  256. # 首先调用父类的实现(如果需要的话)
  257. super().specific_method1()
  258. # 然后执行自己的实现
  259. print("Executing specific method 1 from ConcreteClassA")
  260. # 覆盖父类的钩子方法
  261. def hook_method(self):
  262. print("Executing hook method from ConcreteClassA")
  263. # 定义一个继承自AbstractClass的类ConcreteClassB
  264. class ConcreteClassB(AbstractClass):
  265. # 覆盖父类的第二个具体方法
  266. def specific_method2(self):
  267. # 首先调用父类的实现(如果需要的话)
  268. super().specific_method2()
  269. # 然后执行自己的实现
  270. print("Executing specific method 2 from ConcreteClassB")
  271. # 创建ConcreteClassA的实例a
  272. a = ConcreteClassA()
  273. # 调用模板方法,按照算法框架执行
  274. a.template_method()
  275. # 创建ConcreteClassB的实例b
  276. b = ConcreteClassB()
  277. # 调用模板方法,按照算法框架执行
  278. b.template_method()
  279. # Executing specific method 1 from AbstractClass
  280. # Executing specific method 1 from ConcreteClassA
  281. # Executing hook method from ConcreteClassA
  282. # Executing specific method 2 from AbstractClass
  283. # Executing specific method 1 from AbstractClass
  284. # Executing specific method 2 from AbstractClass
  285. # Executing specific method 2 from ConcreteClassB
1-2、VBA:
略,待后补。
2、推荐阅读:

2-1、Python-VBA函数之旅-callable()函数

Python算法之旅:Algorithms

Python函数之旅:Functions

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

/ 登录

评论记录:

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

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (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-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top