Python面向对象编程(一)类的基础,关系,继承,封装,多态

news2024/11/24 6:24:07

类的一些理论概念及其应用场景等基础内容此处不赘述

目录

类的定义及基础

属性

方法

初始化方法

 普通方法

类之间的关系

相互调用

依赖关系

关联关系

组合关系

三大特征----类的继承

重写父类方法

多继承

三大特征----封装

三大特征----多态


类的定义及基础

类的一般定义:

class Name_of_Class:
    Shared_property=1
    def __init__(self):
        private_property=2
    def method(self):
        print(1)

类里包含了属性方法

属性

属性分为公共属性实例属性,上面的shared_property就是共有属性,private_property就是实例属性,区别在于:

公有属性是放在原始类的内存中的,如果发生改变,所有对象都会发生改变

私有属性是放在对象内存中的,如果改变只会改变该对象的值,是对象独享的

举个例子

class Name_of_Class:
    Shared_property=1
    def __init__(self):
        self.object_property=2

obj1=Name_of_Class()
obj2=Name_of_Class()

Name_of_Class.Shared_property=111

print(obj1.Shared_property)
print(obj2.Shared_property)

obj1.object_property=3
print(obj2.object_property)
# 111
# 111
# 2

那比如要设置一个  某个年级学生信息的类,就可以把 年级 作为公共属性,把一些身高体重等作为实例属性

但是如果对象把类的公共属性给改了,就相当于给对象创建了一个新的实例有属性

class Name_of_Class:
    Shared_property=1

obj1=Name_of_Class()
obj2=Name_of_Class()

obj1.Shared_property=111

print(obj1.Shared_property)
print(obj2.Shared_property)
# 111
# 1

方法

初始化方法

def __init__(self):
    pass

又叫做构造方法,构造函数,实例化的时候会自动运行

初始化方法可以设置参数,一般的格式是

class Name_of_Class:
    Shared_property=1
    def __init__(self,object_property1,object_property2):
        self.object_property1=object_property1
        self.object_property2=object_property2

调用方式是

obj1=Name_of_Class(2,3)
print(obj1.object_property1)
print(obj1.object_property2)
# 2
# 3

在进行实例化的时候直接传参就可以调用初始化方法

这里的self.object_property1=object_property1是确保将传进来的参数作为对象本身的实例属性保存起来,这里借用一张内存图说明

  1.  实例化时,申请一块内存空间
  2. 将实例化的参数传给__init__
  3. __init__将参数转为实例属性传给这个内存空间

 普通方法

class Name_of_Class:
    Shared_property=1
    def __init__(self,object_property1,object_property2):
        self.object_property1=object_property1
        self.object_property2=object_property2
    def method(self):
        print(self.object_property2+self.object_property1)

obj1=Name_of_Class(2,3)
obj1.method()
# 5

普通方法的参数同一有  self ,告知是哪个对象调用了方法

在普通方法中调用私有参数要  self.xxxx

类之间的关系

相互调用

只需要在定义类方法的时候将其他的对象作为参数传进去

class soilder:
    def __init__(self,name,m4):
        self.name=name
        self.m4=m4
        self.bloodall=100
    def attack_back(self,badperson):
        badperson.bloodall-=self.m4
        print('soilder [%s] attack badperson [%s],badperson has [%s] blood'%(self.name,badperson.name,badperson.bloodall))


class badperson:
    def __init__(self, name, ak):
        self.name = name
        self.ak = ak
        self.bloodall = 100

    def attack(self, soilder):
        soilder.bloodall -= self.ak
        print('badperson [%s] attack soilder [%s],soilder has [%s] blood'%(self.name,soilder.name,soilder.bloodall))


lee = soilder('lee',30)
liu =badperson('liu',35)

liu.attack(lee)
lee.attack_back(liu)

# badperson [liu] attack soilder [lee],soilder has [65] blood
# soilder [lee] attack badperson [liu],badperson has [70] blood


依赖关系

在依赖类的 初始化函数 中将master对象引入

class dog:
    def __init__(self,name,age,master):
        self.name=name
        self.age=age
        self.master=master
    def say(self):
        print('my master is ',self.master.name)

