24. 面向对象的思想

news2024/11/27 12:32:33

1. 面向对象

类似于c++/c#/java等高级语言,python从设计之初就已经是一门面向对象的语言,正因为如此,在python中创建一个类和对象是很容易的。关于面向对象的思想及基础,此处不再赘述。

2. 类对象

(1) 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。有的书本也称之为类属性
类属性引用使用和 python 中所有的属性引用一样的标准语法:实例对象.name类名.name


# 创建一个类
class student:
    num = 101

    def test(self):
        print('HelloWorld.')


s = student()  	# 实例化类
print(s.num)	# 引用类属性(通过实例化对象) 
print(student.num)	# 引用类属性(通过类名)
s.test()		# 引用类的方法

在这里插入图片描述


类变量在整个实例化的对象中是公用的,怎么理解???

# 相信看了此demo, 就明白了.
class Animal:
    age = 12

    def setAge(self, Age):
        self.age = Age

    def show(self):
        print("age is:>", self.age)


Animal().show()

a = Animal()
a.setAge(13)
a.show()
a.setAge(14)
a.show()
a.show()
print(Animal.age)

(2) 实例变量 在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量 有的书本也称之为类属性

# self.num, self.name就是实例变量
class Animal:
    def __init__(self, num, name):
        self.num = num
        self.name = name

    def show(self):
        print(self.num, self.name)


Animal(101, 'Cat').show()
# 101 Cat

3. 构造函数__init__()

类有一个名为 __init__() 的特殊方法(构造函数),该方法在类实例化时会自动调用。

class student:
    def __init__(self):
        print("实例化类时将调用类的构造函数.")

student()	# 实例化类时将自动调用类的构造函数

在这里插入图片描述

3. 类的属性

(1) 类的公有属性
可以在任何地方被类对象所调用

class animal:
    num = 101

print(animal().num)

(2) 类的私有属性
__attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问只能在类内部进行调用(self.__attrs)

class animal:
    __num = 101

    def test(self):
        print(self.__num)
        self.__print()

    def __print(self):
        print(self.__num)

animal().test()

在这里插入图片描述


print(animal().__num)	# 错误

在这里插入图片描述

4. 类的普通方法

