31天Python入门——第18天:面向对象三大特性·封装继承多态

news2025/4/25 9:33:10

在这里插入图片描述

你好,我是安然无虞。

文章目录

    • 面向对象三大特性
      • 1. 封装
      • 2. 继承
      • 3. 多态
      • 4. 抽象基类
      • 5. 补充练习

在这里插入图片描述

面向对象三大特性

面向对象编程(Object-Oriented Programming, 简称OOP)有三大特性, 分别是封装继承多态.这些特性是面向对象编程的基础, 它们使得程序的设计更加灵活、易于维护和扩展.

1. 封装

封装是指将数据和操作数据的方法封装在一个单独的单元中, 对外部隐藏数据的具体实现细节, 只暴露必要的接口供外部访问.

通过封装, 可以实现数据的隐藏和保护, 防止外部直接访问对象的内部数据, 同时还可以控制对数据的修改和操作, 确保数据的有效性和安全性.

封装的优势:

  • 提高代码的安全性和可靠性, 外部无法直接修改对象的内部数据, 只能通过定义的接口进行访问和操作.使得对象的数据对外部是不可见的, 提高了数据的安全性和私密性.
  • 封装可以将一组数据和操作封装成一个对象, 使得代码更加模块化和可复用.其他部分的代码可以通过调用对象的接口来使用其功能, 无需关心内部的具体实现.
  • 封装可以降低代码之间的耦合性. 对象之间通过接口进行通信, 而不是直接访问和修改其内部状态, 这使得代码更加灵活和易于维护.
class Student:

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

    def introduce(self):
        print(f"大家好, 我的名字叫{self.name}, 今年{self.age}岁")


# 创建实例对象
stu = Student('张三', 18)
stu.name = '李四'
stu.age = 20


print(stu.name)
print(stu.age)

# 李四
# 20

# 这里的实例变量name和age都是公有属性, 类外可以直接访问和修改.

封装的实现

在 Python 中, 封装通过类来实现.将数据和操作封装在一个类中.类定义了对象的属性和方法, 属性表示对象的状态, 方法表示对象的行为.

在 Python 中, 封装并不是强制性的, 所有的属性和方法默认都是公开的, 外部可以直接访问和修改.但是, 可以通过命名约定来约束对属性和方法的访问.通常, 以下命名约定用于指定属性和方法的访问控制:

公有属性和方法: 默认情况下, 类中的属性和方法都是公有的, 它们的名字前都没有下划线, 这类型的属性和方法在类的外部, 内部, 子类中, 都是可以正常访问的.

私有属性和方法: 以双下划线(__)开头的属性和方法表示为私有的, 外部不能直接访问.如果外部需要访问或修改这些属性, 应该通过公开的接口方法来实现.

受保护的属性和方法: 以单下划线(_)开头的属性和方法表示为受保护的, 外部可以访问, 但是应该将其视为内部实现, 不建议直接访问.

class Student:

    def __init__(self, name, age):
        self.__name = name # 私有属性
        self.age = age

    def introduce(self):
        print(f"大家好, 我的名字叫{self.__name}, 今年{self.age}岁")


# 创建实例对象
stu = Student('张三', 18)
stu.__name = '李四' # 理论上来说类外不能访问和设置私有属性
stu.age = 20


print(stu.__name)
print(stu.age)

# 李四
# 20

# 为什么这里在类外也可以访问和设置私有属性呢?

# 如果我们执行实例方法.introduce():
stu.introduce()
# 大家好, 我的名字叫张三, 今年20岁

# 我们发现类内的数据并没有改变
# 所以上面在类外设置私有变量值, 对类的内部并没有影响.

我们在类外使用和设置类内的私有属性需要通过类内的公有方法:

class Student:

    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def introduce(self):
        print(f"大家好, 我的名字叫{self.__name}, 今年{self.__age}岁")

    def get_name(self):
        return self.__name

    def get_age(self):
        return self.__age

    def set_name(self, name):
        self.__name = name

    def set_age(self, age):
        self.__age = age


# 创建实例对象
stu = Student('张三', 18)

