python笔记10

1、继承

继承是面向对象编程中的一个重要概念,它允许一个类(子类)继承另一个类(父类)的属性和方法。通过继承,子类可以重用父类的代码,并且有机会添加新的属性和方法,或者重写父类的方法。

继承的基本语法:

在 Python 中,使用以下语法实现继承:

class ParentClass:# 父类的属性和方法class ChildClass(ParentClass):# 子类继承父类# 可以添加新的属性和方法,也可以重写父类的方法

示例:

class Animal:def __init__(self, name):self.name = namedef speak(self):print(f"{self.name} makes a sound")# Dog 类继承 Animal 类
class Dog(Animal):def speak(self):print(f"{self.name} barks")# 创建父类实例
animal_obj = Animal("Generic Animal")
animal_obj.speak()  # 输出: Generic Animal makes a sound# 创建子类实例
dog_obj = Dog("Buddy")
dog_obj.speak()  # 输出: Buddy barks

在这个例子中,Dog 类继承了 Animal 类。Dog 类具有 Animal 类的属性和方法,但它还重写了 speak 方法,使其输出狗的特定声音。通过继承,我们可以实现代码的重用和扩展。

调用父类的方法:

在子类中,可以使用 super() 函数调用父类的方法。这样可以在子类中扩展父类的方法而不完全覆盖它。

class Bird(Animal):def speak(self):# 调用父类的 speak 方法super().speak()print(f"{self.name} sings")# 创建子类实例
bird_obj = Bird("Tweetie")
bird_obj.speak()

在这个例子中,Bird 类继承了 Animal 类,并在 speak 方法中通过 super().speak() 调用了父类的 speak 方法,然后添加了新的逻辑。

在面向对象编程中,Python 支持多继承,这意味着一个类可以继承自多个父类。同时,一个父类也可以有多个子类。这种多对多的关系可以带来更灵活的代码组织和结构。

一个子类继承多个父类:

class ParentClass1:# 父类1的属性和方法class ParentClass2:# 父类2的属性和方法class ChildClass(ParentClass1, ParentClass2):# 子类继承父类1和父类2# 可以添加新的属性和方法,也可以重写父类的方法

在这个例子中,ChildClass 继承了 ParentClass1ParentClass2 两个父类。

一个父类拥有多个子类:

class ParentClass:# 父类的属性和方法class ChildClass1(ParentClass):# 子类1继承父类class ChildClass2(ParentClass):# 子类2继承父类class ChildClass3(ParentClass):# 子类3继承父类

在这个例子中,ParentClass 有三个子类:ChildClass1ChildClass2ChildClass3

多继承的注意事项:

尽管多继承提供了更灵活的代码组织方式,但也需要注意一些潜在的问题:

  1. 命名冲突: 如果多个父类中有相同名称的属性或方法,可能会导致命名冲突。可以使用 super() 函数来明确调用特定父类的方法,以解决这个问题。

  2. 复杂性增加: 多继承可能导致代码结构复杂化,理解和维护变得更加困难。在设计时要权衡利弊,确保选择多继承是合理的。

  3. Diamond Inheritance Problem: 当一个类同时继承自两个类,而这两个类又继承自同一个类,就会形成“菱形继承”结构,可能引发一些问题。Python 使用 C3 线性化算法来解决这个问题,但需要程序员遵循良好的设计原则。

class Animal:def speak(self):print("Animal speaks")class Bird:def fly(self):print("Bird flies")class Parrot(Animal, Bird):def speak(self):super().speak()print("Parrot talks")# 创建子类实例
parrot = Parrot()# 调用子类方法
parrot.speak()  # 输出: Animal speaks \n Parrot talks
parrot.fly()    # 输出: Bird flies

2、方法重写

方法重写(Method Overriding)是面向对象编程中的一个概念,它允许子类提供对其父类中已经定义的方法的新实现。重写的方法在子类中具有与父类中方法相同的名称和签名,但是提供了不同的实现。

以下是一个简单的例子,演示了方法重写的概念:

class Animal:def make_sound(self):print("Some generic sound")class Dog(Animal):def make_sound(self):print("Woof! Woof!")class Cat(Animal):def make_sound(self):print("Meow!")# 创建 Animal、Dog 和 Cat 类的实例
animal = Animal()
dog = Dog()
cat = Cat()# 调用各个类的 make_sound 方法
animal.make_sound()  # 输出: Some generic sound
dog.make_sound()     # 输出: Woof! Woof!
cat.make_sound()     # 输出: Meow!

