python面向对象基础_python面向对象基础

本文介绍了面向对象编程在系统监控场景中的应用,对比了面向过程和函数式编程。通过实例展示了如何使用面向对象提高代码的可读性和可维护性,特别是在监控多台设备时的优势。通过创建类和对象,实现对每台机器的独立监控,并利用多线程进行高效管理。此外,还解释了类的self参数以及构造方法__init__()的作用,强调了面向对象的封装、继承和多态特性在实际编程中的价值。
摘要由CSDN通过智能技术生成

面向对象基础

1. 简述

编程方式:

面向过程: 根据代码在脚本的堆叠顺序,从上到下依次执行

函数式编程:将相同功能的代码封装到函数中,直接调用即可,减少代码重复性

面向对象:对函数进行分类和封装,将同类的函数放到一个类中,使调用更简单

为嘛要面向对象

应用需求 要的对系统的cpu、内存、硬盘等进行监控,超过阈值则告警

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

whileTrue:if cpu利用率 > 90%:#发送邮件提醒

连接邮箱服务器

发送邮件

关闭连接if 硬盘使用空间 > 90%:#发送邮件提醒

连接邮箱服务器

发送邮件

关闭连接if 内存占用 > 80%:#发送邮件提醒

连接邮箱服务器

发送邮件

关闭连接

View Code

随着python的学习,开始使用函数式编程

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

def发送邮件(内容)#发送邮件提醒

连接邮箱服务器

发送邮件

关闭连接whileTrue:if cpu利用率 > 90%:

发送邮件('CPU报警')if 硬盘使用空间 > 90%:

发送邮件('硬盘报警')if 内存占用 > 80%:

发送邮件('内存报警')

View Code

函数式编程增加了代码的可读性和重用性,但是,这仅仅是单台机器的监控,如果我要监控多台呢,可能需要需要这样写:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

def发送邮件(内容)#发送邮件提醒

连接邮箱服务器

发送邮件

关闭连接whileTrue:for host in host-list: #通过遍历host列表来进行监控

if cpu利用率 > 90%:

发送邮件('CPU报警')if 硬盘使用空间 > 90%:

发送邮件('硬盘报警')if 内存占用 > 80%:

发送邮件('内存报警')

View Code

这样貌似实现了,但是如果是1000台机器呢,可能当循环到999台的时候,第100台已经出现问题了。造成告警延误。而如果使用面向对象呢?将很好的解决此问题

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

classhost:def发送邮件(内容)#发送邮件提醒

连接邮箱服务器

发送邮件

关闭连接defjudge(self):whileTrue:if cpu利用率 > 90%:

发送邮件('CPU报警')if 硬盘使用空间 > 90%:

发送邮件('硬盘报警')if 内存占用 > 80%:

发送邮件('内存报警')

View Code

我将每个机器创建为一个对象,对象中有上面判断的方法,这样我就可以多线程的监控

2. 面向对象

类和对象

类就是一个模板,模板里可以包含多个方法(即函数),方法里实现一些功能,对象则是根据模板创建的实例,通过实例对象可以执行类中的函数

创建类和对象

#创建类 class+类名class foo: #class是关键字,表示类,foo是类的名字

deff1(self): #类的方法1pass

deff2(self): #类的方法2pass#创建对象 对象=类名()

bar = foo() #创建一个bar对象 ,此对象中有类中所有的方法 ,创建对象,类名称后加括号即可#调用对象的方法 对象.方法名()

bar.f1()

bar.f2()

举例:

#创建类classSQL:defcreate(self,sql):print(sql)defmodify(self, sql):print(sql)defremove(self,sql):print(sql)deffetch(self,sql):print(sql)

#创建对象

obj1 = SQL()

obj2=SQL()#调用对象里的方法

res1 = obj1.modify('修改')

res2 = obj2.fetch('查看')print('obj1:'res1)print('obj2:'res2)

运行结果:

obj1: 修改

obj2: 查看

应用场景

面向对象:【创建对象】【通过对象执行方法】,适用于当某一些函数中具有相同参数时,可以使用面向对象的方式,将参数值一次性封装到对象里,函数直接调用即可

函数编程:【执行函数】 各个函数之间是独立且无共用的数据

类中的self是什么鬼

self是python自动传值的一个形式参数,那个对象调用方法,就会自动执行self,在一个类中,self就是对象本身