class master:
    def __init__(self, name, age):
        self.name = name
        self.age = age

p1 = master('lee',23)
d1=dog('hhh',2,p1)

d1.say()

关联关系

这个通过一个例子来说明这种关系,生活中最常见的这种关系是  结婚

结婚是两个人一起结婚的,所以在这里最好定义一个新的类relationship来存储两个人的婚姻关系,这样可以保证避免了A和B结婚了但是B和A没结婚的bug出现

如果结婚了就调用get_marred函数,如果离婚就是diverse函数,状态存储在couple数组里面

person类中调用这个relation类进行操作,并且可以通过get_partner函数获取自己的伴侣

class relationship:
    def __init__(self):
        self.couple=[]
    def get_married(self,obj1,obj2):
        self.couple=[obj1,obj2]
        print(obj1.name,'and ',obj2.name,'get married')
    def diverse(self):
        self.couple=[]


class person:
    def __init__(self,name,age,sex,relation):
        self.name=name
        self.age=age
        self.sex=sex
        self.relation=relation
    def get_partner(self):
        for i in self.relation.couple:
            if i.name==self.name:
                continue
            else:
                return i.name

relationship_obj=relationship()
p1=person('lee',23,'M',relationship_obj)
p2=person('liu',22,'F',relationship_obj)
relationship_obj.get_married(p1,p2)
print(p2.get_partner())
relationship_obj.diverse()
print(p1.get_partner())
# lee and  liu get married
# lee
# None

 

组合关系

由一堆组件构成一个整体,组件自己独立但是不能自己运行,必须跟宿主结合,例如人的器官和人的关系

这里定义了一个器官类,里面有不同器官的函数

在定义person类时,直接 self.action=organs(),既实例化一个器官对象,那么每次实例化一个person都会实例化一个organs,器官和人就是组合关系

class organs:
    def __init__(self):
        self.name=None
    def heart(self):
        self.name = '心脏'
        print('心脏跳动了一下')
    def lung(self):
        self.name='肺'
        print('肺呼吸了一下')

class person:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
        self.action=organs()
    def get_partner(self):
        for i in self.relation.couple:
            if i.name==self.name:
                continue
            else:
                return i.name


p1=person('lee',23,'M')
p2=person('liu',22,'F')

p1.action.heart()
p1.action.lung()
# 心脏跳动了一下
# 肺呼吸了一下

三大特征----类的继承

类的继承是三大特征之一,主要的功能是使类A能得到类B的所有方法和属性而不需要重复书写代码,继承的方式就是在定义的时候加入父类的名字:

class son(father):
    pass

例如猪和人都是动物,那么可以抽象一个animal类,把动物该有的属性和方法加入,当然新定义的类也可以加入自己独有的方法,或者重构 原有父类的方法:

class animal:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    def eat(self):
        print(111)


class pig(animal):
    pass

class person(animal):
    def eat(self):
        print(333)
    def thinking(self):
        print(222)


p1 = pig('liu',2,'M')
p2 = person('lee',23,'F')

p1.eat()
p2.thinking()
p2.eat()

# 111
# 222
# 333

重写父类方法

新定义的类也可以在原有类的基础上增加功能,而不完全重构

下面的代码在person继承了animal类,并且增加了初始化函数和普通方法的功能,主要思想就是在定义新的类的方法使,先运行父类的方法

class animal:
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    def eat(self):
        print(111)

class person(animal):
    def __init__(self,name,age,sex,hobby):
        animal.__init__(self,name,age,sex)
        self.hobby=hobby

    def eat(self):
        animal.eat(self)
        print(333)
    def thinking(self):
        print(222)


p2 = person('lee',23,'F','study')
print(p2.hobby)

p2.eat()

# study
# 111
# 333

在高版本的python中,还支持这种写法,其实结果是一样的:

class person(animal):
    def __init__(self,name,age,sex,hobby):
        super(person,self).__init__(name,age,sex)
        # animal.__init__(self,name,age,sex)
        self.hobby=hobby    
    def eat(self):
        super(person, self).eat()
        print(333)
    def thinking(self):
        print(222)

