Python面向对象(九)

news2025/1/14 18:19:51

python学习之旅(九)
👍查看更多可以关注查看首页或点击下方专栏目录

一.什么是面向对象

万物皆对象

  • 现实世界的事物都有属性和行为,可在程序中抽离为类来描述现实世界的事物属性和行为。
    请添加图片描述

  • 使用充当程序内现实事物的“设计图纸”,基于图纸(类)生产实体(对象),由对象做具体的工作,称之为:面向对象编程

  • 在现实世界中,生产事物:先设计图纸,完成功能属性分析,再批量制造
    请添加图片描述

  • 在程序中,通过类作为事物的设计图纸,记录事物的属性和行为
    请添加图片描述

  • 基于类(设计图纸)构建(生产)闹钟对象
    请添加图片描述


二.类与对象

使用类封装属性,基于类创建出一个个的对象来使用

(1) 基本语法

# 创建类
class 类名称:
    类的属性(成员变量)
    
    类的行为(成员方法)
    
# 基于类创建对象
对象名 = 类名称()

# 调用
对象名.成员变量
对象名.成员方法()
  • class:关键字,表示要定义类了
  • 类的属性:定义在类中的变量(成员变量) -> 事物的属性
  • 类的行为:定义在类中的函数(成员方法) -> 事物的行为

(2) 使用示例

请添加图片描述

  • 设计表格即设计类(class)
class Student:
    name = None  # 姓名
    sex = None  # 性别
    country = None  # 国籍
    native_place = None  # 籍贯
    age = None  # 年龄
  • 打印表格即创建对象
stu_1 = Student()  # 一张
stu_2 = Student()  # 两张
stu_3 = Student()  # 三张
  • 填写表格即使用对象(为属性赋值):
stu_1 = "李白"
stu_2 = "观止"
stu_3 = "罗辑"
  • 概览:
    请添加图片描述

(3) 成员变量和成员方法

(3.1) 成员变量

  • 定义在类内部的变量称之为成员变量,用法与正常变量一致。

(3.2) 成员方法

定义在类内部的函数称之为方法,与函数存在细微区别。

# 函数
# 形参可以为0-N个
def 函数名(形参1,形参2,..,形参N):
    函数体

# 方法
# 形参可以为0-N个
# self关键字必须填写
def 方法名(self,形参1,形参2,..,形参N):
    方法体
  • self关键字在成员方法定义的时候必须填写,表示类对象自身
  • 在方法内部,想要访问类的成员变量,必须使用self
class Student:
    name = None  
    
    # 调用say_hi1时正常打印
    def say_hi1(self):
        print(f"大家好,我叫{self.name}") 
    
    # 调用say_hi2时报错,'name' is not defined
    def say_hi2(self):
        print(f"大家好,我叫{name}") 
  • 当我们使用对象调用方法的时,self会自动被python传入,尽管在参数列表中,但是传参的时候可以忽略它。
# 定义
class Student:
    name = None

    def say_hi(self, msg):
        print(f"大家好,我是{msg}")

# 创建
stu_1 = Student()
# 通过对象名调用
stu_1.say_hi("练习两年半的偶像实习生")
# 打印 大家好,我是练习两年半的偶像实习生

(4) 构造方法

通过传参的形式快速对属性赋值

  • 正常情况下,为对象的属性赋值需要依次进行
# 定义类
class Student:
    name = None  # 姓名
    sex = None  # 性别
    age = None  # 年龄

# 创建对象
stu_1 = Student()
# 为对象赋值
stu_1.name = "李白"
stu_1.sex = "男"
stu_1.age = 1000
  • 在类可以使用:__init__()方法,即构造方法,快速为对象赋值。
# 定义类
class Student:
    name = None  # 姓名
    sex = None  # 性别
    age = None  # 年龄

    def __init__(self, name, sex, age):
        self.name = name
        self.sex = sex
        self.age = age

# 创建对象并赋值
stu_1 = Student("李白", "男", 1000)

# 简化形式:可以省略成员属性定义,但仍可调用
class Student:

    def __init__(self, name, sex, age):
        self.name = name  # 姓名
        self.sex = sex  # 性别
        self.age = age  # 年龄