还用上面的例子,如果我需要在执行方法的时候,验证用户名、密码传,验证通过之后才能执行里面的方法,那我需要创建对象之后,进行赋值用户密码

classSQL:defmodify(self, sql):print(sql)print(self.name)print(self.passwd)defremove(self,sql):print(sql)print(self.name)print(self.passwd)deffetch(self,sql):print(sql)print(self.name)print(self.passwd)

#创建对象

obj1 = SQL()

obj1.user= 'user'obj1.passwd= 'passwd'res1= obj1.modify('修改')

res2 = obj2.fetch('结果')print(res1)print(res2)

输出结果:

修改

user

passwd

结果

user

passwd

我们使用self来定义user和passwd变量,这样user和passwd对整个对象是生效的,所以在每个方法都都可以调用到

类的构造方法

上例发现每次对象调用方法都要进行对user 和password进行赋值。非常麻烦。

python类中使用init自动构造方法,当创建对象的时候自动执行该方法。如下使用init,这样我只需要定义一次即可

classSQL:def __init__(self,user,password):

self.user=user

self.password=passworddefcreate(self,sql):print(sql)print(self.name)print(self.passwd)defmodify(self, sql):print(sql)print(self.name)print(self.passwd)defremove(self,sql):print(sql)print(self.name)print(self.passwd)deffetch(self,sql):print(sql)print(self.name)print(self.passwd)

obj1= SQL('username','password')

obj1.remove()

obj2= SQL('username1','password1')

obj2.remove()

3. 面向对象的三大特性

封装

封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。所以,在使用面向对象的封装特性时,需要:

将内容封装到某处

classSQL:def __init__(self,name,passwd): #类的构造方法,自动执行

self.name =name

self.passwd=passwddefcreate(self,sql): #类的一个方法print(sql,self.name,self.passwd)

#创建类SQL的obj对象

obj1= SQL('fuzj','123') #自动fuzj和123分别封装到对象obj1的name和asswd属性中

obj2 = SQL('jie','311') #自动jie和311分别封装到对象obj2的name和asswd属性中

从某处调用被封装的内容

方式1 通过对象直接调用

res =obj1.name #直接调用obj的user属性

res2=obj1.passwd #直接调用obj的passwd属性print(res,res2)

输出结果:

fuzj12313

方式2 通过self间接调用

res3 = obj1.create('fasdasda')print(res3)

输出结果:

fasdasda fuzj12313

多重封装

类不仅可以将普通字符串封装到类中,还可以将一个对象封装到类中,看下面代码

#创建类classSQL:def __init__(self,name,passwd):

self.name=name

self.passwd=passwddefcreate(self,sql):print(sql)classtest:def __init__(self,name,obj):

self.name=name

self.obj=objdefadd(self,arg):print(arg)classtest2:def __init__(self,obj):

self.obj=objdefiner(slef,arg):print(arg)

#创建对象

c1= SQL('fuzj','12313')

c2= test('aaa',c1) #把c1对象封装到c2对象里,c2对象会有c1对象的所有方法

c3=test2(c2) #把c2对象封装到c3对象中,c3对象会有c2对象的所有方法,同时也就有了c1对象的所有方法

#调用

c1.create("c1调用自身create方法")

c2.obj.create('c2调用c1的create方法')

c3.obj.add('c3调用c2的add方法')

c3.obj.obj.create('c3调用c1的create方法')

结果:

c1调用自身create方法

c2调用c1的create方法

c3调用c2的add方法

c3调用c1的create方法

可以看出,将a对象封装到b对象中,b对象也就有了a对象的所有方法,

其关系如图:

59b859a58a15f4aa75f61891cf89e4a3.png

所以c3如果要使用c1的create的方法,需要如下调用

c3.obj.obj.create()

继承

类的继承是子类继承父类的所有方法,或者说基类继承派生类的所有方法

class父类:def方法1(slef):pass

class子类(父类):pass

那么子类中就会有父类的方法1

单继承

一个子类只继承一个父类

如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

classc1:def __init__(self):

self.name= 'c1'self.user= 'c1uer'

deftest(self):print("c1_test")deftest1(self):print("c1_test1")deftest3(self):

self.test()classc2(c1):def __init__(self):

self.passwd= 'c2'

deftest(self):print("c2_test")deftest2(self):

self.test3()

obj=c2()

obj.test()

obj.test1()

obj.test2()

执行结果:

c2_test