或者

class person(animal):
    def __init__(self,name,age,sex,hobby):
        super().__init__(name,age,sex)
        # animal.__init__(self,name,age,sex)
        self.hobby=hobby
    def eat(self):
        super().eat()
        print(333)
    def thinking(self):
        print(222)

多继承

 python是允许多继承的,也就是可以同时继承多个父类

当父类也有父类时,就有一个树状结构,此时继承顺序就很重要,这里有一个简单的例子

例如下面这种情况,同时继承了两个类,按照从左到右的顺序继承

class father(grandpa):
    def test(self):
        print('father')

class mother:
    def test(self):
        print('mother')

class son(father,mother):
    pass

p1=son()
p1.test()
#fatehr

再例如,当father类没有test时,会搜索father的父辈grandpa:

class grandpa:
    def test(self):
        print('grandpa')

class father(grandpa):
    pass

class mother:
    def test(self):
        print('mother')

class son(father,mother):
    pass

p1=son()
p1.test()
#grandpa

到这里为止,都很像深度优先搜索,但是其实不是,而是运用了C3算法比如当fater和mather类都继承自grandpa时

class grandpa:
    def test(self):
        print('grandpa')

class father(grandpa):
    pass

class mother(grandpa):
    def test(self):
        print('mother')

class son(father,mother):
    pass

p1=son()
p1.test()
# mother

为了方便,可以直接查看类的继承顺序

print(son.mro())
#[<class '__main__.son'>, <class '__main__.father'>, <class '__main__.mother'>, <class #'__main__.grandpa'>, <class 'object'>]

至于C3算法,有兴趣的可以看看这个

Python 中多继承 C3-MRO 算法的剖析 - 知乎 

三大特征----封装

封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
要访问该类的代码和数据,必须通过严格的接口控制。
封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。
适当的封装可以让程式码更容易理解与维护,也加强了代码数据的安全性。

比如一个这样的例子,人在银行的财产只能通过一些方法改变,例如存钱和取钱,如果按照普通的定义:

class person_bank:
    def __init__(self,name):
        self.money=0

p1=person_bank('lee')
p1.money=100
print(p1.money)
# 100

这样其实是不安全的,因为外部谁都可以自由的修改money的值

 这里引入私有属性的概念,其实就是使得外部不能访问,但是在类里面是可以访问的,只需要在变量前加 __

class person_bank:
    def __init__(self,name):
        self.__money=0
    def get_money(self,num):
        self.__money=self.__money+num
    def check(self):
        print(self.__money)
p1=person_bank('lee')
p1.check()
p1.get_money(100)
p1.check()
# 0
# 100

那么将私有属性放入类方法中修改的这种模式就叫做封装

当然方法也可以变为私有方法

class person_bank:
    def __init__(self,name):
        self.__money=0
    def __interest(self):
        self.__money=self.__money+1
p1=person_bank('lee')
p1.__interest()
# 'person_bank' object has no attribute '__interest'

但是其实私有属性和方法也不是完全不能外部访问的,也可以用下面这种方法破解

也就是  实例名._类名+方法名

print(p1._person_bank__money)
p1._person_bank__interest()

三大特征----多态

有时一个对象会有多种表现形式,比如网站页面有个button按钮,这个button的设计可以不一样(单选框、多选框、圆角的点击按钮、直角的点击按钮等),尽管长的不一样,但它们都有一个共同调用方式,就是onClick()方法。我们直要在页面上一点击就会触发这个方法。点完后有的按钮会变成选中状态、有的会提交表单、有的甚至会弹窗。这种多个对象共用同一个接口,又表现的形态不一样的现象,就叫做多态( Polymorphism )。

通过统一接口实现多态:

其实就是封装一个函数,调用不同类的同名方法

class one:
    def test(self):
        print(1)

class two:
    def test(self):
        print(2)

def gettest(obj):
    obj.test()

a=one()
b=two()
gettest(a)
gettest(b)

通过抽象类实现多态

class num:
    def test(self):
        # 可以继承,但是必须自己定义一个新的
        raise NotImplementedError('自己定义')