stu.set_name('李四')
stu.set_age(20)

name = stu.get_name()
age = stu.get_age()

print(name)
print(age)

私有属性的原理:

class A:
  def __init__(self):
    self.__attr = 1
    self._attr = 2
    self.attr = 3
    
    
a = A()
print(a.__attr) # 报错
print(a._attr) # 2
print(a.attr) # 3

# Python当中私有的实现, 实际上就是变量名改了一个名字, 仅此而已

在这里插入图片描述

我们能够看到保护属性和公有属性在存储的时候都是原来的名字, 但是对于私有属性__attr在存储的时候名字变了, 在私有属性名字前使用了单下划线+类名作为前缀.

所以说如果我们在类中使用修改后的私有变量名, 是可以正常访问到私有变量的, 没错是这样的:

class A:
    def __init__(self):
        self.__attr = 1
        self._attr = 2
        self.attr = 3


a = A()
print(a._A__attr) # 1
print(a._attr) # 2
print(a.attr) # 3

所以之前在类外设置私有属性的值, 其实访问的不是类内的私有属性, 而是类外自己设置的一个新的属性, 因为类内的私有属性名字已经变了.

2. 继承

继承是面向对象编程中的一种重要特性, 它允许一个类(子类)从另一个类(父类)继承属性和方法, 并且可以在此基础上进行扩展和修改.

通过继承, 子类可以复用父类的代码, 避免重复编写相同的功能, 同时可以在子类中添加新的属性和方法, 或者重写父类的方法, 从而实现代码的灵活和易于扩展.

优势

  1. 代码重用: 继承允许子类从父类继承属性和方法, 避免了重复编写相同的代码, 提高了代码的重用性.
  2. 代码组织和扩展: 继承可以使代码的组织结构更加清晰, 将通用的功能封装在父类中, 特定的功能在子类中实现, 便于代码的维护和扩展.
  3. 代码复杂性降低: 继承使得代码的层次结构更加清晰, 提高了代码的可读性和可维护性, 降低了代码的复杂性.

语法

在Python中, 继承使用class 子类名(父类名)的语法来实现, 子类拥有父类的所有属性和方法.子类可以直接使用父类的方法, 也可以在子类中添加新的方法或者重写父类的方法.(私有属性是不能继承过来的)

class Person:

    # 类属性
    id_number = 123123

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

    def greet(self):
        print(f"你好, 我叫 {self.name}")

class Student(Person):
    """单继承"""
    def __init__(self, name, stu_id):
        super().__init__(name)
        self.name = name
        self.stu_id = stu_id

    def show_stu_id(self):
        print(f"姓名: {self.name}, 学号: {self.stu_id}")


stu = Student('张三', 123)
stu.show_stu_id()
stu.greet()
print(stu.id_number)

# 姓名: 张三, 学号: 123
# 你好, 我叫 张三
# 123123

多继承

注意: Python虽然支持多继承, 但是不建议使用, 只使用单继承即可.

在Python中, 一个子类可以继承多个父类, 这种继承方式称为多继承.多继承允许子类同时拥有多个父类的属性和方法.

方法重写

子类可以重写父类的方法, 即在子类中重新实现与父类同名的方法.这样做可以根据子类的需要修改或扩展方法的行为.

调用父类的成员

super: super() 用于调用父类的成员, 它可以在子类中调用父类的成员.

class Singer:

    def sing(self):
        print("正在唱歌")

class Dancer:

    def dance(self):
        print("正在跳舞")

class SingerDancer(Singer, Dancer):
    """多继承"""
    pass

singer_dancer = SingerDancer()
singer_dancer.sing()
singer_dancer.dance()

print(SingerDancer.mro())
# [<class '__main__.SingerDancer'>, <class '__main__.Singer'>, <class '__main__.Dancer'>, <class 'object'>]

# MRO 确保了在多继承的情况下,方法的调用顺序是明确且一致的. 它避免了方法调用的歧义,并确保了 Python 的多继承机制能够正确工作.

3. 多态

多态就是多种状态, 即做某一个行为(同样的行为)的时候, 使用不同的对象会得到不同的状态.

