跟着我学Python进阶篇:02.面向对象(上)

往期文章

跟着我学Python基础篇:01.初露端倪
跟着我学Python基础篇:02.数字与字符串编程
跟着我学Python基础篇:03.选择结构
跟着我学Python基础篇:04.循环
跟着我学Python基础篇:05.函数
跟着我学Python基础篇:06.列表
跟着我学Python基础篇:07.文本
跟着我学Python基础篇:08.集合和字典


跟着我学Python进阶篇:01.试用Python完成一些简单问题


目录

  • 往期文章
  • 1. 面向对象的概念
  • 2. 类和对象
  • 3. 类的定义和使用
    • 3.1 类的定义
    • 3.2 创建对象
    • 3.3 新式类和经典类
  • 4. 属性和方法
    • 4.1 类属性
    • 4.2 对象属性
    • 4.3 构造方法和析构方法
    • 4.4 对象方法
    • 4.5 类方法
    • 4.6 静态方法
    • 4.7 保护对象的私有属性
    • 4.7 更便捷地访问私有属性——使用@property

1. 面向对象的概念

面向对象把解决问题的事物提取为多个对象,而建立对象的目的不是为了完成一个个步骤,而是为了描述某个事物在解决整个问题的过程中所发生的行为。面向对象是一个更大的封装。

2. 类和对象

类是对某类事物的抽象描述,而对象是现实中该类事物的一个个个体,类用于描述多个对象的共同特征,它是对象的定义。对象是类的具体实例,对象是根据类创建的,一个类可以对应多个对象,但一个对象只能对应一个类。

3. 类的定义和使用

3.1 类的定义

class 类名(父类):属性名=属性值def()方法名:方法体

使用class关键字来定义类,class后是类的名称,如果类继承自某一个父类,则将父类写在括号中。
在类的定义体中,使用给属性赋值的方法定义属性,使用def关键字定义类的方法,类的方法定义与函数相似。

以下代码定义了一个dog类:

class Dog(Object):legs=4def description(self,dog_name):print("我的名字是s%" % dog_name)

这段代码定义了一个名为dog的类,并通过赋值方法定义了一个属性,名为legs,然后使用关键字定义了一个方法,名为description。
在类中定义的方法带一个默认的参数self,指向对象本身,这点与函数的定义格式有所不同。

3.2 创建对象

一般创建对象的格式如下:
对象名=类名()
可以看出,Python创建对象与其他开发语言不同,不需要使用常用的关键字new,直接使用类名加括号就可以创建了。
我们使用Dog类创建一个对象my_dog
my_dog=Dog()

3.3 新式类和经典类

在Python2.x及以前的版本,继承自任意自定义类型都成为新式类,能获得所有新式类的特性,相反地,不继承自任何内置类型的自定义类,都称经典类。
在Python3以后,新式类和经典类的区别已经不存在了,在以后的版本里,所有内置类型都继承自object,即所有类都是新式类,object是所有类的父类,如果在定义类型时没有指定父类,那么默认该类型继承自object类。

4. 属性和方法

属性用于描述事物的特征,比如颜色大小数量等,类的属性存储了各类数据,可以通过点语法来访问,类的方法定义了类的行为特征,包括这个类的各种操作。

4.1 类属性

属性包括类属性和对象属性,其中类属性定义在类的内部、方法的外部,它由该类的所有对象共同拥有。
类属性的值可以通过类和对象来访问,但是只能通过类修改,包括直接使用类属性修改,或者在类方法中修改。
比如上面定义的Dog类:

class Dog(object):legs=4
one_dog=Dog()
another_dog=Dog()
another_dog.legs=3
print(another_dog.legs)
print(one_dog.legs)
print(Dog.legs)

在这里插入图片描述
在这段代码中,我们首先定义了一个Dog类,它包含一个属性legs,并赋值为4,然后创建两个对象,one_dog和another_dog,代码another_legs.legs=3修改了属性的值,通过anotherdog访问时属性值已经改为3了,但是通过onedog和Dog访问属性值依旧为4,这说明什么呢?

  • 通过onedog和Dog访问属性值依旧为4,说明对象和类都可以访问类属性的值,也说明类属性并没有被anotherdog修改,即对象不能修改类属性的值。
  • another_legs.legs=3的含义是为another_dog对象添加一个新的对象属性,它覆盖了同名的类属性,所以通过another_legs.legs对象访问返回3.

