Python入门12:面向对象的三大特征与高级特性详解

面向对象编程(OOP)是Python编程中非常重要的一部分,它通过封装继承多态这三大特征,帮助我们更好地组织和管理代码。除此之外,Python还提供了一些其他特性,如类属性类方法静态方法,进一步增强了面向对象编程的灵活性和功能性。本文将详细介绍这些特性,并通过代码示例帮助你更好地理解。

一、面向对象有三大特征

三种:封装性、继承性、多态性

1、封装

在Python代码中,封装有两层含义:
① 把现实世界中的主体中的 属性和⽅法书写到类的⾥⾯的操作 即为封装。
封装可以为属性和⽅法添加为私有权限,不能直接被外部访问

1.1、封装中的私有属性和私有⽅法

在⾯向对象代码中,我们可以把属性和⽅法分为两⼤类:公有(属性、⽅法)、私有(属性、⽅法)
Python:公有(属性、⽅法),私有(属性、⽅法)
公有属性和公有⽅法:⽆论在类的内部还是在类的外部我们都可以对属性和⽅法进⾏操作。
但是有些情况下,我们不希望在类的外部对类内部的属性和⽅法进⾏操作。我们就可以把这个属性或⽅法封装成私有形式。

1.2、私有属性

设置私有属性和私有⽅法的⽅式⾮常简单:在属性名和⽅法名 前⾯ 加上 两个下划线 __ 即可。设置私有属性后,不能直接在类的外面访问私有属性,但是如果我们在在类外部访问私有属性,那么我们需要再类的内部定义访问的“接口”(函数),专门实现私有属性的访问。 接⼝就是我们通常说的⼀个函数,这个函数可以实现对某些属性的访问(设置与获取)。 在Python中, ⼀般定义函数名' get_xx '⽤来获取私有属性,定义' set_xx '⽤来修改私有属性值。
class Person:
 def __init__(self, name, age):
  self.__name = name  # 私有属性
  self.__age = age  # 私有属性

 def get_name(self):  # 公共方法,用于访问私有属性
  return self.__name

 def set_name(self, name):  # 公共方法,用于修改私有属性
  self.__name = name

 def get_age(self):
  return self.__age

 def set_age(self, age):
  if age > 0:
   self.__age = age
  else:
   print("年龄不能为负数!")

# 使用
person = Person("张三", 20)
print(person.get_name())  # 访问私有属性
person.set_name("李四")  # 修改私有属性
print(person.get_name())

运行结果:

对私有属性间接的进行访问:

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

    def tell_info(self):
        print('name:<%s> age:<%s>' % (self.__name, self.__age))

    def set_info(self, name, age):
        if not isinstance(name, str):
            print('名字必须是字符串类型')
            return
        if not isinstance(age, int):
            print('年龄必须是数字类型')
            return
        self.__name = name
        self.__age = age


# 创建实例并调用方法
p = People('jack', 38)
p.tell_info()  # 输出:name:<jack> age:<38>

p.set_info('jennifer', 18)
p.tell_info()  # 输出:name:<jennifer> age:<18>

p.set_info(123, 35)  # 输出:名字必须是字符串类型
p.tell_info()  # 输出:name:<jennifer> age:<18>

运行结果:

1.3、私有方法

class ATM:
 def __card(self):
  print('插卡')

 def __auth(self):
  print('用户认证')

 def __input(self):
  print('输入取款金额')

 def __print_bill(self):
  print('打印账单')

 def __take_money(self):
  print('取款')

 # 定义一个对外提供服务的公共方法
 def withdraw(self):
  self.__card()
  self.__auth()
  self.__input()
  self.__print_bill()
  self.__take_money()

# 创建实例并调用公共方法
atm = ATM()
atm.withdraw()

运行结果:

 