在这个例子中:

  • Animal 类有一个 make_sound 方法,它提供了一个通用的动物声音。
  • Dog 类和 Cat 类分别继承自 Animal,并且它们都重写了 make_sound 方法,提供了狗和猫特有的声音。

当你调用对象的 make_sound 方法时,实际上调用的是该对象所属类中的方法。因此,dog.make_sound() 调用的是 Dog 类中的 make_sound 方法,而不是从 Animal 类继承的版本。

方法重写是一种实现多态(Polymorphism)的方式,它允许不同的子类对象对相同的方法做出不同的响应。这提高了代码的灵活性和可维护性,允许你根据具体的子类实现定制化的行为。

3、多态

多态(Polymorphism)是面向对象编程中的一个重要概念,它允许使用不同的数据类型执行相同的操作,而这些操作可以根据对象的类型具有不同的行为。简而言之,多态允许不同的对象对同一消息做出不同的响应。

多态有两种实现方式:编译时多态和运行时多态。

  1. 编译时多态:也称为静态多态或早期绑定。在编译时,根据对象的声明类型来决定调用哪个方法。这种多态是通过函数重载和运算符重载来实现的。

  2. 运行时多态:也称为动态多态或晚期绑定。在运行时,根据对象的实际类型来决定调用哪个方法。这种多态是通过方法重写(覆盖)和接口实现来实现的。

通过一个示例来说明多态的概念:

class Animal:def speak(self):passclass Dog(Animal):def speak(self):return "Woof!"class Cat(Animal):def speak(self):return "Meow!"class Duck(Animal):def speak(self):return "Quack!"# 函数接受 Animal 对象,并调用其 speak 方法
def make_sound(animal):print(animal.speak())# 创建不同的动物对象
dog = Dog()
cat = Cat()
duck = Duck()# 调用 make_sound 函数,传入不同的动物对象
make_sound(dog)   # 输出: Woof!
make_sound(cat)   # 输出: Meow!
make_sound(duck)  # 输出: Quack!

在这个示例中:

  • Animal 类定义了一个 方法speak,但没有提供具体的实现。
  • DogCatDuck 类分别继承自Animal ,并且它们都重写了 方法speak,提供了狗、猫和鸭的叫声。
  • make_sound 函数接受一个 对象Animal,并调用其 方法speak,而不需要知道具体对象的类型。

这就是多态的威力:通过相同的接口处理不同类型的对象,使得代码更加灵活、可扩展和易于维护。

4、object类

在Python中, object是所有类的基类。所有其他类都直接或间接地继承自 object类。在面向对象编程中, 提供了一些基本的方法和属性,所有object类都可以使用这些方法和属性。

一些常见的 object类的方法包括:

  1. __init__ 方法: 用于对象的初始化。当一个对象被创建时, __init__方法会被调用。

  2. __str__ 方法: 用于返回对象的字符串表示。当使用 str(object)print(object)时,实际上是调用了对象的 __str__方法。

  3. __repr__ 方法: 类似于 __str__方法,用于返回对象的字符串表示。当使用 repr(object)或print(repr(object))在交互式环境中键入对象名并按回车时,会调用 __repr__方法。

  4. __eq__ 方法: 用于比较对象的相等性。当使用 ==运算符进行比较时,实际上是调用了对象的__eq__ 方法。

这是一个简单的例子,演示了如何创建一个自定义类并继承自object

class CustomClass(object):def __init__(self, name):self.name = namedef __str__(self):return f"CustomClass: {self.name}"def __repr__(self):return f"CustomClass('{self.name}')"def __eq__(self, other):if isinstance(other, CustomClass):return self.name == other.namereturn False# 创建两个 CustomClass 对象
obj1 = CustomClass("Object 1")
obj2 = CustomClass("Object 2")# 调用 __str__ 方法
print(obj1)   # 输出: CustomClass: Object 1# 调用 __repr__ 方法
print(repr(obj1))  # 输出: CustomClass('Object 1')# 使用 == 运算符比较对象
print(obj1 == obj2)  # 输出: False

5、对象的特殊方法