class one(num):
    def test(self):
        print(1)

class two(num):
    def test(self):
        print(2)

a=one()
b=two()
objs=[a,b]

for i in objs:
    i.test()

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

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

相关文章

10 mysql tiny/small/medium/big int 的数据存储

前言 这里主要是 由于之前的一个 datetime 存储的时间 导致的问题的衍生出来的探究 探究的主要内容为 int 类类型的存储, 浮点类类型的存储, char 类类型的存储, blob 类类型的存储, enum/json/set/bit 类类型的存储 本文主要 的相关内容是 int 类类型的相关数据的存储 …

EI、Scopus双检索| 2023年第四届自动化、机械与设计工程国际会议

会议简介 Brief Introduction 2023年第四届自动化、机械与设计工程国际会议&#xff08;SAMDE 2023&#xff09; 会议时间&#xff1a;2023年12月8 -10日 召开地点&#xff1a;中国南京 大会官网&#xff1a;www.samde.org 机械设计制造及其自动化学科在国民经济中处于极其重要…

从渗透测试小白到网络安全大佬的成长之路

前言 最近看到很多的安全小白在询问如何去学习安全&#xff0c;如何去入手渗透测试等问题。突然有感而发&#xff0c;想起来自己当时从小白一步一步走向黑客大佬的成长之路。 随着因特网的发展和网络经济的兴起, 越来越多的企业将服务或交易平台放到了互联网上, 而且这些网络应…

es6解构用法

一: 解构数组 二&#xff1a;解构对象 一: 解构数组 原理&#xff1a;模式(结构匹配), 索引值相同的完成赋值 总结&#xff1a;位置对应 二&#xff1a;解构对象 原理&#xff1a;模式(结构匹配), 属性名相同的完成赋值 {}{} 对象结构赋值的应用 常用的就以上两种 &#…

【用unity实现100个游戏之7】从零开始制作一个仿杀戮尖塔卡牌回合制游戏

文章目录 前言素材资源开始一、UI框架二、挂载脚本三、事件监听&#xff0c;用于绑定按钮事件四、声音管理器五、excel转txt文本六、游戏配置七、用户信息表八、战斗管理器九、 敌人管理器十、玩家血量、能量、防御值、卡牌数十一、敌人血量 行动显示逻辑十二、UI提示效果实现十…

缓存技术(缓存穿透,缓存雪崩,缓存击穿)

大家好 , 我是苏麟 , 今天聊一聊缓存 . 这里需要一些Redis基础 (可以看相关文章等) 本文章资料来自于 : 黑马程序员 如果想要了解更详细的资料去黑马官网查看 前言:什么是缓存? 缓存,就是数据交换的 缓冲区 (称作Cache [ kʃ ] ),俗称的缓存就是缓冲区内的数据,是存贮数据的…

20230901工作心得:IDEA列操作lambda表达式加强版用法

今天是中小学开学时间&#xff0c;亦是9月的开始&#xff0c;继续努力。 今日收获较大的有四个地方&#xff0c;先说这四点。 1、IDEA列操作 使用场景&#xff1a;需要批量将Excel表格里的数据插入到数据库中&#xff0c;此时需要写大量的insert SQL语句。 比如像这样的&am…

MySQL - 函数

1.1 什么是函数&#xff1f; 要想实现上面的这些效果&#xff0c;就得借助于MySQL当中的内置函数。 函数&#xff1a;是指一段可以直接被另一段程序调用的程序或代码。 MySQL当中内置了很多的函数&#xff0c;根据其操作的数据类型&#xff0c;分为以下四类&#xff1a; 字符…

vue之若依字典的导入使用(不直接使用若依框架,只使用若依字典)

vue之若依字典的导入使用 若依官网&#xff1a;http://ruoyi.vip 若依演示地址&#xff1a;http://vue.ruoyi.vip 若依代码下载&#xff1a;https://gitee.com/y_project/RuoYi-Vue 以上地址是若依的相关地址&#xff0c;可以下载前后端分离版的若依前后端代码。 如果你不想直…