1.4、封装的意义

  • 数据隐藏:通过将属性设置为私有(使用双下划线__),可以防止外部直接访问和修改对象的内部数据。

  • 接口暴露:通过提供公共方法(如get_xxset_xx),可以控制外部对私有属性的访问和修改。

类中的私有属性和私有⽅法,不能被其⼦类继承。

2、继承

2.1、什么是继承?

继承是面向对象编程的另一个重要特征。它允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码的重用和扩展。

继承几个基本概念:

1、继承:⼀个类从另⼀个已有的类获得其成员的相关特性,就叫作继承!
2、派⽣:从⼀个已有的类产⽣⼀个新的类,称为派⽣!
很显然,继承和派⽣其实就是从不同的⽅向来描述的相同的概念⽽已,本质上是⼀样的!
3、⽗类:也叫作基类,就是指已有被继承的类!
4、⼦类:也叫作派⽣类或扩展类
5、扩展:在⼦类中增加⼀些⾃⼰特有的特性,就叫作扩展,没有扩展,继承也就没有意义了!
6、单继承:⼀个类只能继承⾃⼀个其他的类,不能继承多个类,单继承也是⼤多数⾯向对象语⾔的特性!
7、多继承:⼀个类同时继承了多个⽗类, (C++、Python等语⾔都⽀持多继承)

2.2、继承的基本语法

class B(object):
   pass
class A(B):
   pass
a = A()
a.B中的所有公共属性
a.B中的所有公共⽅法

2.3、单继承

单继承是指一个子类只能继承一个父类。通过继承,子类可以复用父类的属性和方法,同时还可以扩展自己的属性和方法。

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

    def speak(self):
     print(f"{self.name} 在叫")

class Dog(Animal):  # 继承自Animal类
    def bark(self):
     print(f"{self.name} 汪汪汪!")

# 实例化Dog对象
dog = Dog("旺财")
dog.speak()  # 调用父类方法
dog.bark()  # 调用子类方法

运行结果:

 

2.4、单继承的传递性

在Python继承中,如A类继承了B类,B类⼜继承了C类。则根据 继承的传递性 ,则A类也会⾃动继承C类中所有属性和⽅法(公共)
class C(object):
    def func(self):
     print('我是C类中的相关⽅法func')

class B(C):
    pass

class A(B):
    pass

a = A()
a.func()

运行结果:

2.5、多继承

Python支持多继承,即一个子类可以同时继承多个父类。虽然多继承允许我们同时继承⾃多个类,但是实际开发中,应尽量避免使⽤多继承,因为如果两个类中出现了相同的属性和⽅法就会产⽣命名冲突。

class you_car(object):
    y_name = "油车"
    def use_you(self):
        print("我是油车,我使用的是汽油驱动!!!")

class dian_car(object):
    d_name = "电车"
    def use_dian(self):
        print("我是电车,我使用的是电力驱动")

class hunhe_car(you_car,dian_car):
    yd_name = "油电混动"
    def use_hunhe(self):
        print("我是油电混懂,我既能够使用汽油驱动,又能够使用电力驱动")

hh = hunhe_car()
hh.use_hunhe()
hh.use_you()
hh.use_dian()
print(hh.y_name)
print(hh.d_name)
print(hh.yd_name)

运行结果:

2.6、⼦类扩展:重写⽗类属性和⽅法
扩展特性:继承让⼦类继承⽗类的所有公共属性和⽅法,但是如果仅仅是为了继承公共属性和⽅法,继承就没有实际的意义了,应该是在继承以后,⼦类应该有⼀些⾃⼰的属性和⽅法。
什么是重写?
如果⼦类中的属性和⽅法与⽗类中的属性或⽅法同名 则⼦类中的属性或⽅法会对⽗类中同名的属性或⽅法进⾏覆盖(重写)

 

# 重写2:类⽅法的调⽤顺序,当我们在⼦类中重构⽗类的⽅法后,Cat⼦类的实例先会在⾃⼰的类 Cat 中查找该⽅法,
# 当找不到该⽅法时才会去⽗类 Animal 中查找对应的⽅法。
class Animal():
    def call(self):
        print("我是动物类中叫方法")