# 创建对象并赋值
stu_1 = Student("李白", "男", 1000)
  • 在创建类对象(构造类)的时候,会自动执行,将传入参数自动传递给__init__方法使用。

  • 构造方法也是成员方法,定义时也需要在参数列表中提供:self

  • 变量定义在构造方法内部,如果要成为成员变量,需要用self来表示,例如self.name

  • 使用了构造方法,创建对象时必须传参否则会报错
    请添加图片描述

(5) 魔术方法

Python类内置的类方法,各自有各自特殊的功能

  • 魔术方法非常多,我们学习几个常用的即可。
方法功能
__init__构造方法,可用于创建类对象的时候设置初始化行为
__str__字符串方法,用于实现类对象转字符串的行为
__lt__用于2个类对象进行小于(<)或大于(>)比较
__le__用于2个类对象进行小于等于(<=)或大于等于(>=)比较
__eq__用于2个类对象进行相等(==)比较

(5.1)__str__方法

  • 当直接打印类对象时,打印的是对象的内存地址,用处不大。
class Student:

    def __init__(self, name, age):
        self.name = name  # 姓名
        self.age = age  # 年龄

stu_1 = Student("李白", 1000)
print(stu_1)
# 打印 <__main__.Student object at 0x0000024D8C6195D0>
  • 我们可以通过__str__方法,自定义控制打印类对象时输出的内容。
class Student:

    def __init__(self, name, age):
        self.name = name  # 姓名
        self.age = age  # 年龄
        
	# 自定义打印输出内容
    def __str__(self):
        return f"Student对象,name={self.name},age={self.age}"

stu_1 = Student("李白", 1000)
print(stu_1)
# 打印 Student对象,name=李白,age=1000

(5.2)__lt__方法

  • 直接对2个对象进行比较是不可以的,会报错。
class Student:

    def __init__(self, name, age):
        self.name = name  # 姓名
        self.age = age  # 年龄


stu_1 = Student("李白", 1000)
stu_2 = Student("罗辑", 300)
print(stu_1 > stu_2) # 报错

在这里插入图片描述

  • 在类中实现__lt__方法即可完成:小于符号 和 大于符号 2种比较
class Student:

    def __init__(self, name, age):
        self.name = name  # 姓名
        self.age = age  # 年龄

    def __lt__(self, other):
        return self.age < other.age


stu_1 = Student("李白", 1000)
stu_2 = Student("罗辑", 300)
print(stu_1 > stu_2) # 打印 True

(5.3) __le__方法

  • 在类中实现__le__方法即可完成:小于等于符号 和 大于等于符号 2种比较,否则会报错
class Student:

    def __init__(self, name, age):
        self.name = name  # 姓名
        self.age = age  # 年龄

    def __le__(self, other):
        return self.age <= other.age


stu_1 = Student("李白", 1000)
stu_2 = Student("罗辑", 1000)
print(stu_1 <= stu_2)  # True
print(stu_1 >= stu_2)  # True

(5.4) __eq__方法

  • 不实现__eq__方法,对象之间可以比较,但是是比较内存地址,但是不同对象==比较一定是False结果。
class Student:

    def __init__(self, name, age):
        self.name = name  # 姓名
        self.age = age  # 年龄


stu_1 = Student("李白", 1000)
stu_2 = Student("李白", 666)
print(stu_1 == stu_2)  # False
  • 实现了__eq__方法,就可以按照自己的想法来决定2个对象是否相等了。
class Student:

    def __init__(self, name, age):
        self.name = name  # 姓名
        self.age = age  # 年龄
	# 自定义比较规则
    def __eq__(self, other):
        return self.name == self.name


stu_1 = Student("李白", 1000)
stu_2 = Student("李白", 666)
print(stu_1 == stu_2)  # True

三.三大特性

面向对象包含3大主要特性:封装,继承,多态

(1) 封装

将现实世界事物的属性和行为在类中描述为成员变量和成员方法,完成程序对现实世界事物的描述

在这里插入图片描述

  • 现实世界中的事物,有属性和行为。但是不代表这些属性和行为都是开放给用户使用的
    在这里插入图片描述

(1.1) 私有成员

在类中提供仅供内部使用的属性和方法,无法被对象调用

在这里插入图片描述

  • 基本语法:
    • 私有成员变量:变量名以__开头(2个下划线)
    • 私有成员方法:方法名以__开头(2个下划线)
