菜鸟教程《Python 3 教程》笔记(20):面向对象
菜鸟教程《Python 3 教程》笔记(20)
- 20 面向对象
- 20.1 面向对象技术简介
- 20.2 创建类
- 20.2.1 类定义
- 20.2.2 实例化
- 20.2.3 初始化
- 20.2.4 类变量、实例变量
- 20.2.5 类方法、实例方法、静态方法
- 20.3 访问可见性
- 20.3.1 @property装饰器
- 20.4 动态性
- 20.4.1 __slots__魔法
- 20.5 继承
- 20.5.1 多继承
- 20.5.2 super() 函数
- 20.6 多态
- 20.7 类的专有方法
- 20.7.1 运算符重载
笔记带有个人侧重点,不追求面面俱到。
20 面向对象
出处: 菜鸟教程 - Python3 面向对象
参考内容:
- GtiHub - jackfrued: Python-100-Days/09.面向对象进阶
- 知乎 - 泽霖: python类的实例方法、静态方法和类方法区别
20.1 面向对象技术简介
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 方法: 类中定义的函数。
- 类变量: 类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
- 局部变量: 定义在方法中的变量,只作用于当前实例的类。
- 实例变量: 在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
- 数据成员: 类变量或者实例变量用于处理类及其实例对象的相关的数据。
- 实例化: 创建一个类的实例,类的具体对象。
- 对象: 通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
- 继承: 即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
- 方法重写: 如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
20.2 创建类
20.2.1 类定义
使用 class 定义类。
class ClassName:<statement-1>...<statement-N>
最好使用
class ClassName(object)的形式定义类。
类的属性和方法:
class ClassName(object):a = 0def fuc():print("Hello")
20.2.2 实例化
通过下述方法可以创建类实例。
obj = Myclass()
20.2.3 初始化
类有一个名为 __init__() 的特殊方法(构造方法),该方法在类实例化时会自动调用。
class Complex:def __init__(self, realpart, imagpart):self.r = realpartself.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5
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()
20.2.4 类变量、实例变量
class test(object):a = 'cls' # 类变量def __init__(self, num):some.b = num # 实例变量print(test.a)
obj = test(10)
print(obj.b)
print(obj.a)
20.2.5 类方法、实例方法、静态方法
一、创建
类方法第一个参数为 cls,表示这个类本身,包含当前类的相关信息。
实例方法第一个参数为 self,表示实例本身,包含实例对象的信息。
静态方法可以不用传入参数,相当于把一个外部函数放在类中。
class test(object):a = "类变量"def __init__(self):self.b = "实例变量"@classmethoddef cls_func(cls):print("这是一个类方法")def obj_func(self):print("这是一个实例方法")@staticmethoddef func():print("这是一个静态方法")
二、调用
类内调用:
class Test(object):a = "类变量"def __init__(self):self.b = "实例变量"@classmethoddef cls_func(cls):print("这是一个类方法")def obj_func(self):print("这是一个实例方法")@staticmethoddef func():print("这是一个静态方法")# 类内调用@classmethoddef cls_func1(cls):cls.cls_func()cls.func()obj = cls()obj.obj_func()def obj_func1(self):self.cls_func()self.obj_func()self.func()@staticmethoddef func1():Test.cls_func()obj = Test()obj.obj_func()Test.func()
对象调用:
if __name__ == "__main__":test.cls_func()test.func()obj = test()obj.cls_func()obj.obj_func()obj.func()
三、使用场景
类方法一般是整个类都会使用的操作,不受实例化影响。
实例方法需要实例化,用于涉及特定实例化对象的操作。
静态方法用于不涉及类信息的操作。
四、区别
子类的实例继承了父类的static_method静态方法,调用该方法,还是调用的父类的方法和类属性。
子类的实例继承了父类的class_method类方法,调用该方法,调用的是子类的方法和子类的类属性。
20.3 访问可见性
在 Python 中,属性和方法的访问权限只有2种:公开和私有。以2个下划线开头进行声明,可以将属性和方法定义为私有。声明为私有后,只能在类的内部调用 ,不能在类的外部调用。
class Test:def __init__(self, foo):self.__foo = foodef __bar(self):print(self.__foo)print('__bar')def main():test = Test('hello')# AttributeError: 'Test' object has no attribute '__bar'test.__bar()# AttributeError: 'Test' object has no attribute '__foo'print(test.__foo)if __name__ == "__main__":main()
但是,Python并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个名字来妨碍对它们的访问,事实上如果你知道更换名字的规则仍然可以访问到它们,下面的代码就可以验证这一点。之所以这样设定,可以用这样一句名言加以解释,就是"We are all consenting adults here"。因为绝大多数程序员都认为开放比封闭要好,而且程序员要自己为自己的行为负责。
class Test:def __init__(self, foo):self.__foo = foodef __bar(self):print(self.__foo)print('__bar')def main():test = Test('hello')test._Test__bar()print(test._Test__foo)if __name__ == "__main__":main()
在实际开发中,并不建议将属性设置为私有的,因为这会导致子类无法访问。所以大多数Python程序员会遵循一种命名惯例就是让属性名以单下划线开头来表示属性是受保护的,本类之外的代码在访问这样的属性时应该要保持慎重。这种做法并不是语法上的规则,单下划线开头的属性和方法外界仍然是可以访问的,所以更多的时候它是一种暗示或隐喻。
20.3.1 @property装饰器
在不将属性直接暴露给外界的情况下,如果想访问属性可以通过属性的 getter(访问器)和 setter(修改器)方法进行对应的操作。如果要做到这点,就可以考虑使用 @property 包装器来包装 getter 和 setter 方法,使得对属性的访问既安全又方便。
class Person(object):def __init__(self, name, age):self._name = nameself._age = age# 访问器 - getter方法@propertydef name(self):return self._name# 访问器 - getter方法@propertydef age(self):return self._age# 修改器 - setter方法@age.setterdef age(self, age):self._age = agedef play(self):if self._age <= 16:print('%s正在玩飞行棋.' % self._name)else:print('%s正在玩斗地主.' % self._name)def main():person = Person('王大锤', 12)person.play()person.age = 22person.play()# person.name = '白元芳' # AttributeError: can't set attributeif __name__ == '__main__':main()
20.4 动态性
Python 是一门动态语言。通常,动态语言允许我们在程序运行时给对象绑定新的属性或方法,当然也可以对已经绑定的属性和方法进行解绑定。
import typesclass Pearson(object):def __init__(self, name, age):self._name = nameself._age = agedef is_adult(self):if self._age >= 18:return Trueelse:return Falsedef main():boy = Pearson("小明", 16)boy._gender = "男"boy.is_adult = types.MethodType(is_adult, boy)print(boy._gender)print(boy.is_adult())del boy.is_adultdelattr(boy, "_gender")if __name__ == "__main__":main()
注意:
del和delattr功能有限,都是针对实例对象而言的,对于类方法,类属性则删除不了。
更多内容可以参考:CSDN - 涤生大数据:Python语言的动态性:运行时动态绑定,删除属性和方法
20.4.1 __slots__魔法
如果需要限定自定义类型的对象只能绑定某些属性,可以通过在类中定义 __slots__ 变量来进行限定。需要注意的是 __slots__ 的限定只对当前类的对象生效,对子类并不起任何作用。
class Person(object):# 限定Person对象只能绑定_name, _age和_gender属性__slots__ = ('_name', '_age', '_gender')def __init__(self, name, age):self._name = nameself._age = age
20.5 继承
子类(派生类 DerivedClassName)会继承父类(基类 BaseClassName)的属性和方法:
class DerivedClassName(BaseClassName):<statement-1>...<statement-N>
基类定义在另一个模块中时,可以使用:
class DerivedClassName(modname.BaseClassName):
子类除了继承父类提供的属性和方法,还可以定义自己特有的属性和方法,所以子类比父类拥有的更多的能力。
20.5.1 多继承
多继承的类定义形如下:
class DerivedClassName(Base1, Base2, Base3):<statement-1>...<statement-N>
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类类中未找到时,python会从左到右查找父类中是否包含方法。
class A(object):@classmethoddef who(cls):print("A")class B(object):@classmethoddef who(cls):print("B")class C(A, B):passdef main():C.who()print(C.__mro__) # 查看类的方法解析顺序if __name__ == "__main__":main()
更多内容可以参考:朋疏哲N:Python多继承实现以及问题应对策略
20.5.2 super() 函数
super() 函数是用于调用父类(超类)的一个方法。super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。MRO 就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
语法:
super(type[, object-or-type])
参数:
- type – 类。
- object-or-type – 类,一般是 self。
实例:
class FooParent(object):def __init__(self):self.parent = 'I\'m the parent.'print ('Parent')def bar(self, message):print ("%s from Parent" % message)class FooChild(FooParent):def __init__(self):super().__init__() print ('Child')def bar(self, message):super().bar(message)print ('Child bar fuction')print (self.parent)if __name__ == '__main__':fooChild = FooChild()fooChild.bar('HelloWorld')
菱形继承:
---> B ---
A --| |--> D---> C ---
Python3 中继承遵循广度优先原则:
class A:def __init__(self):print("Enter A")print(self)print("Leave A")class B(A):def __init__(self):print("Enter B")print(self)super(B, self).__init__()print("Leave B")class C(A):def __init__(self):print("Enter C")print(self)super(C, self).__init__()print("Leave C")class D(B, C):def __init__(self):print("Enter D")print(self)super(D, self).__init__()print("Leave D")d = D()
运行结果:
Enter D
<__main__.D object at 0x7fdb02618490>
Enter B
<__main__.D object at 0x7fdb02618490>
Enter C
<__main__.D object at 0x7fdb02618490>
Enter A
<__main__.D object at 0x7fdb02618490>
Leave A
Leave C
Leave B
Leave D
20.6 多态
子类在继承了父类的方法后,可以对父类已有的方法给出新的实现版本,这个动作称之为方法重写(override)。通过方法重写我们可以让父类的同一个行为在子类中拥有不同的实现版本,当我们调用这个经过子类重写的方法时,不同的子类对象会表现出不同的行为,这个就是多态(poly-morphism)。
class Parent: # 定义父类def myMethod(self):print ('调用父类方法')class Child(Parent): # 定义子类def myMethod(self):print ('调用子类方法')c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child, c).myMethod() # 用子类对象调用父类已被覆盖的方法
20.7 类的专有方法
__init__:构造函数,在生成对象时调用;__del__:析构函数,释放对象时使用;__repr__:打印,转换;__setitem__:按照索引赋值;__getitem__:按照索引获取值;__len__:获得长度;__cmp__:比较运算;__call__:函数调用;__add__:加运算;__sub__:减运算;__mul__:乘运算;__truediv__:除运算;__mod__:求余运算;__pow__:乘方。
参考阅读:
知乎 - 黄同学:Python基础(十九):面向对象“类”之魔法方法
DataScience:Day12.魔法方法&方法重写
20.7.1 运算符重载
#!/usr/bin/python3class Vector:def __init__(self, a, b):self.a = aself.b = bdef __str__(self):return 'Vector (%d, %d)' % (self.a, self.b)def __repr__(self):return 'Vector (%d, %d)' % (self.a, self.b)def __add__(self,other):if other.__class__ is Vector:return Vector(self.a + other.a, self.b + other.b)elif other.__class__ is int:return Vector(self.a+other,self.b)def __radd__(self,other):"""反向算术运算符的重载__add__运算符重载可以保证V+int的情况下不会报错,但是反过来int+V就会报错,通过反向运算符重载可以解决此问题"""if other.__class__ is int or other.__class__ is float:return Vector(self.a+other,self.b)else:raise ValueError("值错误")def __iadd__(self,other):"""复合赋值算数运算符的重载主要用于列表,例如L1+=L2,默认情况下调用__add__,会生成一个新的列表,当数据过大的时候会影响效率,而此函数可以重载+=,使L2直接增加到L1后面"""if other.__class__ is Vector:return Vector(self.a + other.a, self.b + other.b)elif other.__class__ is int:return Vector(self.a+other,self.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
print (v1 + 5)
print (6 + v2)
相关文章:
菜鸟教程《Python 3 教程》笔记(20):面向对象
菜鸟教程《Python 3 教程》笔记(20) 20 面向对象20.1 面向对象技术简介20.2 创建类20.2.1 类定义20.2.2 实例化20.2.3 初始化20.2.4 类变量、实例变量20.2.5 类方法、实例方法、静态方法 20.3 访问可见性20.3.1 property装饰器 20.4 动态性20.4.1 __slot…...
vue2编辑markdown
效果 npm i mavon-editor --save 只能全局注册 使用...
PCB走线规则
1、线间距。 这里应该遵循3W规则,所谓3W就是为了减少线间串扰,应保证线间距足够大,当线中心不少于3倍线宽,则可 保持70%的电场不互相干扰。如要达到98%的电场不互相干扰,可使用10W的间距。——这是查阅华为PCB布线规则…...
webpack静态资源上传到CDNS (阿里云 OSS,亚马逊 AWS S3,七牛云 Qiniu Cloud Kodo)webpack-plugin-cdns
webpack-plugin-cdns 是一个 Webpack 插件,用于实现将前端项目中的资源(如 JavaScript、CSS、图片等)上传到 CDN(OSS、S3、Kodo) 服务器。从而完成资源的 CDN 加速。 在开发前端项目时,我们通常会将静态资源放在本地服务器上&…...
python 异常
1.捕获异常 2.密码爆破 3....
stm32--独立看门狗
最近学习到独立看门狗,总结下笔记 1.看门狗的作用:防止程序异常跑飞,跑飞时,进行系统复位,从而不会导致代码瘫痪,奔溃卡死在某段程序。 2.看门狗其实是12bit递减计数器,,减到0会产…...
vue3中css使用script中定义的变量
代码 <template><div class"box">haha</div> </template><script setup lang"ts"> const boxWidth 500px </script><style lang"scss"> .box {width: v-bind(boxWidth);height: 200px;background-c…...
Ubuntu 22.04 安装配置 flatpak
Ubuntu 22.04 安装配置 Flatpak 安装 Flatpak sudo apt install flatpakFlatpak 仓库配置 官方仓库 https://flathub.org/repo/flathub上交大镜像 https://mirror.sjtu.edu.cn/flathub flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatp…...
oracle创建数据库以及用户,并导入dmp格式数据
oracle创建数据库以及用户,并导入dmp格式数据 安装可参考之前的文章https://blog.csdn.net/qq_43421954/article/details/132717546?spm1001.2014.3001.5501 首先创建表空间(也就是其他数据库所谓的数据库) 使用的是navicat,连接配置可以参…...
[deeplearning]pytorch实现softmax多分类问题预测训练
写在前面:俺这两天也是刚刚加入实验室,因为之前的学习过程中用到更多的框架是tensorflow,所以突然上手pytorch多少有些力不从心了。 这两个框架的主要区别在与tensorflow更偏向于工业使用,所以里面的很多函数和类都已经封装得很完…...
【C++初阶】动态内存管理
👻内容专栏: C/C编程 🐨本文概括: C/C内存分布、C语言动态内存管理、C动态内存管理、operator new与operator delete函数、new和delete的实现原理、定位new表达式、常见面试问题等。 🐼本文作者: 阿四啊 …...
Mac电脑安装Zulu Open JDK 8 使用 spring-kafka 消费不到Kafka Partition中的消息
一、现象描述 使用Mac电脑本地启动spring-kakfa消费不到Kafka的消息,监控消费组的消息偏移量发现存在Lag的消息,但是本地客户端就是拉取不到,通过部署到公司k8s容器上消息却能正常消费! 本地启动的服务消费组监控 公司k8s容器服…...
CodeArts Check代码检查服务用户声音反馈集锦(2)
作者:gentle_zhou 原文链接:CodeArts Check代码检查服务用户声音反馈集锦(2)-云社区-华为云 CodeArts Check(原CodeCheck),是自主研发的代码检查服务。建立在华为30年自动化源代码静态检查技术…...
红帽RHCE9.0学什么内容,新版有什么变化
【微|信|公|众|号:厦门微思网络】 一、红帽公司介绍 红帽是首个(也是全球最大、全球领先)的企业开源软件解决方案提供商,在过去 20 几年里,红帽已经成为开源社区里令人尊敬的成员,赞助了数百个开源项目&…...
线性代数的本质(一)——向量空间
文章目录 向量空间向量及其性质基与维数向量的坐标运算 《线性代数的本质》 - 3blue1brown 高中数学A版选修4-2 矩阵与变换 《线性代数及其应用》(第五版) 《高等代数简明教程》- 蓝以中 向量空间 In the beginning Grant created the space. And Grant said, Let there be vec…...
PP-Tracking之C++部署
文章目录 概要环境fastdeploy源码编译PP-Tracking源码编译使用参考概要 PP-Tracking是基于飞桨深度学习框架的业界首个开源实时跟踪系统。针对实际业务的难点痛点,PP-Tracking内置行人车辆跟踪、跨镜头跟踪、多类别跟踪、小目标跟踪及流量计数等能力与产业应用,同时提供可视…...
智慧公厕建设,要以技术为支撑、体验为目的、业务为驱动
#智慧公厕[话题]# #智慧公厕系统[话题]# #智慧公厕厂家[话题]# #智慧公厕驿站[话题]# 在数字化城市与智慧城市的大力推进下,作为社会重要的生活设施,智慧化的公共厕所的建设变得越来越重要。作为城市的基础部件之一,公厕的智慧化建设需要进行…...
通过Sealos 180秒部署一套K8S集群
通过Sealos 180秒部署一套K8S集群 一、主机准备 1.1 主机操作系统说明 序号操作系统及版本备注1CentOS7u9 1.2 主机硬件配置说明 k8s集群CPU及内存最低分别为2颗CPU、2G内存,硬盘建议为100G 需求CPU内存硬盘角色主机名值8C8G1024GBmasterk8s-master01值8C8G1024…...
如何获取美团的热门商品和服务
导语 美团是中国最大的生活服务平台之一,提供了各种各样的商品和服务,如美食、酒店、旅游、电影、娱乐等。如果你想了解美团的热门商品和服务,你可以使用爬虫技术来获取它们。本文将介绍如何使用Python和BeautifulSoup库来编写一个简单的爬虫…...
开启编程之门
自我介绍 目前已经大二了,计算机专业在读,是一个热爱编程,做事踏实专注的人。转眼间一年已经过去了,也接触编程一年了,但开始并没有对所学所想进行很好的总结和输出,这一年也有了新的很多感悟与心得&#x…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...
链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...
门静脉高压——表现
一、门静脉高压表现 00:01 1. 门静脉构成 00:13 组成结构:由肠系膜上静脉和脾静脉汇合构成,是肝脏血液供应的主要来源。淤血后果:门静脉淤血会同时导致脾静脉和肠系膜上静脉淤血,引发后续系列症状。 2. 脾大和脾功能亢进 00:46 …...
轻量级Docker管理工具Docker Switchboard
简介 什么是 Docker Switchboard ? Docker Switchboard 是一个轻量级的 Web 应用程序,用于管理 Docker 容器。它提供了一个干净、用户友好的界面来启动、停止和监控主机上运行的容器,使其成为本地开发、家庭实验室或小型服务器设置的理想选择…...