class Cat(Animal):
    # 自定义
    def cat_call(self):
        print("我是猫类中喵喵叫的方法")
    # 重写方法
    def call(self):
        print("我是猫类中喵喵叫的方法")
# 父类中的方法功能不够,在子类中的解决方法:
# 1、重写
# 2、定义一个新的方法
c = Cat()
c.call()

运行结果:

 

2.7、super()调⽤⽗类属性和⽅法

在子类中,可以通过super()函数调用父类的方法,尤其是在重写父类方法时,仍然希望保留父类的行为。在Python3以 后版本中,调⽤⽗类的属性和⽅法我们只需要使⽤ super().属性 或 super().⽅法名() 就可以完 成调⽤了。

class Car:
    def __init__(self, brand, model):
        self.brand = brand   # 品牌
        self.model = model  # 型号

    def run(self):
        print(f"{self.brand} {self.model} 在行驶!")

class ElectricCar(Car):
    # 重写构造函数
    def __init__(self, brand, model, battery):
        super().__init__(brand, model)  # 调用父类的构造方法
        self.battery = battery
    # 重写run方法
    def run(self):
        super().run()  # 调用父类的run方法
        print(f"在以 {self.battery} 千米每小时的速度在行驶")

tesla = ElectricCar("Tesla", "Model S", 75)
tesla.run()

运行结果:

 

2.8.MRO属性或MRO⽅法:⽅法解析顺序

当多个父类中有同名方法时,Python 需要确定调用哪个父类的方法,这就涉及到方法解析顺序(MRO)。Python 使用 C3 线性化算法来计算 MRO。可以使用__mro__属性或mro()方法查看类的 MRO。

class A:
    def method(self):
        print("Method from A")

class B(A):
    def method(self):
        print("Method from B")

class C(A):
    def method(self):
        print("Method from C")

class D(B, C):
    pass

# 查看D类的MRO
print(D.__mro__)

# 创建D类的实例
d = D()
# 调用method方法
d.method()

运行结果:

 

class Parent1:
    def __init__(self):
        print("Parent1 __init__")

class Parent2:
    def __init__(self):
        print("Parent2 __init__")

class Child(Parent1, Parent2):
    def __init__(self):
        # 调用父类的__init__方法
        super().__init__()
        print("Child __init__")

# 创建Child类的实例
child = Child()
print(Child.__mro__)

 运行结果:

 

说明:有MRO⽅法解析顺序可知,在类的继承中,当某个类创建了⼀个对象时,调⽤属性或⽅法, ⾸先 在⾃身类中去寻找,如找到,则直接使⽤,停⽌后续的查找。如果未找到,继续向上⼀级继承的类中去 寻找,如找到,则直接使⽤,没有找到则继续向上寻找...直到object类,这就是Python类继承中,其⽅法解析顺序。

3、多态

3.1、什么是多态?

多态指的是⼀类事物有多种形态。
定义:多态是⼀种使⽤对象的⽅式,⼦类重写⽗类⽅法,调⽤不同⼦类对象的相同⽗类⽅法,可以产⽣ 不同的执⾏结果。
① 多态依赖继承(不是必须的)
② ⼦类⽅法必须要重写⽗类⽅法。
好处:调⽤灵活,有了多态,更容易编写出通⽤的代码,做出通⽤的编程,以适应需求的不断变化!

3.2多态原理图

3.3、多态代码的实现

# ⽗类Fruit
class Fruit(object):
    def makejuice(self):
        print('i can make juice')

# ⼦类:苹果
class Apple(Fruit):
    # 重写⽗类⽅法
    def makejuice(self):
        print('i can make apple juice')

# ⼦类:⾹蕉
class Banana(Fruit):
    # 重写⽗类⽅法
    def makejuice(self):
        print('i can make banana juice')

