Python @staticmethod、super().__init__()和self

最近在看代码,由于之前没有系统学习过Python,就有些知识点不是很清楚,这里整理一下,方便以后查阅。

Python中的@staticmethod\super.init和self

  • Python 装饰器
  • @staticmethod和@classmethod的作用与区别
    • 作用
    • 区别
    • 代码演示
  • super() 函数
  • super().__init__()函数
    • super().__init__()基本用法
    • super().__init__() 和 super(Child, self).__init__() 的区别
      • 参数传递方式:
      • 多继承中的 super().__init__()
      • 多继承中的 super(Child, self).__init__()
  • self 代表类的实例,而非类
  • 参考资料

Python 装饰器

装饰器(decorators)是 Python 中的一种高级功能,它允许你动态地修改函数或类的行为。

装饰器是一种函数,它接受一个函数作为参数,并返回一个新的函数或修改原来的函数。

装饰器的语法使用 @decorator_name 来应用在函数或方法上。

Python 还提供了一些内置的装饰器,比如 @staticmethod@classmethod,用于定义静态方法和类方法。

装饰器的应用场景:

  1. 日志记录: 装饰器可用于记录函数的调用信息、参数和返回值。
  2. 性能分析: 可以使用装饰器来测量函数的执行时间。
  3. 权限控制: 装饰器可用于限制对某些函数的访问权限。
  4. 缓存: 装饰器可用于实现函数结果的缓存,以提高性能。

使用装饰器

装饰器通过 @ 符号应用在函数定义之前,例如:

@time_logger
def target_function():pass

等同于:

def target_function():pass
target_function = time_logger(target_function)

这会将 target_function 函数传递给 decorator 装饰器,并将返回的函数重新赋值给 target_function。从而,每次调用 target_function 时,实际上是调用了经过装饰器处理后的函数。

通过装饰器,开发者可以在保持代码整洁的同时,灵活且高效地扩展程序的功能。

@staticmethod和@classmethod的作用与区别

作用

一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。但是使用@staticmethod或@classmethod,就可以不需要实例化。

所以@staticmethod或@classmethod作用:使用@staticmethod或@classmethod,就可以不需要实例化,直接“类名.方法名()”来调用。这有利于组织代码,把某些应该属于某个类的函数给放到那个类里去,同时有利于命名空间的整洁。

区别

  1. @staticmethod不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。@classmethod也不需要self参数,但第一个参数需要是表示自身类的cls参数。
  2. @classmethod 是一个函数修饰符,它表示接下来的是一个类方法,而对于平常我们见到的则叫做实例方法。类方法的第一个参数cls,而实例方法的第一个参数是self,表示该类的一个实例。
    类方法有类变量cls传入,从而可以用cls做一些相关的处理。并且有子类继承时,调用该类方法时,传入的类变量cls是子类,而非父类。
    对于类方法,可以通过类来调用,就像Test.foo(),有点类似C++中的静态方法, 也可以通过类的一个实例来调用,就像Test().foo(),这里Test(),写成这样之后它就是类的一个实例了。
  3. 静态方法它基本上跟一个全局函数相同,一般来说用的很少。
  4. 在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。
    而@classmethod因为持有cls参数(当然,也可以用“self” 代替,个人认为是为了和类的self区分才用cls的),可以来调用类的属性,类的方法,实例化对象等,避免硬编码。

代码演示

class A(object):bar = 1def foo(self):print('foo')@staticmethoddef static_foo():print('static_foo')print(A.bar)@classmethoddef class_foo(cls):print('class_foo')print(cls.bar)cls().foo()A.static_foo()
A.class_foo()'''输出结果
static_foo
1
class_foo
1
foo
'''

super() 函数

super() 函数是用于调用父类(超类)的一个方法。

super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。

MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。

super().init()函数

super().__init__() 是用于在 Python 中调用父类(也称为超类或基类)的构造方法(init 方法)的一种方式。这通常在子类的构造方法中使用,以便在添加子类特有的功能之前,初始化父类中定义的属性和执行其他必要的设置。

super()用来调用父类(基类)的方法,init()是类的构造方法,
super().__init__() 就是调用父类的__init__()方法, 同样可以使用super()去调用父类的其他方法。