class Student:
    name = None  # 普通成员变量
    __age = None  # 私有成员变量
    
    # 普通成员方法
    def say_hi(self):
        print("你好")

    # 私有成员方法
    def __DNA(self):
        print("DNA数量")
  • 仅在成员内部可以使用
class Student:
    name = None  # 普通成员变量
    __age = 16  # 私有成员变量

    # 普通成员方法
    def show(self): 
        self.__check()  # 在类中使用私有成员变量
        if self.__age > 18: # 在类中使用私有成员变量
            print("成年人")
        else:
            print("未成年")

    # 私有成员方法
    def __check(self):
        print("自检")

(2) 继承

一个类继承另外一个类的所有成员变量和成员方法(不含私有)

在这里插入图片描述

(2.1) 单继承

  • 基本语法:
class 类名(父类名):
    类内容体
  • 基本使用:
# 待继承的类
class Phone:
    producer = "apple"  # 厂商

    def call_by_4g(self):
        print("4g通话")

# 继承Phone
class Phone2022(Phone):
    face_id = True  # 面部识别

    def call_by_5g(self):
        print("2022最新5G通话")
# 创建对象
phone = Phone2022()
# 使用
print(phone.producer) # 可调用 继承自Phone的成员变量
print(phone.face_id) # 可调用 自身的成员变量
phone.call_by_4g() # 可调用 继承自Phone的成员方法
phone.call_by_5g() # 可调用 自身的成员方法

(2.2) 多继承

  • 一个类也可以继承多个类
  • 多个父类中,如果有同名的成员,默认以继承顺序(从左到右)为优先级。即:后继承的被先继承的覆盖
  • 基本语法:
class 类名(父类1,父类2,...,父类N):
    类内容体
  • 使用示例:
class Phone:
    producer = "apple"  # 厂商

class Camera:
    producer = "suoni"  # 厂商

class Phone2022(Phone, Camera):
    face_id = True  # 面部识别

    def call_by_5g(self):
        print("2022最新5G通话")

phone = Phone2022()

print(phone.producer)  # 打印结果为apple而非suoni

(2.3) 复写

  • 子类继承父类的成员属性和成员方法后,如果对其“不满意”,那么可以进行复写。即:在子类中重新定义同名的属性或方法。

  • 一旦复写父类成员,那么类对象调用成员的时候,就会调用复写后的新成员

class Phone2021:
    producer = "apple"  # 厂商

    def call_by_5g(self):
        print("2021版5G通话")


class Phone2022(Phone2021):
    face_id = True  # 面部识别

    def call_by_5g(self):
        print("2022升级版5G通话")


phone = Phone2022()

phone.call_by_5g()  # 打印 2022升级版5G通话
  • 如果需要使用被复写的父类的成员,只能在子类内通过如下方式调用父类的同名成员:

    • 方式一:使用父类名调用
    使用成员变量:父类名.成员变量
    使用成员方法:父类名.成员方法(self)
    
    • 方式二:使用super()调用
    使用成员变量:super().成员变量
    使用成员方法:super().成员方法()
    
    • 使用示例:
    class Phone2021:
        producer = "apple"  # 厂商
    
        def call_by_5g(self):
            print("2021版5G通话")
    
    
    class Phone2022(Phone2021):
        face_id = True  # 面部识别
    
        def call_by_5g(self):
            # 方式一调用
            print(Phone2021.producer)  # 打印 apple
            Phone2021.call_by_5g(self)# 打印 2021版5G通话
            # 方式二调用
            print(super().producer)# 打印 apple
            super().call_by_5g()# 打印 2021版5G通话
    

(3) 多态

多种状态,即完成某个行为时,使用不同的对象会得到不同的状态

在这里插入图片描述

  • 多态常作用在继承关系上,函数(方法)形参声明接收父类对象,实际传入父类的子类对象进行工作,即

    • 以父类做定义声明

    • 以子类做实际工作

    • 用以获得同一行为, 不同状态
      在这里插入图片描述

(3.1) 抽象类(接口)

抽象类就好比定义一个标准,包含了一些抽象的方法,要求子类必须实现