对象的特殊方法(也称为魔术方法或双下划线方法)是在类中以双下划线(__)开头和结尾的方法,用于实现对象的特定行为。这些方法可以被Python解释器调用,而不是由开发者直接调用。以下是一些常见的对象特殊方法:

  1. __init__(self, ...): 该方法在对象创建时被调用,用于进行初始化操作。它在对象被创建后立即执行。

  2. __str__(self): 当使用 str(object)print(object) 时调用,返回对象的字符串表示。

  3. __repr__(self): 类似于 __str__ 方法,但通常用于生成对象的“开发者友好”字符串表示,通过 repr(object) 或在交互式环境中输入对象名而不调用 print 时调用。

  4. __eq__(self, other): 用于比较对象的相等性。当使用 == 运算符进行比较时,实际上是调用了对象的 __eq__ 方法。

  5. __lt__(self, other), __le__(self, other), __gt__(self, other), __ge__(self, other): 分别用于实现对象的小于、小于等于、大于和大于等于运算符。

  6. __add__(self, other): 用于实现对象的加法操作。当使用 + 运算符时,实际上是调用了对象的 __add__ 方法。

  7. __sub__(self, other): 用于实现对象的减法操作。当使用 - 运算符时,实际上是调用了对象的 __sub__ 方法。

  8. __len__(self): 返回对象的长度。当调用内建函数 len(object) 时调用。

  9. __getitem__(self, key): 用于获取对象的元素,支持索引操作。当使用 object[key] 时调用。

  10. __setitem__(self, key, value): 用于设置对象的元素,支持索引操作。当使用 object[key] = value 时调用。

  11. __delitem__(self, key): 用于删除对象的元素,支持索引操作。当使用 del object[key] 时调用。

这些特殊方法允许类自定义其实例的行为,使其可以与Python的内建功能(如len()str()==等)交互。通过实现这些方法,开发者可以更好地控制类的实例在不同上下文中的行为。

6、特殊属性

在Python中,除了特殊方法(双下划线开头和结尾的方法)之外,还有一些特殊属性(也称为魔术属性或内置属性),它们以双下划线开头和结尾,用于提供对象的一些元信息或行为。以下是一些常见的特殊属性:

  1. __dict__: 包含对象的命名空间(namespace)的字典,其中存储了对象的属性。

  2. __class__: 表示对象所属的类。

  3. __doc__: 包含对象的文档字符串(docstring)。

  4. __name__: 对于模块,表示模块的名称;对于类,表示类的名称。

  5. __module__: 表示定义对象的模块名称。对于在交互式环境中定义的对象,它可能为 "__main__"

  6. __bases__: 对于类,表示其基类的元组。

  7. __annotations__: 包含变量注解的字典。

  8. __slots__: 一个类属性,用于限制类实例可以具有的属性,通常是一个字符串列表。

  9. __weakref__: 用于支持弱引用(weak reference)。

这里是一个简单的例子,演示了一些特殊属性的使用:

class MyClass:class_variable = "I am a class variable"def __init__(self, name):self.name = name# 创建一个对象
obj = MyClass("Object")# 访问特殊属性
print(obj.__dict__)       # 对象的命名空间
print(obj.__class__)      # 对象所属的类
print(obj.__doc__)        # 对象的文档字符串
print(obj.__module__)     # 定义对象的模块名称
print(obj.__name__)       # 对象的名称
print(obj.__bases__)      # 对象的基类元组
print(obj.__annotations__) # 变量注解的字典

需要注意的是,虽然这些特殊属性可以访问,但在通常的编程中,直接使用它们的情况相对较少。特殊属性主要用于一些高级用途,例如元编程(metaprogramming)或在特定情况下获取有关对象的信息。在一般情况下,通过调用对象的方法和访问其属性来与对象交互更为常见。

7、类的深拷贝与浅拷贝

深拷贝(deep copy)和浅拷贝(shallow copy)是关于复制对象时涉及到的两个概念,主要涉及到嵌套对象的复制问题。

浅拷贝:

  • 浅拷贝创建一个新对象,然后将原对象中的元素(如子对象)的引用复制到新对象中。这意味着新对象中的元素是原对象中元素的引用,而不是新的独立的对象。                             
  • Python中,可以使用 copy 模块的 copy() 函数进行浅拷贝。
import copyoriginal_list = [1, [2, 3, 4], 5]
shallow_copy = copy.copy(original_list)print(shallow_copy)

在上面的例子中,original_list 中的第二个元素是一个嵌套的列表。通过浅拷贝后,shallow_copy 中的嵌套列表仍然是原始列表中相同的列表引用。