c1_test1

c2_test

单继承

继承规则:

1) 调用子类的某个方法时,如果这个方法在子类中存在,则执行子类的方法,如果子类方法不存在,再去找父类的方法。所以执行obj.test()时,子类中有该方法,就直接执行该方法,不再父类中找,因此返回结果是c2_test;执行obj.test1()时,子类中没有改方法,就找到父类的方法,再执行,因此返回的结果是c1_test1

2) 子类的方法优先于父类的方法,当父类的方法中有调取其他方法时,会优先查找子类的方法,所以执行c2_test2()时,发现该方法调用的时是test3(),于是开始从自己方法中查找test3(),然后再去找父类中的方法,找到父类的test3()方法,发现该方法调用了test()方法,于是会再次查找test()方法,发现自己有,所以就直接调用自己的test()方法,返回c2_test

3) 子类继承父类,其实就是将父类中的方法子类中没有的全部挪到子类下

多继承

python的子类可以继承多个父类,这是比java、c++等开发语言最大的优势

单父继承,即没有共同的父类,规则为一条道走到黑

class父类1:pass

class父类2:pass

class子类(父类1,父类2)pass那么,子类中就会有父类1,父类2的所有方法

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

#c4继承了c2,c3两个父类,c2继承了c1父类,c3和c1中都有test()的方法

classc1:deftest1(self):print("c1_test")deftest(self):print("c1_test")classc2(c1):deftest2(self):print('c2_test')classc3:deftest3(self):print("c3_test")deftest(self):print("c3_test")classc4(c2,c3):deftest4(self):print('c4_test')

obj=c4()

obj.test()

obj.test3()

运行结果:

c1_test

c3_test

从结果可以看出:obj.test()执行顺序为:

首先去c4类中查找,如果c4类中没有,则继续去c2类中找,如果c2类中没有,则继续去父类c1类中找,所以test()打印的结果为c1_test

obj.test3()执行顺序为:

首先去c4类中查找,如果c4类中没有,则继续去c2类中找,如果c2类中没有,则继续去父类c1类中找,c1没有,则返回继续去另一个c4的父类c3中找,所以test3()打印的结果为c3_test

```

单继承

继承规则:

1)子类中有两个父类,会从左到右依次查找父类的方法

2)子类的父类如果还有继承,优先查找当前父类的父类

3)多继承的每次查找父类仍然遵循单继承的原则

56bd36d77423045dbfdd1dc2f81a91d8.png

同父继承,最上边有继承的是一个父类,情况则不一样了

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

#c4继承c2和c3两个父类,c2继承c1父类,c3继承c0父类,c0和c1继承c父类

classc:deftest(self):print("c_test")classc0(c):deftest(self):print("c0_test")classc1(c):deftest1(self):print("c1_test")classc2(c1):deftest2(self):print('c2_test')classc3(c0):deftest3(self):print("c3_test")classc4(c2,c3):deftest4(self):print('c4_test')

obj=c4()

obj.test()

运行结果:

c0_test

同父继承

查找顺序为:

1.查找c4中是否有test()方法,如果没有则查找c2中,c2中没有则查找c1中,c1中没有,不会继续查找父类了,会反回来查找c3类,c3类没有则找c0类,最后返回结果

62447ad9e91a5359658ea7f098f0a61a.png

该规则同样适用下面情况

e5b9022a4e10198163233b6a9d6b104a.png

多态:

Pyhon不支持多态并且也用不到多态,多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚“鸭子类型”

多态中python和其他编程语言最大的区别是传参问题。python的函数传参,参数可以是列表,字典,字符串,数字等,而java、c++等语言传递参数时,参数需要指定类型,一旦参数类型被指定,就只能处理此中类型的数据

举例:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

python:

```deffunc(arg):passarg 可以是字符串、数字、列表、字典等

```

java或c++```deffunc(int,arg)passarg 只能处理int类型的数据deffunc(str,arg)passarg只能处理字符串类型的数据,如果数据类型不符合的话。直接报错

```

伪代码

java如何支持多态

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

classA:pass

classB(A):pass

classC(A)pass

deffunc(B,arg):pass此时arg指定类型为B,那么只能为B的对象类型deffunc(A,arg)pass此时指定arg类型为A类型,而B和C都继承A,所以ABC类型都可以使用了

所以类似java的编程语言,都是利用类的继承关系来实现多态

伪代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值