python笔记10

news2024/11/19 3:48:20

1、继承

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

继承的基本语法:

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

class ParentClass:
    # 父类的属性和方法

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

示例:

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

    def 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):
        pass

class 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 = name

    def __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.name
        return 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 copy

original_list = [1, [2, 3, 4], 5]
shallow_copy = copy.copy(original_list)

print(shallow_copy)

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

深拷贝:

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

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

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

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

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

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

class CPU():
    pass

class GPU():
    pass

class Computer():
    # 计算机有CPU和GPU
    def __init__(self,cpu,gpu):
        self.cpu = cpu
        self.gpu = gpu

cpu = 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.coloradmin.cn/o/1417504.html

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

相关文章

【C++】一题掌握空指针

今天看见一道面试题&#xff0c;比较有意思&#xff0c;这一分享出来&#xff1a; 1.下面程序能编译通过吗&#xff1f; 2.下面程序会崩溃吗&#xff1f;在哪里崩溃 class A {public:void PrintA(){cout<<_a<<endl;}void Show(){cout<<"Show()"&…

.ui文件相关

目录 ui类生成过程&#xff1a; 提问&#xff1a; 等以后自己熟练了用代码写这些样式内容&#xff0c;尽量用代码写&#xff0c;原因很简单&#xff1a; 用代码写的可以直接修改代码&#xff0c;但是在设计界面修改的东西&#xff0c;电脑没有QC这玩意&#xff0c;还真不好改…

ChatGPT4 比 ChatGPT3.5 强在了那里?

刚开始的时候我还在纠结&#xff0c;一个月20 刀的ChatGPT4 &#xff0c;到底值不值这个价钱&#xff1f;使用过后发现&#xff0c;诶嘛真香。因为 GPT4 比 GPT3.5 多了太多功能&#xff0c;特别是识图能力&#xff0c;用好的话效率翻倍。 1. 看图写代码 ChatGPT4 相比 ChatG…

【极数系列】Flink集成DataSource读取集合数据(07)

文章目录 01 引言02 简介概述03 基于集合读取数据3.1 集合创建数据流3.2 迭代器创建数据流3.3 给定对象创建数据流3.4 迭代并行器创建数据流3.5 基于时间间隔创建数据流3.6 自定义数据流 04 源码实战demo4.1 pom.xml依赖4.2 创建集合数据流作业4.3 运行结果日志 01 引言 源码地…

用ASM HEMT模型提取GaN器件的参数

标题&#xff1a;Physics-Based Multi-Bias RF Large-Signal GaNHEMT Modeling and Parameter Extraction Flow (JEDS 17年) 模型描述 该模型的核心是对表面势&#xff08;ψ&#xff09;及其随施加的栅极电压&#xff08;Vg&#xff09;和漏极电压&#xff08;Vd&#xff09…

【数据结构1-3】集合

有时候&#xff0c;我们并不关心数据之间的前后关系&#xff0c;也不关心数据的层次关系。一些确定元素只是单纯的聚集在一起&#xff0c;这样的元素聚集体被称为集合。 当希望知道某个数据是否存在一个集合中&#xff0c;或者两个元素是否在同一个集合中时&#xff0c;就需要使…

JVM系列——对象管理

JVM对象分布 对象头 第一类是用于存储对象自身的运行时数据&#xff0c;如哈希码&#xff08;HashCode&#xff09;、GC 分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等 另外一部分是类型指针&#xff0c;即对象指向它的类型元数据的指针&#xff0c;Java 虚…

敲黑板啦!CSGO游戏搬砖项目操作注意事项

CSGO游戏搬砖项目怎么赚钱的&#xff0c;利润在哪&#xff1f; 1.两个平台之间币种不一样&#xff0c;就存在一个汇率差&#xff0c;两平台装备价格也不一样&#xff0c;汇率差-价格差利润。 CSGO游戏搬砖项目具体有哪些操作步骤&#xff1f; 1、准备一台电脑&#xff0c;配置…

Git学习,基础,安装,配置,笔记总结