在这里插入图片描述

  • 抽象类:包含抽象方法的类

  • 抽象方法:没有具体实现的方法(只含pass)称之为抽象方法

  • pass是占位语句,用来保证函数(方法)或类定义的完整性,表示无内容,空的意思
    在这里插入图片描述

  • 多用于做顶层设计(设计标准),以便子类做具体实现。是对子类的一种软性约束,要求子类必须复写(实现)父类的一些方法

    并配合多态使用,获得不同的工作状态。

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

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

相关文章

10. 正则表达式匹配

题目链接&#xff1a;https://leetcode.cn/problems/regular-expression-matching/从暴力递归到动态规划&#xff0c;对于状态转移方程不容易推导出来的可以先从递归进行尝试各种策略&#xff0c;最后再从暴力递归转为动态规划&#xff0c;这种尝试方式容易求解dp初始值以及dp更…

数据结构-考研难点代码突破 (图关键路径完全解析(流程+代码) - C++代码)

考研在关键路径上的考察以流程为主 文章目录1. AOE网2. 关键路径问题解决流程C代码1. AOE网 首先区分AOV网&#xff1a; AOV网∶若用DAG 图&#xff08;有向无环图&#xff09;表示一个工程&#xff0c;其顶点表示活动&#xff0c;用有向边<Vi&#xff0c;Vj>表示活动 V…

【ESP32+freeRTOS学习笔记-(五)队列Queue】

目录1、什么是队列Queue2、队列的多任务特性2.1 多任务的访问&#xff1a;2.2 队列读取阻塞&#xff1a;2.3 写队列阻塞&#xff1a;2.4 阻塞于多个队列&#xff1a;3、队列的使用3.1 创建队列--The xQueueCreate() API3.2 写入队列3.3 从队列中接收数据3.4 删除队列4、队列集4…

ReactDOM.render在react源码中执行之后发生了什么?

ReactDOM.render 通常是如下图使用&#xff0c;在提供的 container 里渲染一个 React 元素&#xff0c;并返回对该组件的引用&#xff08;或者针对无状态组件返回 null&#xff09;。本文主要是将ReactDOM.render的执行流程在后续文章中会对创建更新的细节进行分析&#xff0c…

MATLAB-plot3/ezplot3三维绘图

&#xff08;1&#xff09; plot3是三维绘图的基本函数&#xff0c;调用格式如下。1、plot3( X,Y,Z):绘制简单的三维曲线&#xff0c;当X、Y、Z是长度相同的向量时&#xff0c;plot3命令将绘制以向量X、Y、Z为(x, y,z)坐标值的三维曲线;当X、Y、Z是mn矩阵时,plot3命令将绘制m条…

Android 虚拟分区详解(四) 编译开关

Android Virtual A/B 系统简称 VAB,我将其称为虚拟分区。 本系列文章基于 Android R(11) 进行分析,如果没有特别说明,均基于代码版本 android-11.0.0_r46 请已经购买《Android 虚拟分区》专栏的朋友加我 wx 进 "虚拟分区专栏 VIP 答疑"群,作为本专栏文章的附加服…

(6)元对象系统与信号与槽机制

1. 元对象系统 元对象系统是一个基于标准C的扩展&#xff0c;为Qt提供了信号与槽机制、实时类型信息、动态属性系统。 什么是元对象 在计算机科学中&#xff0c;元对象是这样一个东西&#xff1a;它可以操纵、创建、描述、或执行其他对象。元对象描述的对象称为基对象。元对象可…

记一次搭建备库,使用连接串主库无法连接到备库

主库使用连接串连接备库失败 SQL> conn sys/oracleorcldg as sysdba ERROR: ORA-12528: TNS:listener: all appropriate instances are blocking new connections 备库已经建立了静态监听 # listener.ora Network Configuration File: /u01/app/oracle/product/11.2.0/db_1/…

安全寒假第一堂课

一、状态码 200 – 服务器成功返回网页 404 – 请求的网页不存在 503 – 服务器超时 1xx&#xff08;临时响应&#xff09; 表示临时响应并需要请求者继续执行操作的状态码。 100&#xff08;继续&#xff09; 请求者应当继续提出请求。服务器返回此代码表示已收到请求的第一…

OpenCV实战(5)——图像运算详解