在面向对象编程中, 多态是一种重要的概念, 它允许不同的对象对相同的方法做出不同的响应.简而言之, 多态使得可以使用统一的接口来调用不同类的对象, 而无需关心对象的具体类型, 从而实现更灵活和可扩展的代码设计.

在Python中, 多态性是由动态类型和动态绑定实现的.具体来说, Python是一种动态类型语言, 这意味着变量的类型在运行时根据赋值而确定, 而不是在编译时确定.因此, 同一个方法名可以在不同的类中实现, 并且可以根据对象的类型调用不同类的方法

class Cat:

     def say(self):
         print("喵喵")


class Dog:

    def say(self):
        print("汪汪")

animal = Cat()
# animal = Dog()
animal.say()

4. 抽象基类

抽象基类(Abstract Base Classes, 简称ABC)是Python中的一个重要概念, 它允许我们定义抽象类和抽象方法, 从而可以规范子类的行为.

抽象基类并不能被实例化, 只能用于继承.子类必须实现抽象基类中定义的所有抽象方法.

Python中的抽象基类通过abc模块提供, 使用抽象基类可以达到以下几个目的:

  1. 规范子类行为: 抽象基类允许我们定义一组接口或方法, 子类必须实现这些方法, 从而规范了子类的行为.
  2. 约束方法命名: 通过抽象基类可以强制子类必须实现指定的方法, 这样可以避免方法名拼写错误或者忘记实现方法的问题.
  3. 多态性支持: 抽象基类实现了多态性, 可以在使用抽象基类的地方接受多种不同的子类对象, 从而实现更灵活的代码设计.
  4. 文档化接口: 抽象基类可以帮助文档化接口, 让开发者了解哪些方法必须实现, 哪些是可选的.
from abc import ABCMeta, abstractmethod

class Animal(metaclass=ABCMeta): # ABCMeta 是一个元类,用于创建抽象基类
    """抽象基类"""
    """元类就是创建类的类"""
	# abstractmethod 是一个装饰器,用于定义抽象方法
	# 子类中必须实现这些抽象方法
    @abstractmethod
    def say(self):
    	# 在抽象基类中,当一个方法被定义为抽象方法时
    	# 通常会使用raise NotImplementedError来明确表示这个方法需要在子类中被具体实现
        raise NotImplementedError

class Cat(Animal):

     def say(self):
         print("喵喵")


class Dog(Animal):

    def say(self):
        print("汪汪")

animal = Cat()
animal.say()
class Phone:# 抽象基类
  
  def call(self): # 抽象方法
    raise NotImplementedError
   
 	def music(self):
    raise NotImplementedError
    
  def wechat(self):
    raise NotImplementedError
    

class Apple(Phone):
  pass

class HuaWei(Phone):
  pass

5. 补充练习

"""
设计一个图形类(Shape),包含计算面积的方法(calculate_area)。然后设计三个子类:圆类(Circle)、
矩形类(Rectangle)和三角形类(Triangle),分别实现计算面积的方法。要求实现以下功能:

分别创建圆、矩形和三角形的对象,并设置它们的相关属性(例如半径、长和宽、底和高等)。
分别调用这些对象的计算面积方法,并打印出计算结果。
"""
from math import pi


class Shape:

    def calculate_area(self):
        raise NotImplementedError


class Circle(Shape):

    def __init__(self, radius):
        self.radius = radius

    def calculate_area(self):
        area = pi * self.radius ** 2
        return area


class Rectangle(Shape):

    def __init__(self, length, width):
        self.length = length
        self.width = width

    def calculate_area(self):
        area = self.length * self.width
        return area


class Triangle(Shape):

    def __init__(self, base, height):
        self.base = base
        self.height = height

    def calculate_area(self):
        area = self.base * self.height * 0.5
        return area


# shape = Circle(5)
# shape = Rectangle(5, 6)
shape = Triangle(5, 6)
_area = shape.calculate_area()
print(_area)
遇见安然遇见你,不负代码不负卿。
谢谢老铁的时间,咱们下篇再见~

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

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