(0) 默认有个self参数,且只能被对象调用。
(1) 在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self, 且为第一个参数,self 代表的是类的实例。(static函数除外, c++中的static函数中也不能出现this)
self实际上就是实例对象本身, 该参数名一般约定为self.(相当于c++/c#/java当中的this)
通过它来传递实例的属性和方法.(也可以传类的属性和方法)
(2) 调用形式:实例对象.普通函数()
(3) 类的公有方法
可以在任何地方被对象调用

# 类方法的必须有一个额外参数, 约定为self
# test()就是一个类方法, 并且是public类型的, 可以在任何地方被对象调用
class animal:
    def test(self):
        print('HelloWorld.')

animal().test()

在这里插入图片描述
(4) 类的私有方法
__method两个下划线开头,声明该方法为私有方法,只能在类的内部调用(self.__method()),不能在类的外部调用

class animal:
    def __printInfo(self):
        print('这是私有方法, 只能在类的内部被调用.')
    def test(self):
        self.__printInfo()

animal().test()			
# animal().__printInfo() # 错误

(5) 类的专有方法
__init__:构造函数,在生成对象时调用
__del__:析构函数,释放对象时使用
__repr__:打印,转换
__setitem__:按照索引赋值
__getitem__:按照索引获取值
__len__:按照索引获取值
__cmp__:比较运算
__call__:函数调用
__add__:加运算
__sub__:减运算
__mul__:乘运算
__truediv:除运算
__mod__:求余运算
__pow__:乘方

5. 类的静态方法

(1) 可用staticmethod()将类方法包装成静态函数;
(2) 也可以用@staticmethod装饰器定义一个 静态函数;
(3) static函数与一般方法不同,不包含参数self
(4) static函数中不能出现self,就好比C++中的static函数中不能出现this一样;

(5) static函数的调用:类名.静态函数() 或者 实例对象.静态函数()

class StaticClass:
    def call():
        print('call static method1 <call()>.')

    # 将call()包装成静态函数
    call = staticmethod(call)

	# 使用@staticmethod定义静态函数
    @staticmethod
    def say():
        print('call static method2 <say()>.')

# 通过实例对象访问静态函数
StaticClass().call()
StaticClass.say()

# 通过类名访问静态函数
StaticClass.call()
StaticClass.say()

在这里插入图片描述

6. 类方法

(1) 默认有个 cls 参数,可以被类和对象调用,需要加上 @classmethod 装饰器函数的第一个参数表示类本身且该参数一般约定为cls, 通过它来传递类的属性和方法(不能传实例的属性和方法)
(2) 调用方法:实例.类方法()类名.类方法()

# demo1
class ClassMethod:
    @classmethod
    def test(cls):
        print('调用类方法.')

ClassMethod().test()	# 通过实例调用类方法
ClassMethod.test()		# 通过类名调用类方法 
# demo2:cls的使用
class Student:
    addr = "SuZhou"

    @classmethod
    def ClassMethod(cls):
        print('call classMethod.')

    # 类方法中调用类属性 和 类方法(通过类名)
    @classmethod
    def ClassMethodExtend(cls):
        Student.addr = "JiangSu"
        print(Student.addr)
        Student.ClassMethod()
        print("call ClassMethodExtend.")

    # 类方法中调用类属性 和 类方法(通过参数cls)
    @classmethod
    def ClassMethodExtendEx(cls):
        cls.addr = "ZhongGuo"
        print('cls.addr:> ', cls.addr)
        cls.ClassMethod()


Student.ClassMethodExtend()
Student.ClassMethodExtendEx()
print(Student.addr)

在这里插入图片描述

7. 类的静态方法和类方法异同

类方法 和 静态方法 都可以通过类名和实例进行调用。
类方法 和 静态方法 都是属于类级方法。
[a]. 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。有的书本也称作类属性
[b]. 实例变量:在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用self修饰的变量有的书本也称为实例属性
[c]. 实例方法:就是类的普通方法。
(1) 类方法
  a. 类方法中只能使用 类属性和类方法,不能使用实例属性和实例方法(普通方法),因为不具备self
  b. 类方法中也可以调用 静态方法;
(2) 静态方法
  a. 实例属性和实例方法都不能使用(因为不具备self),但是可以类属性和类方法;

8. 单继承

python 同样支持类的继承,如果一种语言不支持继承,类就没有什么意义。
派生类的定义格式:

class DerivedClassName(BaseClassName):
    <statement-1>
    .
    .
    .
    <statement-N>

子类(派生类 DerivedClassName)会继承父类(基类 BaseClassName)的属性和方法。
BaseClassName(实例中的基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用:

class DerivedClassName(modname.BaseClassName):
# 基类
class People:
    __weight = 0

    def __hello(self):
        print('HelloWorld')

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

    def speak(self):
        print("[father] %s say:> i am %d years old." % (self.name, self.age))


# 派生类
class Student(People):

    def __init__(self, name, age, weight, grade):
        # 调用父类的构造函数
        People.__init__(self, name, age, weight)
        # 初始化实例变量
        self.grade = grade

    # 覆盖父类的方法
    def speak(self):
        print("[son] %s say:> i am %d years old and i am in %d grade." % (self.name, self.age, self.grade))

    # 父类的私有属性和私有方法不会被继承
    def test(self):
        print(self.weight)
        self.__hello()
Student('Ken', 30, 60, 6).speak()
Student('Tom', 10, 10, 4).test()    # 错误

在这里插入图片描述

9. 多继承

python同样有限的支持多继承形式。
多继承的类定义格式

class DerivedClassName(Base1, Base2, Base3):
    <statement-1>
    .
    .
    .
    <statement-N>

需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索,即方法在子类中未找到时,从左到右依次查找父类中是否包含方法。

class Father:
    def __init__(self, ear, eye):
        self.ear = ear
        self.eye = eye

    def test(self):
        print('test() in father.')


class Mother:
    def __init__(self, hair, sing):
        self.hair = hair
        self.sing = sing

    def test(self):
        print('test() in mother.')


class Son(Father, Mother):
    def __init__(self, ear, eye, hair, sing, eat):
        # 调用父类的构造函数
        Father.__init__(self, ear, eye)
        # 调用基类的构造函数
        Mother.__init__(self, hair, sing)
        # 初始化实例变量
        self.eat = eat

    def show(self):
        print(self.ear, self.eye, self.hair, self.sing, self.eat)

    def test(self):
        print('test() in son.')


s = Son('Big-ear', 'little-eye', 'black-hair', 'good-sing', 'eat-pig')
s.show()
s.test()  # test(), 如果子类中不存在此方法, 那么python将会从左至右查找其基类中是否包含此方法

在这里插入图片描述

10. 方法重写

如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法

class Parent(object):
    def __init__(self):
        self.parent = 'I am parent.'

    def bar(self, message):
        print("%s from Parent." % message)


class Child(Parent):
    def __init__(self):
        super(Child, self).__init__()

    # 重写(覆盖)基类的方法
    def bar(self, message):
        print("%s from Son." % message)


child = Child()
child.bar('HelloWorld~~~')

在这里插入图片描述

11. 运算符重载

python同样支持运算符重载,我们可以对类的专有方法进行重载。

class Vector:
    def __init__(self, aa, bb):
        self.a = aa
        self.b = bb
	
	# 对类的专有方法__str__进行重载
    def __str__(self):
        return 'Vector(%d, %d).' % (self.a, self.b)

	# 对类的专有方法__add__进行
    def __add__(self, other):
        return Vector(self.a + other.a, self.b + other.b)


v1 = Vector(2, 10)
v2 = Vector(5, -2)
print(v1 + v2)

12. super()函数

super() 函数是用于调用父类(超类)的一个方法
super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
格式:

super(type[, object-or-type])
  type:类。
  object-or-type:类, 一般是self。
  Python3.x 和 Python2.x 的一个区别是: python3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx。
# 1. python3写法
class A:
    def __init__(self):
        pass

    def add(self, x):
        print(x ** 3)

    def test(self):
        print('I am father.')


class B(A):
    def __init__(self):
        super().__init__()

    def add(self, x):
        super().add(x)  # 调用父类的add()


B().add(2)  # 8
# 2. python2写法
class A(object):  # python2.x记得继承object
    def add(self, x):
        print(x + 1)


class B(A):
    def add(self, x):
        super(B, self).add(x)


B().add(9)  # 10

# 3. demo
class Parent(object):
    def __init__(self):
        self.parent = 'I am parent.'

    def bar(self, message):
        print("%s from Parent." % message)

class Child(Parent):
    def __init__(self):
        super(Child, self).__init__()

    def bar(self, message):
        super(Child, self).bar(message)     # 调用基类的bar()函数
        print("%s from Son." % message)


child = Child()
super(Child, child).bar('HelloWorld@@@')     # 调用基类的bar()函数

在这里插入图片描述

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

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

相关文章

计算机毕业设计选题推荐基于nodejs+Vue360学生宿舍系统

管理员&#xff1b;首页、个人中心、宿舍信息管理、学生管理、宿舍报修管理、访客信息管理、水电费管理、管理员管理、交流论坛、系统管理&#xff0c;学生&#xff1b;首页、个人中心、宿舍报修管理、水电费管理&#xff0c; 前台首页&#xff1b;首页、交流论坛、通知公告、个…

STM32之HAL源码阅读(GPIO章节)

前言 说明 本文只针对于软件层面的阅读&#xff0c;详细操作请查阅对应的手册,使用过标准库的朋友更好的能理解本文针对的是STM32F10x系列&#xff0c;其他的类似 参考资料 STM32F10x中文参考手册 工具 stm32cubemx6.5clion最新版 HAL源码之GPIO的阅读 步骤一&#xff…

Cesium:Indexed 3D Scene Layers (I3S)加载

点击此处,查看完整的OGC标准列表项。Indexed 3D Scene Layers(I3S)标准官网介绍地址为:I3S,相关的GitHub主页地址为:Esri/i3s-spec,其详细介绍文档地址可点击此处查阅。我们的核心点在于介绍如何通过Cesium.js开发框架加载I3S三维场景服务。 目录 Cesium.js:I3S支持情…

JUC面试(九)——Synchronized和Lock的区别

Synchronized和Lock的区别 前言 对象锁&#xff08;synchronized method{}&#xff09;和类锁&#xff08;static sychronized method{}的区别 对象锁也叫实例锁&#xff0c;对应synchronized关键字&#xff0c;当多个线程访问多个实例时&#xff0c;它们互不干扰&#xff0…

基于蜣螂优化的BP神经网络(分类应用) - 附代码

基于蜣螂优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录基于蜣螂优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.蜣螂优化BP神经网络3.1 BP神经网络参数设置3.2 蜣螂算法应用4.测试结果&#xff1a;5.Mat…

Ubuntu16.04安装N卡驱动

最近碰到个实验&#xff0c;需要用pytorch0.4和python2.7的环境&#xff0c;因为环境比较老&#xff0c;所以新显卡可能不能装。紧急联系朋友搞了张1660ti想来跑实验&#xff0c;结果光是驱动就碰了一鼻子灰&#xff0c;这里简单做下总结&#xff0c;引以为戒。首先是系统版本&…

Python for循环及用法详解

Python 中的循环语句有 2 种&#xff0c;分别是 while 循环和 for 循环&#xff0c;前面章节已经对 while 做了详细的讲解&#xff0c;本节给大家介绍 for 循环&#xff0c;它常用于遍历字符串、列表、元组、字典、集合等序列类型&#xff0c;逐个获取序列中的各个元素。for 循…

ARP渗透与攻防(五)之Ettercap劫持用户流量

ARP-Ettercap劫持用户流量 系列文章 ARP渗透与攻防(一)之ARP原理 ARP渗透与攻防(二)之断网攻击 ARP渗透与攻防(三)之流量分析 ARP渗透与攻防(四)之WireShark截获用户数据 一.ettercap 工具介绍 项目官网&#xff1a;http://ettercap.github.io/ettercap/index.html EtterC…

(十五)ForkJoin框架

ForkJoinPoolForkJoinPool是一种“分治算法”的多线程并行计算框架&#xff0c;自Java7引入。它将一个大的任务分为若干个子任务&#xff0c;这些子任务分别计算&#xff0c;然后合并出最终结果。ForkJoinPool比普通的线程池可以更好地实现计算的负载均衡&#xff0c;提高资源利…

安装MikTeX-latex

安装MikTeX-latex一、报错信息二、重新安装三、编译MDPI Template一、报错信息 由于之前使用的是basic-miktex-2.9.7269-x64.exe这个版本&#xff0c;当安装完成后&#xff0c;在更新package时遇到了以下错误&#xff1a; MikTeX update error 于是&#xff0c;通过搜索&…

冯·诺依曼、哈佛、改进型哈佛体系结构解析

在如今的CPU中&#xff0c;由于Catch的存在&#xff0c;这些概念已经被模糊了。个人认为去区分他们并没有什么意义&#xff0c;仅作为知识点。 哈佛结构设计复杂&#xff0c;但效率高。冯诺依曼结构则比较简单&#xff0c;但也比较慢。CPU厂商为了提高处理速度&#xff0c;在C…

2023 年程序员的热门开发项目:掌握最新技术的教程和工具的完整列表

欢迎阅读我们关于“2023 年程序员的热门开发项目”的博文&#xff01;作为一名开发人员&#xff0c;了解最新的技术和工具对于在就业市场上保持竞争力至关重要。在这篇文章中&#xff0c;我们编制了一份 2023 年最热门开发项目的完整列表&#xff0c;以及掌握每个项目的教程和资…

ChatGPT付费版来啦,好用的AI生成产品还能免费使用吗?AIGC工具箱

​最新消息&#xff0c;chatGPT推出了付费版&#xff01;每月&#xff04;42美元&#xff0c;不限流使用&#xff0c;你会付费使用吗&#xff1f;&#x1f9f0;AIGC工具箱下面推荐几款AI 生成产品&#xff01;你觉得哪个更好用呢&#xff1f;AI 的出现&#xff0c;颠覆了内容生…

自己动手写一个操作系统——我们能做什么,我们需要做什么

文章目录计算机启动流程第一条指令BIOSMBRloaderkernel总结计算机启动流程 第一条指令 在开机的一瞬间&#xff0c;也就是上电的一瞬间&#xff0c;CPU 的 CS:IP 寄存器被硬件强制初始化为 0xF000:0xFFF0。 CS:IP 就是 PC 指针&#xff0c;也就是 CPU 下一条要执行的指令的地址…

Elasticsearch7.8.0版本入门—— Elasticsearch7.8.0映射操作

目录一、映射的概述二、创建映射的示例2.1、首先&#xff0c;创建索引2.2、然后&#xff0c;再创建好的索引基础上&#xff0c;创建映射2.3、映射属性说明2.4、查看创建的映射2.5、最后&#xff0c;创建文档2.6、根据文档中name属性条件查询文档 理解映射示例2.7、根据文档中se…

HDM KVM维护

前言 服务器遇到个问题&#xff0c;无法启动&#xff0c;下面简单记录一下解决程 方法 进入维护界面&#xff1a; 尝试 H5 KVM&#xff0c;发现H5 kvm挂载镜像速度较慢 使用 KVM.jnlp&#xff0c;需配置 java 环境&#xff0c;安装好java 环境已经配置java 环境变量后&…

Linux常见命令 18 - 用户管理命令 useradd, passwd, who, w

目录 1. 添加用户命令 useradd 2. 设置用户密码 passwd 3. 查看用户登录信息 who 4. 查看用户登录详细信息 w 1. 添加用户命令 useradd 语法&#xff1a;useradd [用户名] 2. 设置用户密码 passwd 语法&#xff1a;passwd [用户名] 注意&#xff1a;每个用户只能用passwd更改自…

作为项目经理,如何做好项目进度管理

一、项目进度管理需要做什么&#xff1f; 项目进度管理分9步&#xff1a;其中前⑥条属于规划过程组的工作内容&#xff0c;第⑦条属于监控过程组的工作内容。 ①规划进度管理&#xff1a;在文档内计划如何做好进度管理 ②定义活动&#xff1a;识别和记录项目中的活动 ③排列活动…

数据库系统概念 | 第六章:形式化关系查询语言 | 含带答案习题

文章目录&#x1f4da;关系代数&#x1f407;基本运算&#x1f955;选择运算&#x1f955;投影运算&#x1f955;关系运算的组合&#x1f955;集合并运算&#x1f955;集合差运算&#x1f955;集合交运算&#x1f955;笛卡尔积运算&#x1f955;更名运算&#x1f955;一道综合例…

量子力学奇妙之旅-微扰论和变分法

专栏目录: 高质量文章导航 一.基本概念 前置: 厄密算符和简并: 两大重要结论: 厄米算符的本征值一定是实数 厄米算符不同本征值的本征态一定正交 证明: 我们 λ<