super().init()基本用法

以下是一个基本示例,展示了如何在子类的构造方法中使用 super().init():

class Parent:def __init__(self, name):self.name = nameclass Child(Parent):def __init__(self, name, age):super().__init__(name)  # 调用父类的构造方法以初始化 nameself.age = age #添加自定义age属性child = Child("Alice", 25)
print(child.name)  # 输出 "Alice"
print(child.age)   # 输出 25

super().init() 和 super(Child, self).init() 的区别

super().init() 和 super(Child, self).init() 都是用于调用父类的构造方法,但它们之间有一个重要的区别:

参数传递方式:

  • super().__init__(): 这种方式不需要显式传递当前类和实例(self)作为参数,Python会自动识别当前类和实例。这是一种简化的写法,通常用于单继承的情况。

  • super(Child, self).__init__(): 这种方式明确指定了当前类(Child)和实例(self)作为参数传递给 super()。这种方式通常在多继承的情况下使用,以明确指定要调用哪个父类的构造方法。

多继承中的 super().init()

如果类是多继承的,使用 super(Child, self).init() 可以更明确地控制调用的是哪个父类的构造方法,因为 super() 可以基于参数中的当前类(Child)找到正确的父类。

下面是一个多继承的示例,演示了使用super().init() 和 super(Child, self).init() 的区别:

class Parent1:def __init__(self):print("Parent1 constructor")class Parent2:def __init__(self):print("Parent2 constructor")class Parent3:def __init__(self):print("Parent3 constructor")class Child(Parent1,Parent2,Parent3):    # 顺序为Parent1,Parent2,Parent3def __init__(self):super().__init__()               # 使用简化写法,调用了 Parent1 的构造方法child = Child()
#输出结果:Parent1 constructor

接下来将Child继承父类中Parent1,Parent2的顺序进行调换,运行结果如下:

#把Parent1,Parent2的顺序进行调换
class Parent1:def __init__(self):print("Parent1 constructor")class Parent2:def __init__(self):print("Parent2 constructor")class Parent3:def __init__(self):print("Parent3 constructor")class Child(Parent2,Parent1,Parent3):    # 顺序为Parent2,Parent1,Parent3def __init__(self):super().__init__()               # 使用简化写法,调用了 Parent2 的构造方法child = Child()
#输出结果:
#Parent2 constructor

在上面的示例中,我们可以知道,在多继承的情况下,super().init() 调用的是子类(Child)继承父类中,第一个父类的构造方法。

多继承中的 super(Child, self).init()

class Parent1:def __init__(self):print("Parent1 constructor")class Parent2:def __init__(self):print("Parent2 constructor")class Parent3:def __init__(self):print("Parent3 constructor")class Child(Parent1, Parent2,Parent3):def __init__(self):super(Child, self).__init__()     # 调用Child下一个父类的构造方法,即Parent1super(Parent2, self).__init__()   # 调用Parent2下一个父类的构造方法,即Parent3child = Child()
#输出结果:
#Parent1 constructor
#Parent3 constructor

综上,我们可以知道,在多继承中,super().init() 继承的是子类继承的第一个父类,super(Parent2, self).init() 继承的是声明类的下一个父类

self 代表类的实例,而非类

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。

class Test:def prt(self):print(self)print(self.__class__)t = Test()
t.prt()

以上实例执行结果为:

<__main__.Test instance at 0x100771878>
__main__.Test

从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。

self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的:

class Test:def prt(runoob):print(runoob)print(runoob.__class__)t = Test()
t.prt()

以上实例执行结果为:

<__main__.Test instance at 0x100771878>
__main__.Test

在 Python中,self 是一个惯用的名称,用于表示类的实例(对象)自身。它是一个指向实例的引用,使得类的方法能够访问和操作实例的属性。

当你定义一个类,并在类中定义方法时,第一个参数通常被命名为 self,尽管你可以使用其他名称,但强烈建议使用 self,以保持代码的一致性和可读性。

class MyClass:def __init__(self, value):self.value = valuedef display_value(self):print(self.value)# 创建一个类的实例
obj = MyClass(42) # 调用实例的方法
obj.display_value() # 输出 42