如果使用类名对类属性进行修改,是什么样子呢?

class Dog(object):legs=4
one_dog=Dog()
print(one_dog.legs)
print(Dog.legs)
Dog.legs=3
print(Dog.legs)
print(one_dog.legs)

在这里插入图片描述
通过结果我们可以看出,使用类名成功修改了类属性的值。

4.2 对象属性

对象属性是描述对象特征的数据属性,对象属性的设置方法很灵活,可以在类定义的方法里添加,也可以在调用实例的代码里添加。
(1)在方法中添加对象属性
如果在类定义的对象方法里添加对象属性,这个属性之一在调用该方法后才能使用,否则会引起错误。
对象属性只能由对象调用,不能由类调用。
如果不调用方法,则在方法里定义的对象属性都无法访问,而其他对象创建的对象属性归创建它的对象所有,本地对象也无法访问。
(2)在调用时添加对象属性
在调用对象时,也可以动态地给对象添加属性。例如:

class Dog(object):legs=4
one_dog=Dog()
one_dog.color="红色"
print("狗狗的颜色是%s"%one_dog.color)

在这里插入图片描述
(3)删除对象属性
对象属性可以删除,这是Python特有的语法。例如:

class Dog(object):legs=4
one_dog=Dog()
one_dog.color="红色"
print("狗狗的颜色是%s"%one_dog.color)
del one_dog.color
print("狗狗的颜色是%s"%one_dog.color)

在这里插入图片描述

4.3 构造方法和析构方法

在Python中,构造方法和析构方法是类中的两种特殊方法,用于对象的初始化和资源的释放。构造方法在对象创建时调用,而析构方法在对象被销毁时(通常是在程序结束时或对象被垃圾回收时)调用。以下是它们的基本使用方式:

  1. 构造方法(__init__):

    • 构造方法是在对象创建时自动调用的特殊方法。
    • 它用于执行对象的初始化操作,设置对象的属性等。
    • 构造方法的名称是__init__,它接受self作为第一个参数,后面可以包含其他参数。
    • 示例:
    class MyClass:def __init__(self, name, age):self.name = nameself.age = age# 创建对象时,构造方法被调用
    obj = MyClass("John", 25)
    
  2. 析构方法(__del__):

    • 析构方法是在对象被销毁时自动调用的特殊方法。
    • 它用于执行一些清理操作,释放对象占用的资源等。
    • 析构方法的名称是__del__,它接受self作为第一个参数。
    • 注意:析构方法的调用时机不是确定的,依赖于Python的垃圾回收机制。
    • 示例:
    class MyClass:def __init__(self, name, age):self.name = nameself.age = agedef __del__(self):print(f"Object {self.name} is being destroyed")# 创建对象
    obj = MyClass("John", 25)# 手动删除对象,触发析构方法
    del obj
    

在实际应用中,通常更推荐使用上下文管理器(with语句)来确保资源的正确释放,而不是依赖析构方法。这是因为析构方法的调用时机不是完全可控的,而上下文管理器可以更明确地在需要时进行资源管理。

4.4 对象方法

对象方法是在类中定义的,以关键字self作为第一个参数的方法。对象方法的self参数代表调用这个方法的对象本身(在其他语言中可能使用this)。在方法调用时,可以不用传递这个参数,系统会自动将调用方法的对象作为self参数传入。
在对象方法里可以使用self关键字定义和访问对象属性,同名的对象属性会覆盖类属性。
下面的代码定义了一个类Employee,它有一个对象方法work_for_one_year().

class Employee(object):level=3def work_for_one_year(self):self.level=4
tom=Employee()
print(tom.level)
tom.work_for_one_year()
print(tom.level)

在这里插入图片描述
在方法中定义的对象属性覆盖了同名类属性。

对象可以直接调用对象方法,但是类不可以直接调用对象方法,但是类在调用时传入类或者该类对象也可以调用对象方法。
Python是一个非常灵活的语言。

4.5 类方法

