Python面向对象进阶教程,Python面向对象进阶知识笔记

news2025/3/15 22:47:42

类方法、静态方法

1. 类方法

  • 第一个形参是类对象的方法
  • 需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数。

class Dog(object):

    __type = "狗"

    # 类方法,用classmethod来进行修饰

    @classmethod

    def get_type(cls):

        return cls.__type

print(Dog.get_type())

使用场景:

  • 当方法中 需要使用类对象 (如访问私有类属性等)时,定义类方法
  • 类方法一般和类属性配合使用

2. 静态方法

  • 需要通过装饰器@staticmethod来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)
  • 静态方法 也能够通过 实例对象 和 类对象 去访问。

class Dog(object):

    type = "狗"

    def __init__(self):

        name = None

    # 静态方法   

    @staticmethod

    def introduce():  # 静态方法不会自动传递实例对象和类对象

        print("犬科哺乳动物,属于食肉目..")

dog1 = Dog()

Dog.introduce()    # 可以用 实例对象 来调用 静态方法

dog1.introduce()    # 可以用 类对象 来调用 静态方法

用场景:

  • 当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法
  • 取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗

注意点:

  • 类中定义了同名的方法时,调用方法会执行最后定义的方法

class Dog:

    def demo_method(self):

        print("对象方法")

    @classmethod

    def demo_method(cls):

        print("类方法")

    @staticmethod

    def demo_method():  # 被最后定义

        print("静态方法")

dog1 = Dog()

Dog.demo_method()  # 结果: 静态方法

dog1.demo_method()  # 结果: 静态方法

__new__和__init__方法

class A(object):

    def __init__(self):

        print("这是 init 方法")

    def __new__(cls):

        print("这是 new 方法")

        return object.__new__(cls)

A()

总结

  • __new__至少要有一个参数cls,代表要实例化的类,此参数在实例化时由Python解释器自动提供
  • __new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以return父类__new__出来的实例,或者直接是object的__new__出来的实例
  • __init__有一个参数self,就是这个__new__返回的实例,__init____new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值

# 实例化一个单例

class Singleton(object):

    __instance = None

    __is_first = True

    def __new__(cls, age, name):

        if not cls.__instance:

            cls.__instance = object.__new__(cls)

        return cls.__instance

    def __init__(self, age, name):

        if self. __is_first: # 不会再创建第二个对象

            self.age = age

            self.name = name

            Singleton. __is_first = False

a = Singleton(18, "张三")

b = Singleton(28, "张三")

print(id(a))

print(id(b))

print(a.age) # 18

print(b.age) # 18

a.age = 19

print(b.age)

继承的基本使用

在现实生活中,继承一般指的是子女继承父辈的财产,父辈有的财产,子女能够直接使用。

程序里的继承

继承是面向对象软件设计中的一个概念,与多态、封装共为面向对象的三个基本特征。继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。

  • 在程序中,继承描述的是多个类之间的所属关系。
  • 如果一个类A里面的属性和方法可以复用,则可以通过继承的方式,传递到类B里。
  • 那么类A就是基类,也叫做父类;类B就是派生类,也叫做子类。

class Animal:

    def __int__(self):

        pass

    """动物类"""

    def sleep(self):

        print('正在睡觉')

class Dog(Animal):

    """Dog类继承自Animal类"""

    def __init__(self):

        pass

class Cat(Animal):  # 定义类时,在括号后面传入父类的类名,表示子类继承父类

    """Cat类继承自Animal类"""

    def __int__(self):

        pass

# Dog 和 Cat 都继承自Animal类,可以直接使用Animal类里的sleep方法

dog = Dog()

dog.sleep()

cat = Cat()

cat.sleep()

在Python中,继承可以分为单继承、多继承和多层继承。

单继承:子类只继承一个父类

继承概念:子类用于父类的所有的方法和属性。

继承语法:

class 类名(父类名):
    pass
  • 子类继承自父类,可以享受父类中已经封装好的方法,不需要再次定义
  • 子类中应该根据职责,封装子类特有的属性和方法。

继承的传递性

Dog类继承自Animal,XiaoTianQuan又继承自Dog类,那么XiaoTianQuan类就具有了Animal类里的所有属性和方法。

子类拥有父类以及父类的父类中封装的所有属性和方法。

思考:

XiaoTianQuan能否调用Animal的run()方法? XiaoTianQUan能够调用Cat里的方法?

多继承

子类可以拥有多个父类,并且具有所有父类的属性和方法。

语法格式:

class 子类名(父类名1,父类名2...)
    pass

多继承的使用注意事项

思考:

如果不同的父类中存在同名的方法,子类对象在调用方法时,会调用哪个父类的方法? 说明:开发中,应该尽量避免这种容易产生混淆的情况。如果多个父类之间存在同名的属性后者方法,应该尽量避免使用多继承。