参考资料

Python方法:@staticmethod和@classmethod

Python 装饰器

super().init()函数

Python super 详解

Python super() 函数

Python3 面向对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/47825.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【STM32 HAL库】DMA+串口

DMA 直接存储器访问 DMA传输&#xff0c;将数据从一个地址空间复制到另一个地址空间。-----“数据搬运工”。 DMA传输无需CPU直接控制传输&#xff0c;也没有中断处理方式那样保留现场和恢复现场&#xff0c;它是通过硬件为RAM和IO设备开辟一条直接传输数据的通道&#xff0c…

opencv 优势

OpenCV(开源计算机视觉库)是一个广泛使用的计算机视觉和机器学习软件框架。它最初由Intel开发,后来由Itseez公司维护,最终于2015年成为非营利组织OpenCV.org的一部分。OpenCV的目的是实现一个易于使用且高效的计算机视觉框架,支持实时视觉应用。 以下是关于OpenCV的一些关…

浅谈断言之XML断言

浅谈断言之XML断言 XML断言是JMeter的一个组件&#xff0c;用于验证请求的响应数据是否符合XML结构。这对于测试返回XML格式数据的Web服务特别有用。 如何添加XML断言&#xff1f; 要在JMeter测试计划中添加XML断言&#xff0c;遵循以下步骤&#xff1a; 打开测试计划&…

CentOS 6.8 中部署 Spring Boot 应用程序

在CentOS 6.8的系统中本来想通过docker或者宝塔免费来快速部署&#xff0c;结果发现CentOS6.8版本比较老&#xff0c;装docker或宝塔面板都非常费劲&#xff0c;算了就用传统的方式来安装吧。 在 CentOS 6.8 中通过传统的方式部署 Spring Boot 应用程序主要涉及以下几个步骤&a…

Flutter 插件之 easy_refresh(下拉刷新、上拉加载)

今天给大家较少一下日常开发中最常见的一个功能,就是 下拉刷新、上拉加载,这个在我们使用分页功能是最常见的。 此前我我也写了一篇关于 下拉刷新、上拉加载。 Flutter 下拉刷新、上拉加载flutter_easyrefresh的使用https://blog.csdn.net/WangQingLei0307/article/details/…

Logback 配置文件加载步骤

Logback的初始化过程有多个步骤&#xff0c;确保在不同情况下都能找到并加载适当的配置文件。以下是详细的步骤描述&#xff1a; Logback 配置文件加载步骤 检查系统属性 logback.configurationFile Logback 首先检查系统属性 logback.configurationFile 是否设置。如果设置了…

学习记录--Bert、Albert、RoBerta

目录 Bert 1&#xff1a;输入 2&#xff1a;Bert结构 3&#xff1a;模型预训练 Albert 1&#xff1a;SOP任务 2&#xff1a;embedding因式分解 3&#xff1a;参数共享 RoBerta 参考&#xff1a; BERT原理和结构详解_bert结构-CSDN博客 [LLM] 自然语言处理 --- ALBER…

实现一个自己的OpenFeign 远程调用验证协议--Springboot 自定义拦截器验证请求合法性--xunznux

Springboot 如何实现一个自定义的拦截器处理系统发出的请求以及接收到的请求&#xff08;实现一个用于feign远程调用验证的简单协议&#xff09; 文章目录 Springboot 如何实现一个自定义的拦截器处理系统发出的请求以及接收到的请求&#xff08;实现一个用于feign远程调用验证…

某企业网络及服务器规划与设计

目录 1. 项目需求与设计... 5 1.1 项目需求... 5 1.2 组建企业网络内部网的流程... 5 1) 构思阶段... 5 2) 方案设计阶段... 6 3) 工程实施阶段... 6 4) 测试验收... 6 5) 管理维护... 7 1.3 技术可行性分析... 7 1.4 网络组网规则... 8 1.5 网络拓扑... 8 2. 项目所…

【UE5】在Widget中显示3D网格体