# ⼦类:橘⼦
class Orange(Fruit):
    # 重写⽗类⽅法
    def makejuice(self):
        print('i can make orange juice')

# 定义⼀个公共接⼝(专⻔⽤于实现榨汁操作)
def service(obj):
    # obj要求是⼀个实例化对象,可以传⼊苹果对象/⾹蕉对象
    obj.makejuice()

# 调⽤公共⽅法
service(Orange())

运行结果:

3.4、在Python中还有哪些多态的案例呢?

# 数值相加
print(1 + 2)  # 输出:3

# 字符串拼接
print("Hello" + " World")  # 输出:Hello World

# 列表合并
print([1, 2] + [3, 4])  # 输出:[1, 2, 3, 4]

二、面向对象的其他高级特性

1、类属性

类属性是属于类本身的属性,而不是类的实例。类属性被该类的所有实例对象所共享。

class Person(object):
    # 定义类属性count,⽤于记录⽣成的Person类对象的个数
    count = 0

    # 定义⼀个__init__魔术⽅法,⽤于进⾏初始化操作
    def __init__(self, name):
        self.name = name
        # 对count类属性进⾏+1操作,⽤于记录这个Person类⼀共⽣成了多少个对象
        Person.count += 1


# 1、实例化对象p1
p1 = Person('Tom')
p2 = Person('Harry')
p3 = Person('Jennifer')

# 2、在类外部输出类属性
print(f'我们共使⽤Person类⽣成了{Person.count}个实例对象')

运行结果:

2、类方法

为什么需要类⽅法,在⾯向对象中,特别强调数据封装性。所以不建议直接在类的外部对 类属性 进⾏直接获取。所以我们如果想操作类属性,建议使⽤类⽅法。
class Tool(object):
    # 定义⼀个类属性count
    count = 0

    # 定义⼀个__init__初始化⽅法
    def __init__(self, name):
        self.name = name
        Tool.count += 1

    # 封装⼀个类⽅法:专⻔实现对Tool.count类属性进⾏操作
    @classmethod  # 声明为类⽅法,⽤于对类属性进⾏操作
    def get_count(cls):  # cls代表类对象
        print(f'我们使⽤Tool类共实例化了{cls.count}个⼯具')

t1 = Tool('斧头')
t2 = Tool('榔头')
t3 = Tool('铁锹')

Tool.get_count()

运行结果:

3、静态方法

静态方法既不操作实例属性,也不操作类属性。它通常用于实现与类相关的工具函数。

class Game:
    @staticmethod
    def menu():
        print("1. 开始游戏")
        print("2. 游戏暂停")
        print("3. 退出游戏")

# 调用静态方法
Game.menu()

三、总结

面向对象编程的三大特征——封装继承多态,是Python编程中非常重要的概念。通过封装,我们可以隐藏对象的内部实现细节;通过继承,我们可以复用和扩展代码;通过多态,我们可以编写更加通用和灵活的代码。此外,Python还提供了类属性类方法静态方法等高级特性,进一步增强了面向对象编程的功能性。

希望本文能帮助你更好地理解Python面向对象编程的核心概念,并在实际开发中灵活运用这些特性!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

20分钟 Bash 上手指南

文章目录 bash 概念与学习目的第一个 bash 脚本bash 语法变量的使用位置参数管道符号&#xff08;过滤条件&#xff09;重定向符号条件测试命令条件语句case 条件分支Arrayfor 循环函数exit 关键字 bash 脚本记录历史命令查询文件分发内容 bash 概念与学习目的 bash&#xff0…

观成科技:海莲花“PerfSpyRAT”木马加密通信分析

1.概述 在2024年9月中旬至10月&#xff0c;东南亚APT组织“海莲花”通过GitHub发布开源安全工具项目&#xff0c;针对网络安全人员发起了定向攻击。通过对相关攻击活动进行分析&#xff0c;可以将其与一些海莲花的样本关联起来。这些样本的通信数据结构与海莲花此前使用的攻击…