Git安装与常用命令 本教程里的git命令例子都是在Git Bash中演示的,会用到一些基本的linux命令,在此为大家提前列举: ls/ll 查看当前目录 cat 查看文件内容 touch 创建文件 vi vi编辑器(使用vi编辑器是为了方便展示效果,学员可以记事本、editPlus、notPad++等其它编 辑…

C#使用OpenCvSharp4库读取电脑摄像头数据并实时显示

一、OpenCvSharp4库 OpenCvSharp4库是一个基于.Net封装的OpenCV库&#xff0c;Github源代码地址为&#xff1a;https://github.com/shimat/opencvsharp&#xff0c;里面有关于Windows下安装OpenCvSharp4库的描述&#xff0c;如下图所示&#xff1a; 二、C#使用OpenCvSharp4库…

React 组件生命周期-概述、生命周期钩子函数 - 挂载时、生命周期钩子函数 - 更新时、生命周期钩子函数 - 卸载时

React 组件生命周期-概述 学习目标&#xff1a; 能够说出组件的生命周期一共几个阶段 组件的生命周期是指组件从被创建到挂在到页面中运行&#xff0c;在到组件不用时卸载组件 注意&#xff1a;只有类组件才有生命周期&#xff0c;函数组件没有生命周期(类组件需要实例化&…

监听项目中指定属性数据,点击或模块显示时

当项目中&#xff0c;需要获取某个页面上、某个标签上、有指定自定义属性时&#xff0c;需要在点击该元素时进行公共逻辑处理&#xff0c;或该元素在显示的时候进行逻辑处理&#xff0c;这时可以定义一个公共的方法&#xff0c;在每个页面引用&#xff0c;并写入数据即可 &…

Win11系统连接带HDMI接口的显示器后,电脑没有声音如何调试

解决这个问题的方法很简单&#xff0c;没有那么复杂。之所以使用HDMI接口连接了显示器后没声音&#xff0c;原因就是HDMI接口是包含音频视频两种信号的接口。当电脑的HDMI接口被使用时&#xff0c;系统就会默认从HDMI设备输出声音信号了&#xff0c;而此时如果HDMI设备没有声音…

基本控件(二)QMainWindow主窗口相关 以及 手写控件的方法 (按F2)

探究过程 先创建个QMainWindow项目。 鼠标点击选中QMainWindow之后按F2&#xff0c;就会进入其最一开始的定义的头文件中。 来到qmainwindow.h头文件中&#xff0c;可以清楚看到这些继承关系&#xff1a; 同样的操作&#xff0c;来到QWidget的定义之处&#xff1a; UI设计界面…

操作符详解(下)

目录 下标访问[ ]、函数调用() [ ] 下标引用操作符 函数调用操作符 结构成员访问操作符 结构体成员的直接访问 操作符的属性&#xff1a;优先级、结合性 优先级 结合性 整型提升 算术转换 下标访问[ ]、函数调用() [ ] 下标引用操作符 操作数&#xff1a;一个数组…

Matlab处理excel数据

我们新建个excel文档&#xff0c;用Matlab读取里面的内容&#xff0c;计算和判断里面的计算结果是否正确&#xff0c;并打印到另一个文档当中。 新建文档 新建输入文档&#xff0c;文件名TestExcel 编写脚本 [num,txt] xlsread(TestExcel.xlsx); SNcode num(:,1);%从序号中…

github连不上

github连不上 错误提示解决方案steam 采用Hosts加速 错误提示 fatal: unable to access ‘https://github.com/Ada-design/qianduan.git/’: Failed to connect to github.com port 443 after 21073 ms: Couldn’t connect to server 解决方案 下载steam https://steampp.ne…

爬虫基础-前端基础

Html是骨骼、css是皮肤、js是肌肉&#xff0c;三者之间的关系可以简单理解为m(html)-v(css)-c(js) 浏览器的加载过程 构建dom树 子资源加载-加载外部的css、图片、js等外部资源 样式渲染-css执行 DOM树 ajax、json、xml AJAX 是一种在无需重新加载整个网页的情况下&#xf…

【CANoe使用大全】——Logging窗口

&#x1f64b;‍♂️【CANoe使用大全】系列&#x1f481;‍♂️点击跳转 文章目录 1.概述2.Logging窗口打开方式3.创建Logging4.配置4.1. 命名4.2.格式选择4.3. 路径选择与命名4.3.1.Logging文件命名_自定义4.3.2.Logging文件命名_系统内选择 5.Logging触发方式5.1 Logging模块…

MATLAB - 仿真单摆的周期性摆动

系列文章目录 前言 本例演示如何使用 Symbolic Math Toolbox™ 模拟单摆的运动。推导摆的运动方程&#xff0c;然后对小角度进行分析求解&#xff0c;对任意角度进行数值求解。 一、步骤 1&#xff1a;推导运动方程 摆是一个遵循微分方程的简单机械系统。摆最初静止在垂直位置…