OpenCV实战&#xff08;5&#xff09;——图像运算详解0. 前言1. 图像基本运算2. 重载图像运算符2.1 加法运算符重载2.2 分割图像通道2.3 完整代码3. 图像重映射3.1 OpenCV 重映射函数3.2 完整代码小结系列链接0. 前言 图像可以以不同的方式进行组合&#xff0c;因为它们是正则…

XGBoost论文阅读

XGBoost: A Scalable Tree Boosting System 目录 XGBoost: A Scalable Tree Boosting System 1.摘要 2.方法 2.1 正则化学习目标 2.2 梯度提升树 2.3 收缩率和列采样 2.4分裂点查找算法 1.摘要 提出了一种新的稀疏性感知算法&#xff0c;用于稀疏数据和加权全图草图&a…

Python教程:什么是三级模式和二级映像?

美国国家标准学会(American National Standards Institute,ANSI)所属的标准计划与需求委员会&#xff08;Standards Planning and Requirements Committee,SPARC)在1971年公布的研究报告中提出了ANSI-SPARC体系结构&#xff0c;即三级模式结构&#xff08;或称为三层体系结构&a…

ArcGIS基础实验操作100例--实验53导出线、面要素的坐标值

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验53 导出线、面要素的坐标值 目录 一、实验背景 二、实验数据 三、实验步骤 &#xf…

笔记杂项(一)

都是踩过的坑&#xff0c;趟过的水。 ubuntu虚拟机终端字体太小的设置方法&#xff1a;ubuntu18.04调整终端字体大小 这个方法试试看&#xff1a;https://zhuanlan.zhihu.com/p/139305626 容器里面编译内核代码&#xff0c;进程被杀掉的原因是触发了内核OOM killer&#xff0c…

干货| app自动化测试之Andriod微信小程序的自动化测试

随着微信小程序的功能和生态日益完善&#xff0c;很多公司的小程序项目页面结构越来越多&#xff0c;业务逻辑也越来越复杂。如何做好小程序的自动化测试就成为测试同学普遍面临的一大痛点难题。微信小程序小程序内嵌于微信内部&#xff0c;页面包含 Native 原生元素和 Web 元素…

华为防火墙与二层交换机对接配置VLAN上网设置

拓扑图 一、防火墙设置 1、G1/0/0接口设置IP&#xff0c;G1/0/1接口切换二层口设置VLAN&#xff0c;G1/0/0 桥接了本地无线网卡来模拟公网地址 <USG6000V1>sys [USG6000V1]sys FW1 [FW1]un in en# 设置公网IP [FW1]int g1/0/0 [FW1-GigabitEthernet1/0/0]ip addr 192.1…

package.json配置解读之入门

文章目录前言一、描述配置nameversionrepositorydescriptionkeywordslicenseauthor二、文件配置filestypemainbrowsermoduleexportsworkspaces三、脚本配置scriptsconfig四、结语前言 package.json是每个前端项目都会有的json文件&#xff0c;位于项目的根目录中。很多脚手架在…

RHCE(chrony服务器)

chrony服务器 chrony服务器是一个开源自由的网络时间协议NTP的客户端和服务器的软件&#xff0c;他能让计算机保持系统时钟和时钟服务器保持同步&#xff0c;让计算机保持精确的时间&#xff0c;chrony也可以作为服务端软件为其他计算机提供时间同步服务 chrony由两部分组成&…

openAI--十拳剑助你做AI时代的弄潮儿

AI它厉害&#xff08;diao&#xff09;吗&#xff1f; 最近大家玩chatgpt还好吗&#xff1f; 有被它的恋爱情商暴击到吗&#xff1f; 有没有觉得那在leetcode上所向无敌的技巧都是浮云吗&#xff1f; 今天&#xff0c;我为大家带来十个很好的AI平台。这一篇先介绍一下&…

【远程桌面】nomachine下载安装使用教程、zerotier下载安装使用教程超详细

文章目录一、软件介绍二、NoMachine远程桌面1.Windows下载安装使用2.Linux下载安装使用3.Android下载安装使用4.ARM下载安装使用&#xff08;未实践&#xff09;三、ZeroTier内网穿透0.官网注册账户1.Windows下载安装使用2.Linux下载安装使用3.Android下载安装使用4.ARM下载安装…