类方法是使用修饰器@classmethod修饰的方法,他的第一个参数代表类本身,按照惯例,以cls作为第一个参数,在调用时,不需要传递这个参数,系统会自动调用它的类当作参数传入。
类方法还有一个用途就是对类属性进行修改,我们知道,在对象方法中无法给类属性赋值,这样的语句会被视为定义同名的对象属性。
下面的代码演示分别使用对象方法和类方法试图修改类属性:

class Apple(object):count=0def add_one(self):self.count=1@classmethoddef add_two(cls):cls.count=2apple=Apple()
apple.add_one()
print(Apple.count)
Apple.add_two()
print(Apple.count)

在这里插入图片描述
从结果可以看出,调用对象方法addone后,类属性的值count没有改变。因为对象代码中self.count=1实际上创建了一个同名的对象属性,并没有修改属性值,而调用addtwo类方法后,类属性的值就被修改为2.

那么谁可以调用类方法呢?Python是一个很灵活的语言,虽然叫做类方法,但是对象和类都可以调用。当对象调用类方法时,系统自动将对象所属的类作为第一个默认参数传入。我们使用一个例子来测试一下:

class ExampleClass(object):@classmethoddef class_method(cls):print("---类方法---")print(cls)example=ExampleClass()
example.class_method()
ExampleClass.class_method()

在这里插入图片描述
从这个例子可以看出,对象和类都可以调用类方法,而且从打印结果可知,传入的第一个参数都是类。

4.6 静态方法

静态方法是使用修饰器@staticmethod进行修饰的方法,它不需要传入默认参数,所以与类没有很强的联系。由于没有传入默认的参数,所以在静态方法中不能直接访问类属性和方法,需要通过类名方法名和属性名来访问。

那么对象和类可以调用动态方法吗?我们进行一个测试:

class ExampleClass(object):@staticmethoddef static_method():print("---静态方法---")example=ExampleClass()
example.static_method()
ExampleClass.static_method()

在这里插入图片描述
从测试结果可以看出,类和方法都可以调用静态方法。
至此,我们学习了对象方法,类方法和静态方法,我们通过下表对他们的具体特征进行归纳:

方法第一个参数修饰器类和对象访问
实例方法self对象可以直接访问,类需要传入参数
类方法cls@classmethod都可以直接访问
静态方法@staticmethod都可以直接访问

在Python中,有一种私有机制用于限制对类的属性和方法的直接访问。这通过在属性名或方法名前面添加一个或两个下划线来实现。这种机制被称为名称修饰(Name Mangling)。

  1. 单下划线 _

    • 以单下划线开头的属性或方法被视为“受保护”的,表示它们不应该在类外部直接访问,但并没有强制限制。
    • 这只是一种约定,用于告诉其他程序员“请不要直接访问这个属性或方法”。
    class MyClass:def __init__(self):self._protected_variable = 42obj = MyClass()
    print(obj._protected_variable)  # 可以访问,但是被视为受保护的
    
  2. 双下划线 __

    • 以双下划线开头的属性或方法会进行名称修饰,变成 _类名__属性名_类名__方法名 的形式。
    • 这种方式使得属性或方法在类的外部几乎无法直接访问,但在类内部是可以的。
    class MyClass:def __init__(self):self.__private_variable = 42def __private_method(self):print("This is a private method.")obj = MyClass()
    # 在类的外部访问双下划线开头的属性和方法会进行名称修饰
    print(obj._MyClass__private_variable)
    obj._MyClass__private_method()
    

请注意,虽然可以通过名称修饰来实现某种程度上的私有性,但在Python中并没有真正的私有性。这是因为在Python中,“我们都是成年人(We are all consenting adults here)”的理念,强制执行私有性可能会破坏灵活性和开发者的创造力。因此,开发者被信任以负责使用和维护这些规定。

4.7 保护对象的私有属性

在开发中,我们有时会不希望对象的私有属性被外界随意访问和修改的情况,我们希望外界对属性的操作在我们的控制范围之内,此时一般的处理方式是:

  • 将属性定义为私有
  • 添加一个公有方法,用于属性操作

现在我们将类Girl修改一下,使用方法来修改它的私有属性_age:

class Girl(object):def __init__(self,age):self._age=agedef get_age(self):is_stranger=Falseif is_stranger:return 0else:return self._agedef set_age(self,age):if 110>age>0:self._age=ageelse:print("年龄不正确")
lily=Girl(25)
lily.set_age(18)
print(lily.get_age())

在这里插入图片描述

4.7 更便捷地访问私有属性——使用@property

@property装饰器可以把方法变成属性调用。
是的,@property 装饰器是用于将一个方法变成只读属性的一种方式。它允许你像访问属性一样调用方法,而不需要添加额外的括号。

在一个类中,如果你有一个方法返回某个值,并且你希望在使用该方法时像访问属性一样,而不是使用括号调用方法,可以使用 @property 装饰器。

以下是一个简单的例子:

class Circle:def __init__(self, radius):self._radius = radius@propertydef radius(self):return self._radius@propertydef diameter(self):return self._radius * 2@propertydef area(self):return 3.14 * self._radius ** 2# 创建一个 Circle 实例
my_circle = Circle(radius=5)# 使用 @property 装饰器后,可以像访问属性一样访问方法
print(my_circle.radius)   # 输出: 5
print(my_circle.diameter) # 输出: 10
print(my_circle.area)     # 输出: 78.5

在这个例子中,radiusdiameterarea 方法都被用 @property 装饰器修饰,因此可以直接访问,而不需要在后面添加括号。这提高了代码的可读性,并使其更像是访问对象的属性而不是调用方法。

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

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

相关文章

Linux C/C++ 显示NIC流量统计信息

NIC流量统计信息是由操作系统维护的。当数据包通过NIC传输时,操作系统会更新相关的计数器。这些计数器记录了数据包的发送和接收数量、字节数等。通过读取这些计数器,我们可以获得关于网络流量的信息。 为什么需要这些信息? 可以使用这些信息来监控网络…

Java建筑工程建设智慧工地源码

智慧工地管理平台依托物联网、互联网,建立云端大数据管理平台,形成“端云大数据”的业务体系和新的管理模式,从施工现场源头抓起,最大程度的收集人员、安全、环境、材料等关键业务数据,打通从一线操作与远程监管的数据…

C++11_lambda表达式

文章目录 一、lambda表达式1.lambda的组成2.[capture-list] 的其他使用方法2.1混合捕捉 二、lambda表达式的使用场景1.替代仿函数 总结 一、lambda表达式 lambda表达式是C11新引入的功能,它的用法与我们之前学过的C语法有些不同。 1.lambda的组成 [capture-list] …

【C++进阶05】AVL树的介绍及模拟实现

一、AVL树的概念 二叉搜索树的缺点 二叉搜索树虽可以缩短查找效率 但如果数据有序或接近有序 二叉搜索树将退化为单支树 查找元素相当于在顺序表中搜索元素,效率低下 AVL树便是解决此问题 向二叉搜索树中插入新结点 并保证每个结点的左右子树 高度之差的绝对值不超…

Java诊断利器Arthas

https://arthas.aliyun.com/doc/https://arthas.aliyun.com/doc/ 原理 利用java.lang.instrument(容器类) 做动态 Instrumentation(执行容器) 是 JDK5 的新特性。使用 Instrumentation,开发者可以构建一个独立于应用程序的代理程序(Agent)&…

汽车IVI中控开发入门及进阶(十二):手机投屏

前言: 汽车座舱有车载中控大屏、仪表/HUD多屏的显示能力,有麦克风/喇叭等车载环境更好的音频输入输出能力,有方控按键、旋钮等方便的反向控制输入能力,还有高精度的车辆数据等。但汽车座舱中控主机硬件计算能力升级迭代周期相对较长,汽车的应用和服务不够丰富。现在很多汽…

.NetCore部署微服务(二)

目录 前言 概念 一 Consul注册服务中心 1.1 consul下载 1.2 consul运行 二 服务注册 2.1 安装Consul包 2.2 修改配置文件 2.3 注入Consul服务 2.3 修改Controller,增加HealthCheck方法 三 运行服务 3.1 docker运行服务 前言 上一篇讲到微服务要灵活伸缩…

「超级细菌」魔咒或将打破,MIT 利用深度学习发现新型抗生素