【附安装包】Multisim 14.0安装教程|电子电路

软件下载 软件&#xff1a;Multisim版本&#xff1a;14.0语言&#xff1a;简体中文大小&#xff1a;649.68M安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.5GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a;https://pan.bai…

深度学习基础篇 第二章: 转置卷积

参考教程&#xff1a; https://arxiv.org/pdf/1603.07285.pdf 文章目录 什么是转置卷积转置卷积的思想一维形式的理解二维形式的理解卷积和转置的关系no pading, unit stridespadding, unit stridesno padding, non-unit stridepadding&#xff0c;non-unit stride pytorch中的…

ububtu部署bind-dns 问题

启动(重启)命令如下&#xff1a; sudo systemctl restart bind9查看状态命令如下&#xff1a; sudo systemctl status bind9停止命令如下&#xff1a; sudo systemctl stop bind9#配置自己的域 要修改一下路径的文件(named.conf.local)&#xff1a; 在这个文件named.conf.loca…

java从入门到起飞(六)——用Socket实现网络通信

文章目录 背景网络编程网络编程三要素 2.DatagramSocket之UDP通信程序2.1 UDP发送数据2.2UDP接收数据2.3 3. Socket之TCP通信程序3.1TCP发送数据3.2TCP接收数据 背景 网络编程 ● 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线…

开始MySQL之路——MySQL 函数(详细讲解)

MySQL 函数 在MySQL中&#xff0c;为了提高代码重用性和隐藏实现细节&#xff0c;MySQL提高了很多函数。函数可以理解为别人封装好的模块代码。 在MySQL中&#xff0c;函数非常多&#xff0c;主要可以分为以下大类&#xff1a; 聚合函数&#xff1a;这类函数就是用来做简单的…

[深度学习]1. 深度学习知识点汇总

本文记录了我在学习深度学习的过程中遇到过的不懂的知识点&#xff0c;为了方便翻阅&#xff0c;故将其发表于此&#xff0c;随时更新&#xff0c;供大家参考。 深度学习常见知识点 1. 测试精度和训练精度 在深度学习中&#xff0c;测试精度和训练精度是两个重要的指标&#…

408考研-数据结构算法-双链表

双向链表的存储方式 双向链表跟链表差不多&#xff0c;只是它每个结点都含有两个链——一个指向下一结点&#xff0c;另一个指向前一结点。此外&#xff0c;它还能直接访问第一个和最后一个结点。 单链表只能向后操作&#xff0c;不可以向前操作。为了向前、向后操作方便&…

表白墙程序

目录 一、页面代码部分 二、设计程序 二、实现 doPost​编辑 三、实现 doGet 四、前端代码部分 五、使用数据库存储数据 一、页面代码部分 在之前的一篇博客中&#xff0c;已经写过了表白墙的页面代码实现&#xff0c;这里就不再重复了 页面代码如下&#xff1a; <!…

【Vue2】 axios库

网络请求库-axios库 认识Axios库为什么选择Axios库安装Axios axios发送请求常见的配置选项简单请求可以给Axios设置公共的基础配置发送多个请求 axios创建实例为什么要创建axios的实例 axios的拦截器请求拦截器响应拦截器 axios请求封装 认识Axios库 为什么选择Axios库 在游览…

git学习笔记 | 版本管理 - 分支管理

文章目录 git学习笔记Git是什么仓库常见的命令commit 备注规范在文件下设置git忽略文件 .gitignore 版本管理git log | git reflog 查看提交日志/历史版本版本穿梭 git resetgit reset HEAD <file> git checkout -- fileName 丢弃工作区的修改git revertGit恢复之前版本的…

海格里斯HEGERLS高密度料箱式四向穿梭车存储系统有哪些显著优势?

近些年仓储货架向着自动化、智能化发展&#xff0c;因此市面上出现很多不同类型的智能自动化仓储货架。其中&#xff0c;最受企业青睐的便是四向穿梭车货架。四向穿梭车货架根据其载重不同可分为托盘式和料箱式两大类。这两种不同类型的四向穿梭车货架在结构形式和控制方式上基…