Orange 开源项目 - 集成百度智能云-千帆大模型

1 集成百度智能云-千帆大模型 百度智能云-千帆ModelBuilder百度智能云千帆大模型服务与开发平台ModelBuilder&#xff08;以下简称千帆ModelBuilder&#xff09;是面向企业开发者的一站式大模型开发及服务运行平台。千帆ModelBuilder不仅提供了包括文心一言底层模型和第三方开源…

猿大师播放器:网页内嵌VLC/FFPlayer在Web端直接播放RTSP/RTMP/H.265视频流

据统计&#xff0c;2024年中国视频转码服务器市场规模已突破百亿&#xff0c;但企业IT投入中约40%用于转码服务器的采购与维护&#xff0c;消防、安防等场景对实时性的严苛要求&#xff08;如火灾预警需秒级响应&#xff09;&#xff0c;使得传统转码方案因延迟过高而屡屡失效&…

uni-app 开发 App 、 H5 横屏签名(基于lime-signature)

所用插件&#xff1a;lime-signature 使用到 CSS 特性 绝对定位transform 旋转transform-origin transform 原点 复习一下定位元素&#xff08;相对定位、绝对定位、粘性定位&#xff09; 代码# <template><view class"signature-page"><view clas…

搜广推校招面经三十一

vivo策略算法 一、机器学习中 L1 和 L2 正则化的原理 见【搜广推校招面经二十五】 L1 正则化将某些特征权重置0实现模型简化&#xff0c;而 L2 正则化主要通过平滑权重来实现模型简化。 1.1. 正则化的原理 正则化的核心思想是在损失函数中加入一个惩罚项&#xff08;Regula…

DeepSeek+Kimi生成高质量PPT

DeepSeek与Kimi生成PPT全流程解析 一、工具分工原理 DeepSeek核心作用&#xff1a;生成结构化PPT大纲&#xff08;擅长逻辑构建与内容优化&#xff09;Kimi核心作用&#xff1a;将文本转换为视觉化PPT&#xff08;提供模板库与排版引擎&#xff09; 二、操作步骤详解 1. 通…

vmware虚拟机安装使用教程【视频】

vmware虚拟机安装使用教程【视频】 VMware是一款强大的桌面级虚拟化软件&#xff0c;它允许用户在单个计算机上同时运行多个操作系统&#xff0c;每个操作系统都被称为一个虚拟机&#xff08;VM&#xff09;。这种技术不仅方便了软件测试、系统开发&#xff0c;还便于资源管理&…

【Linux Oracle】time命令+oracle exp压缩

Linux && Oracle相关文档&#xff0c;希望互相学习&#xff0c;共同进步 风123456789&#xff5e;-CSDN博客 1.说明 Linux中的time命令&#xff1a;主要用于测量命令的执行时间&#xff0c;并显示该命令在执行过程中所使用的系统资源情况&#xff0c;如CPU时间、内存和…

STM32CUBEIDE FreeRTOS操作教程(十三):task api 任务访问函数

STM32CUBEIDE FreeRTOS操作教程&#xff08;十三&#xff09;&#xff1a;task api 任务访问函数 STM32CUBE开发环境集成了STM32 HAL库进行FreeRTOS配置和开发的组件&#xff0c;不需要用户自己进行FreeRTOS的移植。这里介绍最简化的用户操作类应用教程。以STM32F401RCT6开发板…

网络安全扫描--基础篇

前言 1、了解互联网安全领域中日趋重要的扫描技术 2、了解在不同网络场景下扫描技术手段 3、熟悉linux下系统内核防护策略并能大件一个有效的系统防护体系 4、增强工作安全意识&#xff0c;并能有效的实践于工作场景中 目录 1、熟悉主机扫描工具&#xff08;fping&#xff0c;…