效果 步骤 1. 新建一个工程并添加第三人称游戏资源包 2. 添加一个控件蓝图&#xff0c;这里命名为“WBP_3DOverlay”&#xff0c;用于显示3D网格体 打开“WBP_3DOverlay”&#xff0c;添加一个画布面板和一个背景模糊控件&#xff0c;这里模糊强度设置为10 3. 打开第三人称角色…

connect的非阻塞模式

本文参考&#xff1a;connect 函数在阻塞和非阻塞模式下的行为 一般情况下&#xff0c;在使用connect连接服务端时&#xff0c;需要等待一会儿才会函数才会返回&#xff0c;导致程序阻塞。为了降低阻塞的影响&#xff0c;我们可能会单独开个线程处理connect请求&#xff0c;例…

Spark-第一周

一、spark是什么 Spark是一种快速、通用、可扩展的大数据分析引擎 2009年诞生于加州大学伯克利分校AMPLab&#xff0c;2010年开源&#xff0c;2013年6月成为Apache孵化项目&#xff0c;2014年2月成为Apache顶级项目。 目前&#xff0c;Spark生态系统已经发展成为一个包含多个…

常见的数据集格式

常见的数据集格式有三种&#xff0c;分别为voc(xml)、coco(json)、yolo(txt)。 1 VOC VOC数据集由五个部分构成&#xff1a;JPEGImages&#xff0c;Annotations&#xff0c;ImageSets&#xff0c;SegmentationClass以及SegmentationObject. . └── VOC #根目…

HAL库源码移植与使用之RTC时钟

实时时钟(Real Time Clock&#xff0c;RTC)&#xff0c;本质是一个计数器&#xff0c;计数频率常为秒&#xff0c;专门用来记录时间。 普通定时器无法掉电运行&#xff01;但RTC可由VBAT备用电源供电&#xff0c;断电不断时 这里讲F1系列的RTC 可以产生三个中断信号&#xff…

Kafka之存储设计

文章目录 1. 分区和副本的存储结构1. 分区和副本的分布2. 存储目录结构3. 文件描述 2. 相关配置3. 数据文件类型4. 数据定位原理LogSegment 类UnifiedLog 类 5. 副本数据同步HW水位线LEO末端偏移量HW更新原理 6. 数据清除 1. 分区和副本的存储结构 在一个多 broker 的 Kafka 集…

文心一言大模型

文心一言是百度基于其强大的“文心”大模型技术推出的生成式AI产品&#xff08;英文名&#xff1a;ERNIE Bot&#xff09;。以下是关于文心一言的详细介绍&#xff1a; 一、产品定位与功能 定位&#xff1a;文心一言被定位为人工智能基座型的赋能平台&#xff0c;旨在助力金融…

8 Vue 开发方案

通用需求 axios 封装 封装 axios 请求 import axios from axios // 导入 axios// 第一种: 直接配置在 axios 上(无法配置多个) axios.defaults.baseURL http://ttapi.research.itcast.cn/// 第二种: 使用 create 方法创建一个 axios 实例化对象(能够配置多个) // 1. 设置基准…

MFC:以消息为基础的事件驱动系统和消息映射机制

以消息为基础的事件驱动系统和消息映射机制 (1)消息 A.What&#xff08;什么是消息&#xff09; 本质是一个数据结构&#xff0c;用于应用程序不同部分之间进行通信和交互 typedef struct tagMSG {HWND hwnd; // 接收该消息的窗口句柄UINT message; // 消息标…

【C语言】 利用栈完成十进制转二进制(分文件编译,堆区申请空间malloc)

利用栈先进后出的特性&#xff0c;在函数内部&#xff0c;进行除二取余的操作&#xff0c;把每次的余数存入栈内&#xff0c;最后输出刚好就是逆序输出&#xff0c;为二进制数 学习过程中&#xff0c;对存储栈进行堆区的内存申请时候&#xff0c;并不是很熟练&#xff0c;一开始…

双边性:构建神经网络的新方法

正如承诺的那样&#xff0c;这是最近我遇到的最有趣的想法之一的第二部分。如果你错过了&#xff0c;请务必观看本系列的第一部分 - 神经科学家对改进神经网络的看法 - 我们讨论了双边性的生物学基础以及我们大脑的不对称性质如何带来更高的性能。 在这篇文章中&#xff0c;我…