Python中的MRO

  • Python中针对类提供了一个内置属性__mro__可以用来查看方法的搜索顺序。
  • MRO method resolution order的简称,主要用于在多继承时判断方法属性的调用顺序。
print(C.__mro__)

输出结果:

(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
  • 在调用方法时,按照__mro__的输出结果从左至右的顺序查找。
  • 如果再当前类中找到方法,就直接执行,不再向下搜索。
  • 如果没有找到,就顺序查找下一个类中是否有对应的方法,如果找到,就直接执行,不再继续向下搜索。
  • 如果找到了最后一个类,依然没有找到方法,程序就会报错。

新式类和旧式(经典)类

object是Python中所有对象的基类,提供了一些内置的属性和方法,可以时候用dir函数查看。

  • 新式类:以object为基类的类,推荐使用
  • 经典类:不以object为基类的类,不推荐使用
  • 在 Python3.x 以后定义类时,如果没有指定父类,这个类会默认继承自 object,所以,python3.x版本定义的类都是新式类。
  • 在Python2.x中定义类时,如果没有指定父类,则不会继承自object.

为了保证代码在Python2.x和Python3.x中都能够运行,在定义类时,如果一个类没有父类,建议统一继承自'object'

class 类名(object):
    pass

对象相关的内置函数

Python中的身份运算符用来判断两个对象是否相等;isinstance用来判断对象和类之间的关系;issublcass用啊里判断类与类之间的关系。

身份运算符

身份运算符用来比较两个对象的内存地址,看这两个对象是否是同一个对象。

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
 
p1 = Person('张三', 18)
p2 = Person('张三', 18)
p3 = p1
 
print(p1 is p2)  # False
print(p1 is p3)  # True

isinstance

instance内置函数,用来判断一个实例对象是否是由某一个类(或者它的子类)实例化创建出来的。

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
class Student(Person):
    def __init__(self, name, age, score):
        super(Student, self).__init__(name, age)
        self.score = score
 
class Dog(object):
    def __init__(self, name, color):
        self.name = name
        self.color = color
 
 
p = Person('tony', 18)
s = Student('jack', 20, 90)
d = Dog('旺财', '白色')
 
print(isinstance(p, Person))  # True.对象p是由Person类创建出来的
print(isinstance(s, Person))  # True.对象s是有Person类的子类创建出来的
print(isinstance(d, Person))  # False.对象d和Person类没有关系

issubclass

issubclass 用来判断两个类之间的继承关系。

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
class Student(Person):
    def __init__(self, name, age, score):
        super(Student, self).__init__(name, age)
        self.score = score
 
class Dog(object):
    def __init__(self, name, color):
        self.name = name
        self.color = color
 
 
print(issubclass(Student, Person))  # True
print(issubclass(Dog, Person))  # False

多态

面向对象的三大特性:

  • 封装:这是定义类的准则,根据对象的特点,将行为和属性抽象出来,封装到一个类中。
  • 继承:这是设计类的技巧。父类与子类,主要体现在代码的重用,不需要大量的编写重复代码。
  • 多态:不同的子类调用相同的父类方法,产生不同的执行结果,可以增加代码的外部灵活度。多态是以继承和重写父类方法为前提的,它是一种调用方法的技巧,不会影响到类的内部设计。

场景

  • 提供三个类:缉毒犬、军犬、人
  • 缉毒犬-->追查毒品,军犬-->攻击假人,人-->让小狗干活
  • 设计类来完成功能。

代码实现:

class ArmyDog(object):
 
    def bite_enemy(self):
        print('追击敌人')
class DrugDog(object):
 
    def track_drug(self):
        print('追查毒品')
class Person(object):
 
    def work_with_army(self, dog):
        dog.bite_enemy()
 
    def work_with_drug(self, dog):
        dog.track_drug()
 
ad = ArmyDog()
dd = DrugDog()
 
p = Person()
p.work_with_army(ad)
p.work_with_drug(dd)

思考:这段代码设是否有问题?

新增需求:此时,又多了一个犬种,就又需要在Person类里新建一个方法,让这个方法操作新的狗。

class XiaoTianDog(object):
 
    def eat_moon(self):
        print('哮天犬把月亮吃了')
class Person(object):
 
    def work_with_xiaotian(self, dog):  # 添加方法
        dog.eat_moon()

Person 类总是不断的添加新的功能,每次都需要改动Person类的源码,程序的扩展性太差了!

  • 最好是提供一个父类 Dog,具备 work 的功能,其他小狗继承它,这样只要是小狗类,则行为被统一起来了,我们人类完全可以保证,只要是小狗的子类,找它干活肯定不会有问题。
  • 这样人只要一个方法就能逗任意种类的狗玩,哪怕是添加新的狗,人的类都不需要修改。
  • 图示如下:

代码实现:

class Dog(object):
 
    def work(self):  # 父类提供统一的方法,哪怕是空方法
        pass
class ArmyDog(Dog):   # 继承 Dog
 
    def work(self):  # 子类重写方法,并且处理自己的行为
        print('追击敌人')
class DrugDog(Dog):
 
    def work(self):
        print('追查毒品')
class Person(object):
 
    def work_with_dog(self, dog):
        dog.work()    # 使用小狗可以根据对象的不同而产生不同的运行效果, 保障了代码的稳定性
# 子类对象可以当作父类来使用
dog = Dog()
ad = ArmyDog()
dd = DrugDog()
 
 
p = Person()
p.work_with_dog(dog)
p.work_with_dog(ad)  # 同一个方法,只要是 Dog 的子类就可以传递,提供了代码的灵活性
p.work_with_dog(dd)  # 并且传递不同对象,最终 work_with_dog 产生了不同的执行效果
  • 最终效果
    • Person 类中只需要调用 Dog 对象 work() 方法,而不关心具体是 什么狗
    • work() 方法是在 Dog 父类中定义的,子类重写并处理不同方式的实现
    • 在程序执行时,传入不同的 Dog 对象作为实参,就会产生不同的执行效果

多态总结

  • 定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
  • 好处:调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化!
  • 实现步骤:
    • 定义父类,并提供公共方法
    • 定义子类,并重写父类方法
    • 传递子类对象给调用者,可以看到不同子类执行效果不同

 

 

 

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

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

相关文章

数据结构中公式前中后缀表达式-二叉树应用

目录 数据结构中公式前中后缀表达式-二叉树应用 数据结构中公式前中后缀表达式-二叉树应用 什么是前缀表达式、中缀表达式、后缀表达式 前缀表达式、中缀表达式、后缀表达式&#xff0c;是通过树来存储和计算表达式的三种不同方式 以如下公式为例 通过树来存储该公式&#x…

Avalonia 11 WebAssembly中文乱码

文章目录 0x00 原因0x01 解决方法FontForge 0x02 使用自定义字体App.axaml控件使用效果 0x00 原因 新建的Avalonia 11 WebAssembly项目&#xff0c;直接运行的话&#xff0c;会发现中文都是乱码&#xff0c;并且直接在控件上修改FontFamily属性是无法生效的。 0x01 解决方法…

MySQL学习笔记 - 进阶部分

MySQL进阶部分 字符集的相关操作&#xff1a;字符集和比较规则&#xff1a;utf8与utf8mb4&#xff1a;比较规则&#xff1a;常见的字符集和对应的Maxlen&#xff1a; Centos7中linux下配置字符集&#xff1a;各个级别的字符集&#xff1a;执行show variables like %character%语…

matlab画图中多个图例分开绘制

在matlab绘图中&#xff0c;线条较多时导致图例较长回遮挡原图/将图例分类&#xff0c;解决方案将图例分为多个。 一、多个图例一起显示 r 10; a 0; b 0; t0:0.1:2.1*pi; xar*cos(t); ybr*sin(t); plot(x,y,r,linewidth,4);hold on axis equal plot([0 0],[1 10],b,linewi…

双碳目标下基于“遥感+”多技术融合在碳储量、碳排放、碳循环、温室气体等领域应用教程

详情点击链接&#xff1a;双碳目标下基于“遥感”多技术融合在碳储量、碳排放、碳循环、温室气体等领域应用教程 一&#xff1a;双碳视角下遥感技术的研究方向 1.双碳背景及遥感的现实需求 2.全球碳库、碳收支及碳循环现状 3.碳储量、碳收支与碳循环中的遥感技术 4.ENVI及ArcG…

海龟绘图——n个正方形组成的图案

运行结果&#xff1a; 代码&#xff1a; import turtle# 创建海龟对象 nint(input()) t turtle.Turtle()# 设置海龟的颜色和线条粗细 t.color(blue) t.pensize(3)# 画四条直线lengths10 for j in range(n):for i in range(4):lengths20t.forward(lengths)# 旋转90度t.left(90)…

数据治理:打造可信赖的BI环境

章节一&#xff1a;引言 随着信息时代的不断发展&#xff0c;数据已经成为企业决策的重要支撑。而在大数据时代&#xff0c;海量的数据需要被整理、分析&#xff0c;以便为企业提供正确的指导。商业智能&#xff08;BI&#xff09;系统的兴起为企业提供了强大的数据分析能力&am…

利用Lifecycle,管理一个计时器生命周期

Lifecycle是Android Jetpack中的一个组件&#xff0c;用于管理Android应用程序组件&#xff08;如Activity或Fragment&#xff09;的生命周期。它可以帮助开发者在不同的生命周期阶段执行特定的操作&#xff0c;以便更好地管理资源、处理数据和提供用户体验。 Lifecycle作用 …

Python程序设计——对象和类

学习目标 描述对象和类&#xff0c;以及使用类来建模对象定义带数据域和方法的类使用构造方法调用初始化程序来创建和初始化数据域以构建一个对象使用圆点运算符(.)访问对象成员使用self参数引用对象本身使用UML图符号来描述类和对象区分不可变对象和可变对象隐藏数据域以避免数…

应届生运维简历攻略

导语&#xff1a; 当下&#xff0c;计算机科学与技术已经成为一个炙手可热的行业&#xff0c;而作为这个行业中的一份子&#xff0c;运维人员的角色无疑至关重要。如果你是一位即将毕业的应届生&#xff0c;并希望在运维领域打拼&#xff0c;那么一份出色的运维简历将是你踏入…

PS常用快捷按键

1、Ctrl J 键复制&#xff08;快速复制图层&#xff0c;作为备份&#xff09;&#xff1b; 2、快速选择对象&#xff0c;进行移动ctrl 右键 3、放大ctrl 缩小ctrl 4、对同一个图片的多个不同颜色的图片进行截取的时候&#xff0c;注意每次都用同一个切图框&#xff0c;截图保…

【C++】stack容器

1.stack基本概念 英stk 美stk n.&#xff08;整齐的&#xff09;一堆&#xff1b;<英> 垛&#xff0c;堆&#xff1b;大量&#xff0c;许多&#xff1b;&#xff08;尤指工厂的&#xff09;大烟囱&#xff1b;&#xff08;图书馆的&#xff09;藏书架&#xff0c;双面书架…

Redis实现共享Session

Redis实现共享Session 分布式系统中&#xff0c;sessiong共享有很多的解决方案&#xff0c;其中托管到缓存中应该是最常用的方案之一。 1、引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM…

Linux:shell脚本 正则表达式与AWK

一、正则表达式 由一类特殊字符及文本字符所编写的模式&#xff0c;其中有些字符&#xff08;元字符&#xff09;不表示字符字面意义&#xff0c;而表示控制或通配的功能&#xff0c;类似于增强版的通配符功能&#xff0c;但与通配符不同&#xff0c;通配符功能是用来处理文件…

C语言入门 Day_3 整数和变量

目录 1.整型 2.变量 3.易错点 4.思维导图 前言&#xff1a; 昨天的课程里面&#xff0c;我们学会了使用printf()打印一行字母&#xff0c;比如 printf("Hello World!\n"); 那么编程中用来表示&#xfeff;数字的是什么类型呢&#xff1f; 接下来我们学习一下…

实战指南,SpringBoot + Mybatis 如何对接多数据源

系列文章目录 MyBatis缓存原理 Mybatis plugin 的使用及原理 MyBatisSpringboot 启动到SQL执行全流程 数据库操作不再困难&#xff0c;MyBatis动态Sql标签解析 从零开始&#xff0c;手把手教你搭建Spring Boot后台工程并说明 Spring框架与SpringBoot的关联与区别 Spring监听器…

国内外医疗器械政策法规网站集合

随着医疗技术的不断发展&#xff0c;医疗器械在现代医疗中扮演着重要的角色。为了确保医疗器械的安全性、有效性和质量&#xff0c;各国纷纷制定了一系列的政策法规来监管医疗器械的研发、生产、销售和使用。这些政策法规的制定和实施对于保障公众健康、促进医疗器械产业的健康…

报错解决:matlab机器人工具箱不支持将脚本 DHFactor 作为函数执行

matlab使用机器人工具箱出现报错&#xff1a; 不支持将脚本 DHFactor 作为函数执行: D:\MATLAB\install\toolbox\rvctools\robot\DHFactor.m 解决办法&#xff1a;重新到上图的rvctool重重新安装一下工具箱就好了。 到目录"$机器人工具箱路径$\rvctools" 在matlab命…

数据结构基础

将节点构建成树 数据的结构逻辑结构集合线性结构树形结构图状结构 存储结构合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如…

CXL registers

目录 DVSEC CXL PCIe DVSEC for CXL Device//ID 0 DVSEC CXL Capability (Offset 0Ah) DVSEC CXL Control (Offset 0Ch) DVSEC CXL Status (Offset 0Eh) DVSEC CXL Control2 (Offset 10h) DVSEC CXL Status2 (Offset 12h) DVSEC CXL Lock (Offset 14h) DVSEC CXL Capabilit…