深拷贝:

  • 深拷贝创建一个新对象,然后递归地复制原对象中的所有元素,包括子对象。这意味着新对象是原对象及其所有子对象的独立副本,而不是简单的引用关系。                                          在
  • Python中,可以使用 copy 模块的 deepcopy() 函数进行深拷贝。
    import copyoriginal_list = [1, [2, 3, 4], 5]
    deep_copy = copy.deepcopy(original_list)print(deep_copy)
    

    在上面的例子中,通过深拷贝后,deep_copy 中的嵌套列表是原始列表中相同元素的独立副本,而不是引用。

选择深拷贝还是浅拷贝取决于你的需求。如果对象中没有嵌套对象或者你希望嵌套对象也是独立的,那么使用深拷贝是合适的。如果你只是想复制对象的结构而不需要复制嵌套对象的元素,那么浅拷贝可能更有效。

如果还是不明白浅拷贝和深拷贝的区别,下面详细介绍下

赋值,浅拷贝,深拷贝在内存中的行为:

看最后画的内存图后一定能理解它们的区别

class CPU():passclass GPU():passclass Computer():# 计算机有CPU和GPUdef __init__(self,cpu,gpu):self.cpu = cpuself.gpu = gpucpu = CPU()#创建一个CPU对象
gpu = GPU()#创建一个GPU对象#创建一个计算机对象
computer = Computer(cpu,gpu)
#变量(对象)的赋值
computer1 = computer
print(computer,'computer子对象的内存地址:',computer.cpu,computer.gpu)
print(computer1,'computer1子对象的内存地址:',computer1.cpu,computer1.gpu)import copy
computer2 = copy.copy(computer)#computer2是新产生的对象,computer2的子对象cpu,gpu不变
print(computer2,'computer2子对象的内存地址:',computer2.cpu,computer2.gpu)computer3 = copy.deepcopy(computer)#computer3是新产生的对象,computer3的子对象cpu,gpu也会重新创建
print(computer3,'computer3子对象的内存地址:',computer3.cpu,computer3.gpu)

  • 赋值: 共享相同的内存空间,修改一个会影响另一个。
  • 浅拷贝: 顶层元素有不同的内存地址,但嵌套对象是共享的。
  • 深拷贝: 完全独立,包括所有嵌套对象。

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

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

相关文章

使用PowerBI 基于Adventure Works案例分析

Adventure Works案例分析 前言 数据时代来临,但一个人要顺应时代的发展是真理。 数据分析的核心要素 那数分到底是什么? 显然DT 并不等同于 IT,我们需要的不仅仅是更快的服务器、更多的数据、更好用的工具。这些都是重要的组成部分&…

堆宝塔

L2-1 堆宝塔 分数 25 作者 陈越 单位 浙江大学 堆宝塔游戏是让小朋友根据抓到的彩虹圈的直径大小,按照从大到小的顺序堆起宝塔。但彩虹圈不一定是按照直径的大小顺序抓到的。聪明…

AI特训一:为什么要学习AI

我们先了解什么是AI AI(人工智能)是指计算机系统经过学习和推理能够模拟人类智能行为的一种技术。AI利用机器学习、深度学习、自然语言处理等技术,能够分析大量的数据、识别模式、做出决策和预测 AI有哪些强大之处 处理大量数据&#xff1a…

专栏:数据库、中间件的监控一网打尽

前言 对于数据库、中间件的监控,目前社区里最为完善的就是 Prometheus 生态的各个 Exporter,不过这些 Exporter 比较分散,不好管理,如果有很多目标实例需要监控,就要部署很多个 Exporter,要是能有一个大一…

蓝桥杯嵌入式——测量两路PWM频率和占空比

原理:在通道1,TIM_CH1上会输入PWM波,在每个上升沿来的时候会发生三个动作,第一个动作会触发一个中断,第二个动作会把CNT计数值捕获,第三个动作会把CNT的值清0, 要测量占空比则需要打开TI1FP2&a…

经济学基础入门,从《小岛经济学》看经济的演变

一直在学习怎么赚钱,没有专业的人指导。于是就想着先学习一下经济学相关的知识吧!无意间看到大家推荐的这本书籍,一本很适合经济学入门的经济《小岛经济学》,这本书以故事的方式,讲解了经济演变过程。而且大约只需要2到…

对嵌入式系统、GCC、的理解