相关文章

第十六届蓝桥杯模拟二(串口通信)

由硬件框图可以知道我们要配置LED 和按键 一.LED 先配置LED的八个引脚为GPIO_OutPut,锁存器PD2也是,然后都设置为起始高电平,生成代码时还要去解决引脚冲突问题 二.按键 按键配置,由原理图按键所对引脚要GPIO_Input 生成代码,在文件夹中添加code文件夹,code中添加fun.…

UE5学习笔记 FPS游戏制作32 主菜单,暂停游戏,显示鼠标指针

文章目录 一主菜单搭建UI显示主菜单时&#xff0c;暂停游戏&#xff0c;显示鼠标绑定按钮 二 打开主菜单 一主菜单 搭建UI 添加一个MainUi的控件 添加一个返回游戏的按钮和一个退出游戏的按钮 修改一下样式&#xff0c;放中间 显示主菜单时&#xff0c;暂停游戏&#xff0…

LLM - 开源强化学习框架 OpenR1 的环境配置与训练参数 教程

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/146838740 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 OpenR1 是一个开源的强化学习框架,复现 DeepSeek-R1 的训练流程,为研…

蓝桥杯备赛之枚举

用循环等方式依次去枚举所有的数字组合&#xff0c;一一验证是否符合题目的要求 题目链接 0好数 - 蓝桥云课 题目解析 好数的概念: 数的奇数位位奇数,偶数位为偶数,就是一个好数 求输入n里面有多少个好数 题目原理 1> 遍历每个数 2> 每次遍历判断是不是好数 把这…

C++编程语言:抽象机制:一个矩阵的设计(Bjarne Stroustrup)