品融电商解读:小红书KOC打法如何重构品牌增长新路径

品融电商解读&#xff1a;小红书KOC打法如何重构品牌增长新路径 在内容生态高度饱和的今天&#xff0c;品牌若想在小红书等平台实现破局&#xff0c;仅依赖“产品为王”的单一逻辑已远远不够。作为国内头部的小红书代运营公司&#xff0c;品融电商观察到&#xff0c;平台的竞…

【原创工具】文件清单生成器 By怜渠客

【原创工具】文件清单生成器 By怜渠客 刚在论坛看到了一个文件列表生成器 文件列表生成器 - 吾爱破解 - 52pojie.cn &#xff0c;和我去年写的一个软件很像&#xff0c;当时我也是有需求&#xff0c;要把一个文件夹里及其子文件夹里所有的文件列出来&#xff0c;就临时弄了个小…

深度学习-6.用于计算机视觉的深度学习

Deep Learning - Lecture 6 Deep Learning for Computer Vision 简介深度学习在计算机视觉领域的发展时间线 语义分割语义分割系统的类型上采样层语义分割的 SegNet 架构软件中的SegNet 架构数据标注 目标检测与识别目标检测与识别问题两阶段和一阶段目标检测与识别两阶段检测器…

力扣-动态规划-746 使用最小花费爬楼梯

思路 dp数组定义&#xff1a;爬到第i层楼梯最小消耗dp[i]的费用递推公式&#xff1a;dp数组初始化&#xff1a;dp[0] 0, dp[1] 0;遍历顺序&#xff1a;顺序遍历时间复杂度&#xff1a; 代码 class Solution { public:int minCostClimbingStairs(vector<int>&am…

智慧后勤的消防管理:豪越科技为安全护航

智慧后勤消防管理难题大揭秘&#xff01; 在智慧后勤发展得如火如荼的当下&#xff0c;消防管理却暗藏诸多难题。传统模式下&#xff0c;消防设施分布得那叫一个散&#xff0c;就像一盘散沙&#xff0c;管理起来超费劲。人工巡检不仅效率低&#xff0c;还容易遗漏&#xff0c;不…

Linux中的cgdb的基本使用

1.cgdb的简介 Linux中的cgdb是一个基于GDB&#xff08;GNU Debugger&#xff09;的图形化调试前端&#xff0c;它结合了GDB的命令行界面功能和代码查看窗口&#xff0c;为开发者提供了一个更为直观的调试体验。 cgdb的作用和功能&#xff1a; 直观调试体验&#xff1a;cgdb提供…

欧拉回路与哈密尔顿回路: Fleury算法与Hierholzer 算法(C++)

图论中的回路是指一个路径, 它从某个顶点开始, 经过所有边恰好一次, 并回到起始顶点. 定义 欧拉回路: 从一个顶点出发, 经过每条边恰好一次, 并且最终回到起始顶点. 哈密尔顿回路: 从一个顶点出发, 经过每个顶点恰好一次, 并且最终回到起始顶点. 欧拉路径: 从一个顶点出发, …

数据结构 之 【无头单向非循环链表】(C语言实现)

下面将 无头单向非循环链表 简称为 单链表 头指针&#xff1a;指向链表第一个节点的指针 链表为空时&#xff0c;头指针也为空 要实现单链表&#xff0c;就是要实现单链表的 增删查改 一、无头单向非循环链表的c语言实现 1.准备工作 #include <stdio.h> #include <s…

傅里叶变换+注意力机制!CCF-A离你并不遥远!

今天给大家推荐一个&#xff0c;创新Top且热度持续攀升的方向&#xff1a;傅里叶变换注意力机制&#xff01; 傅里叶变换能够捕捉到频域的特征&#xff0c;而注意力机制则能使模型专注任务相关信息。两者结合&#xff0c;不仅能提升模型的性能和效率&#xff0c;还能增强模型的…