1、嵌入式系统通用硬件组成 2、Linux系统的嵌入式的开发流程 3、Linux系统的嵌入式的结构 4、文件IO和标准IO? 5、为什么需要交叉编译 1、嵌入式系统硬件的限制(CPU处理能力不如电脑、存储空间小、网络带宽小不利于传输、安全性不如电脑、能耗问题&…

关于GitHub国内打不开的有效解决办法

哈喽大家好,我是咕噜美乐蒂,很高兴又见面啦! GitHub是全球最大的开源代码托管平台之一,但由于某些原因,它在中国大陆地区经常会遭受网络封锁,导致无法正常访问。如果您也遇到了这个问题,不要担…

【计算机网络】——TCP协议

📑前言 本文主要是【计算机网络】——传输层TCP协议的文章,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是青衿🥇 ☁️博客首页:CSDN主页放风讲故事 🌄每日一句…

前端面试题-说说你了解的js数据结构?(2024.1.29)

1、数组 (Array) 数组是一组有序的值的集合,可以通过索引访问。JavaScript 数组可以包含不同的数据类型,并且长度是动态的。 let myArray [1, hello, true, [2, 3]];2、对象 (Object) 对象是无序的键值对的集合。每个键都是字符串或符号,…

安全刷写简单说明

文章目录 1.安全刷写的目的2.安全刷写的实现3.安全刷写的要求4.签名说明5.刷写过程 1.安全刷写的目的 为了避免ECU被恶意篡改数据,从而导致ECU功能失效。 2.安全刷写的实现 目前很多厂商会使对软件进行签名操作,从一定程度上实现安全刷写的目的。 3.…

【学网攻】 第(16)节 -- 扩展ACL访问控制列表

系列文章目录 目录 系列文章目录 文章目录 前言 一、ACL(访问控制列表)是什么 ? 二、实验 1.引入 实验目标 实验步骤 实验设备 实验拓扑图 实验配置 配置ACL访问控制 实验验证 总结 文章目录 【学网攻】 第(1)节 -- 认识网络【学网攻】 第(2)节 -- 交换机认识…

2024 年, Web 前端开发趋势

希腊哲学家赫拉克利特认为,变化是生命中唯一不变的东西。这句话适用于我们的个人生活、行业和职业领域。 尤其是前端开发领域,新技术、开发趋势、库和框架不断涌现,变化并不陌生。最近发生的一些事件正在改变开发人员构建网站和 Web 应用的方…

FPS游戏框架漫谈第七条

小地图制作流程漫谈: 1.由于场景导出地图顶视图结构给原画 2.原画会对其进行加工处理 3.经过原画处理后的资源给到还原,还原合入游戏内 4.拿的的资源一般是256256 5.场景需要提供一些采样参数给程序 一般3组即可 每组参数是场景中的坐标和顶视图中屏幕坐…

Python机器学习--简单清晰的说说K近邻算法的基本原理

K近邻算法的基本原理:首先通过所有的特征变量构筑起一个特征空间,特征空间的维数就是特征变量的个数,然后针对某个测试样本,按照参数K在特征空间内寻找与它最为近邻的K个训练样本观测值,最后依据这K个训练样本的响应变…

Codeforces Round 871

目录 A. Love Story B. Blank Space C. Mr. Perfectly Fine D. Gold Rush E. The Lakes F. Forever Winter G. Hits Different H. Don’t Blame Me A. Love Story 直接逐个匹配 string a"codeforces"; void solve() {string s; cin>>s;int cnt0;for(i…

快速理解MoE模型

最近由于一些开源MoE模型的出现,带火了开源社区,为何?因为它开源了最有名气的GPT4的模型结构(OPEN AI),GPT4为何那么强大呢?看看MoE模型的你就知道了。 MoE模型结构: 图中&#xff0…

Netty-ChannelHandle的业务处理

ChannelHandle结构 ChannelHandler基础接口 基础接口里面定义的基础通用方法。增加handler,移除handler,异常处理。 ChannelInboundHandler public interface ChannelInboundHandler extends ChannelHandler {/*** The {link Channel} of the {link Ch…

猫突然不吃东西没精神?性价比高可以迅速恢复精神的生骨肉冻干推荐

猫突然不吃东西没精神怎么办?当猫咪不吃东西、精神不振时,可能是由于健康问题、环境因素或食物原因所引起。首先应进行身体检查,观察是否有其他并发症,如无则可排除健康问题。为猫咪提供安全舒适的环境、给予关爱,可改…

亚信安慧AntDB:AntDB-M元数据锁(七)

5.4.5 慢路径锁的授予条件 当且仅当满足如下两个条件时,才可以授予锁。 1. 其他线程没有持有不兼容类型锁。 2. 当前申请的锁的优先级高于请求等待列表中的。 首先通过锁位图判断等待队列,不兼容则不能授予锁。再判断快速路径,不兼容则不…