第29章 一个矩阵的设计(A Matrix Design) 目录 29.1 引言 29.1.1 基本的 Matrix 用法 29.1.2 Matrix 的要求 29.2 一个 Matrix 模板 29.2.1 构造和赋值(Construction and Assignment) 29.2.2 下标和分片(Subscripting and Slicing) 29.3 Matrix算术运算(Matrix…

MSYS2学习笔记

前言 本文内容是MSys2 Documentation的学习笔记可以使用MSYS2编译QGis 学习笔记 什么是MSYS2&#xff1f; MSYS2&#xff08;Minimal System 2&#xff09;是一个为Windows平台打造的软件开发环境和包管理系统&#xff0c;它结合了Cygwin的POSIX兼容层、Arch Linux的pacman…

合规+增效 正也科技携智能营销产品出席中睿论坛

正也科技作为医药数字化领域的标杆企业&#xff0c;受邀参展第二届中睿医健产业企业家年会暨第十三届中睿医药新春论坛&#xff0c;本次论坛以“合力启新程”为主题&#xff0c;吸引了800多位医药健康企业的董事长、总经理参与&#xff0c;并通过主论坛、分论坛、路演等形式探讨…

计算机网络 TCP/IP参考模型

目录 TCP IP模型预览 OSI和TCP的相同点 OSI和TCP的不同点 层参考模型 层参考模型的数据封装与解封装 TCP IP模型预览 OSI和TCP的相同点 OSI和TCP的不同点 层参考模型 层参考模型的数据封装与解封装

JSON的基础知识

文章目录 前言json协议的基本格式json 数组类型 的语法规则json协议报文的实例json常见的一些格式错误在gd32中使用cjson库小结 前言 json协议在互联网应用&#xff0c;物联网应用中都会用到。所谓工欲善其事必先利其器&#xff0c;我们需要学习了解json协议的具体格式&#xf…

区间预测 | MATLAB实现QRBiGRU门控循环单元分位数回归时间序列区间预测

区间预测 | MATLAB实现QRBiGRU门控循环单元分位数回归时间序列区间预测 目录 区间预测 | MATLAB实现QRBiGRU门控循环单元分位数回归时间序列区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 区间预测 | MATLAB实现QRBiGRU门控循环单元分位数回归时间序列区…

11 配置Hadoop集群-免密登录

第一课时 一、复习导入 前面的课程中我们在虚拟机上安装并测试使用了hadoop的示例程序wordcount&#xff0c;并且在准备好了集群的同步工具&#xff0c;那接下来&#xff0c;我们就可去配置hadoop集群了。 二、授新 &#xff08;一&#xff09;认识ssh命令 SSH&#xff08;Secu…

13 配置Hadoop集群-测试使用

第一课时 一、导入 前面的课程我们搭建了hadoop集群&#xff0c;并成功启动了它&#xff0c;接下来我们看看如何去使用集群。 测试的内容包括&#xff1a;1.上传文件&#xff0c;2.下载文件&#xff0c;3.运行程序 二、授新 &#xff08;一&#xff09;上传小文件 上传文件的时…

简单ELK框架搭建

简介 ELK 框架是一套开源的日志管理和分析工具&#xff0c;由 Elasticsearch、Logstash 和 Kibana 三个主要组件组成&#xff0c;现在新增了Filebeat组件&#xff0c;可以更高效的收集数据。 Elasticsearch&#xff1a;是一个分布式、高可扩展的开源搜索引擎&#xff0c;能快速…

Vue2和Vue3响应式的基本实现

目录 简介Vue2 响应式Vue2 响应式的局限性 Vue3 响应式Vue3 响应式的优点 Vue2 和 Vue3 响应式对比 简介 在 Vue 框架中&#xff0c;数据的响应式是其核心特性之一。当页面数据发生变化时&#xff0c;我们希望界面能自动更新&#xff0c;而不是手动操作 DOM。这就需要对数据进…

RCE(自增、取反、异或)

自增: 也就是说&#xff0c;a > b&#xff0c;b > c... 所以&#xff0c;我们只要能拿到一个变量&#xff0c;其值为a&#xff0c;通过自增操作即可获得a-z中所有字符。 无字母数字构造&#xff1a; 所有敏感字符串&#xff08;ASSERT、_POST&#xff09;通过自增动态生…

【深度学习新浪潮】图像修复(Image Inpainting)技术综述:定义、进展与应用展望

本文为精简版,完整技术细节与参考文献可与作者讨论。 1. 图像修复的定义与核心目标 图像修复(Image Inpainting)是一种通过算法手段填补图像中缺失区域或移除不需要对象的技术,其核心目标是利用图像上下文信息生成与周围像素一致且视觉自然的内容。该技术通过计算机视觉和…

计算机视觉——传统数字图像处理中图像去噪原理与代码实现细节

1. 概述 在现实世界中捕获的图像常常受到噪声的影响&#xff0c;这些噪声可能来源于环境因素、信号不稳定、相机传感器问题、照明条件差、电损失等多种因素。为了进一步处理这些图像并对结果进行准确解释&#xff0c;拥有尽可能低噪声的图像至关重要。图像去噪是数字图像处理中…

【STM32】最后一刷-江科大Flash闪存-学习笔记

FLASH简介 STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分&#xff0c;通过闪存存储器接口&#xff08;外设&#xff09;可以对程序存储器和选项字节进行擦除和编程&#xff0c;&#xff08;系统存储器用于存储原厂写入的BootLoader程序&#xff0c;用于串口…

JS实现动态点图酷炫效果

实现目标 分析问题 整个图主要是用canvas实现&#xff0c;其中难点是将线的长度控制在一定范围内、并且透明度随长度变化。 前置知识 canvas绘制点、线、三角形、弧形 // 点ctx.moveTo(this.x, this.y);ctx.arc(this.x, this.y, this.r,0, 2 * Math.PI, false);ctx.fillStyle …

【第十三届“泰迪杯”数据挖掘挑战赛】【2025泰迪杯】【思路篇】A题解题全流程(持续更新)

【第十三届“泰迪杯”数据挖掘挑战赛】【2025泰迪杯】A题解题全流程-思路&#xff08;持续更新&#xff09; 写在前面&#xff1a; 1、A题、C题将会持续更新&#xff0c;陆续更新发布文章 2、赛题交流咨询Q群&#xff1a;1037590285 3、全家桶依旧包含&#xff1a; 代码、…