作者:加零 编辑:李宝珠、三羊 MIT 利用图神经网络 Chemprop 识别潜在抗生素,特异性杀死鲍曼不动杆菌。 自然界中充满了各种各样的微生物,例如结核杆菌(导致肺结核)、霍乱弧菌(导致霍乱&#…

数据结构实验4:链表的基本操作

目录 一、实验目的 二、实验原理 1. 节点 2. 指针 3.链表的类型 3.1 单向链表 3.2 双向链表 3.3 单向循环链表 3.4 双向循环链表 4. 单链表的插入 4.1 头插法 4.2 尾插法 4.3 在指定位置插入元素 5. 单链表的删除 5.1 删除指定数值的节点 5.2 删除指定位置的节点 …

Pytorch从零开始实战16

Pytorch从零开始实战——ResNeXt-50算法的思考 本系列来源于365天深度学习训练营 原作者K同学 对于上次ResNeXt-50算法,我们同样有基于TensorFlow的实现。具体代码如下。 引入头文件 import numpy as np from tensorflow.keras.preprocessing.image import Ima…

TensorRt(5)动态尺寸输入的分割模型测试

文章目录 1、固定输入尺寸逻辑2、动态输入尺寸2.1、模型导出2.2、推理测试2.3、显存分配问题2.4、完整代码 这里主要说明使用TensorRT进行加载编译优化后的模型engine进行推理测试,与前面进行目标识别、目标分类的模型的网络输入是固定大小不同,导致输入…

【现代密码学】笔记3.4-3.7--构造安全加密方案、CPA安全、CCA安全 《introduction to modern cryphtography》

【现代密码学】笔记3.4-3.7--构造安全加密方案、CPA安全、CCA安全 《introduction to modern cryphtography》 写在最前面私钥加密与伪随机性 第二部分流加密与CPA多重加密 CPA安全加密方案CPA安全实验、预言机访问(oracle access) 操作模式伪随机函数PR…

Java微服务系列之 ShardingSphere - ShardingSphere-JDBC

🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 系列专栏目录 [Java项…

报错解决:No module named ‘pytorch_lightning‘ 安装pytorch_lightning

报错记录 执行如下代码: import pytorch_lightning报错: No module named ‘pytorch_lightning’ 解决方式 安装pytorch_lightning包即可。 一般情况下,缺失的包通过pip安装,即: pip install pytorch_lightning然…

1 快速前端开发

1 前端开发 目的:开发一个平台(网站)- 前端开发:HTML、CSS、JavaScript- Web框架:接收请求并处理- MySQL数据库:存储数据地方快速上手:基于Flask Web框架让你快速搭建一个网站出来。1.快速开发…

HarmonyOS应用开发学习笔记 应用上下文Context 获取文件夹路径

1、 HarmoryOS Ability页面的生命周期 2、 Component自定义组件 3、HarmonyOS 应用开发学习笔记 ets组件生命周期 4、HarmonyOS 应用开发学习笔记 ets组件样式定义 Styles装饰器:定义组件重用样式 Extend装饰器:定义扩展组件样式 5、HarmonyOS 应用开发…

14-股票K线图功能-个股日K线SQL分析__ev

需求:统计个股日K线数据,也就是把某只股票每天的最高价,开盘价,收盘价,最低价形成K线图。

山西电力市场日前价格预测【2024-01-11】

日前价格预测 预测说明: 如上图所示,预测明日(2024-01-11)山西电力市场全天平均日前电价为231.43元/MWh。其中,最高日前电价为422.21元/MWh,预计出现在18:00。最低日前电价为0.00元/MWh,预计出…

现代软件测试中的自动化测试工具

自动化测试的重要性和优势 引言:随着软件开发的不断发展,自动化测试工具在现代软件测试中扮演着重要角色。提高效率:自动化测试可以加快测试流程,减少人工测试所需的时间和资源。提升准确性:自动化测试工具可以减少人…

PACS医学影像报告管理系统源码带CT三维后处理技术

PACS从各种医学影像检查设备中获取、存储、处理影像数据,传输到体检信息系统中,生成图文并茂的体检报告,满足体检中心高水准、高效率影像处理的需要。 自主知识产权:拥有完整知识产权,能够同其他模块无缝对接 国际标准…