• python面向对象基础


    面向对象基础

    1. 简述

    • 编程方式:

      • 面向过程: 根据代码在脚本的堆叠顺序,从上到下依次执行
      • 函数式编程:将相同功能的代码封装到函数中,直接调用即可,减少代码重复性
      • 面向对象:对函数进行分类和封装,将同类的函数放到一个类中,使调用更简单
    • 为嘛要面向对象

      • 应用需求 要的对系统的cpu、内存、硬盘等进行监控,超过阈值则告警
      while True:
          if cpu利用率 > 90%:
              #发送邮件提醒
              连接邮箱服务器
              发送邮件
              关闭连接
      
          if 硬盘使用空间 > 90%:
              #发送邮件提醒
              连接邮箱服务器
              发送邮件
              关闭连接
      
          if 内存占用 > 80%:
              #发送邮件提醒
              连接邮箱服务器
              发送邮件
              关闭连接
      View Code

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

      def 发送邮件(内容)
          #发送邮件提醒
          连接邮箱服务器
          发送邮件
          关闭连接
      
      while True:
      if cpu利用率 > 90%:
          发送邮件('CPU报警')
      
      if 硬盘使用空间 > 90%:
          发送邮件('硬盘报警')
      
      if 内存占用 > 80%:
          发送邮件('内存报警') 
      View Code

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

    def 发送邮件(内容)
            #发送邮件提醒
            连接邮箱服务器
            发送邮件
            关闭连接
     
        while True:
            for host in host-list:  #通过遍历host列表来进行监控
                if cpu利用率 > 90%:
                    发送邮件('CPU报警')
             
                if 硬盘使用空间 > 90%:
                    发送邮件('硬盘报警')
             
                if 内存占用 > 80%:
                    发送邮件('内存报警') 
        
    View Code

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

    class host:
        def 发送邮件(内容)
            #发送邮件提醒
            连接邮箱服务器
            发送邮件
            关闭连接
     
        def judge(self):
            while True:
                if cpu利用率 > 90%:
                    发送邮件('CPU报警')
             
                if 硬盘使用空间 > 90%:
                    发送邮件('硬盘报警')
             
                if 内存占用 > 80%:
                    发送邮件('内存报警') 
    View Code

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

    2. 面向对象

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

      • 创建类和对象
      #创建类  class+类名
      class foo:               #class是关键字,表示类,foo是类的名字
          def f1(self):               #类的方法1
              pass
          def f2(self):               #类的方法2
              pass
      
      #创建对象  对象 = 类名()
      bar = foo()   #创建一个bar对象 ,此对象中有类中所有的方法 ,创建对象,类名称后加括号即可 
      
      #调用对象的方法  对象.方法名()
      bar.f1()
      bar.f2()
      • 举例:
      #创建类
      class SQL:
      
          def create(self,sql):
              print(sql)
      
          def modify(self, sql):
              print(sql)
      
          def remove(self,sql):
              print(sql)
      
          def fetch(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就是对象本身
      还用上面的例子,如果我需要在执行方法的时候,验证用户名、密码传,验证通过之后才能执行里面的方法,那我需要创建对象之后,进行赋值用户密码

    class SQL:
        
         def modify(self, sql):
            print(sql)
            print(self.name)
            print(self.passwd)
        def remove(self,sql):
            print(sql)
            print(self.name)
            print(self.passwd)
        def fetch(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,这样我只需要定义一次即可

    class SQL:
             def __init__(self,user,password):
                  self.user = user
                  self.password = password
            def create(self,sql):
            print(sql)
            print(self.name)
            print(self.passwd)
        def modify(self, sql):
            print(sql)
            print(self.name)
            print(self.passwd)
        def remove(self,sql):
            print(sql)
            print(self.name)
            print(self.passwd)
        def fetch(self,sql):
            print(sql)
            print(self.name)
            print(self.passwd)
    obj1 = SQL('username','password')
    obj1.remove()
    obj2 = SQL('username1','password1')
    obj2.remove()

    3. 面向对象的三大特性

    • 封装

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

      • 将内容封装到某处
      class SQL:
          def __init__(self,name,passwd):   #类的构造方法,自动执行 
              self.name = name
              self.passwd = passwd
          def create(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)
          
          输出结果:
          fuzj 12313
        • 方式2 通过self间接调用

          res3 = obj1.create('fasdasda')
          print(res3)
          
          输出结果:
          fasdasda fuzj 12313
        • 多重封装

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

      #创建类
      class SQL:
          def __init__(self,name,passwd):
              self.name = name
              self.passwd = passwd
          def create(self,sql):
              print(sql)
      
      class test:
          def __init__(self,name,obj):
              self.name = name
              self.obj = obj
      
          def add(self,arg):
              print(arg)
      
      class test2:
          def __init__(self,obj):
              self.obj = obj
          def iner(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对象的所有方法,
      其关系如图:

      

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

    • 继承

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

      class 父类:
          def 方法1(slef):
                  pass
      class 子类(父类):
            pass
      
      那么子类中就会有父类的方法1
      
      • 单继承

      一个子类只继承一个父类
      如下:

      class c1:
      def __init__(self):
          self.name = 'c1'
          self.user = 'c1uer'
      
      def test(self):
          print("c1_test")
      
      def test1(self):
          print("c1_test1")
      
      def test3(self):
          self.test()
      
      class c2(c1):
      
          def __init__(self):
              self.passwd = 'c2'
      
          def test(self):
              print("c2_test")
          def test2(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的所有方法
      #c4继承了c2,c3两个父类,c2继承了c1父类,c3和c1中都有test()的方法
      
      class c1:
          def test1(self):
              print("c1_test")
      
          def test(self):
              print("c1_test")
      
      class c2(c1):
          def test2(self):
              print('c2_test')
      
      class c3:
          def test3(self):
              print("c3_test")
          def test(self):
              print("c3_test")
      
      class c4(c2,c3):
          def test4(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)多继承的每次查找父类仍然遵循单继承的原则

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

    #c4继承c2和c3两个父类,c2继承c1父类,c3继承c0父类,c0和c1继承c父类
    class c:
        def test(self):
            print("c_test")
    
    class c0(c):
        def test(self):
            print("c0_test")
    
    class c1(c):
        def test1(self):
            print("c1_test")
    
    class c2(c1):
        def test2(self):
            print('c2_test')
    
    class c3(c0):
        def test3(self):
            print("c3_test")
    
    
    class c4(c2,c3):
        def test4(self):
            print('c4_test')
    
    obj = c4()
    obj.test()
    
    运行结果:
    c0_test
    同父继承
    
    
    查找顺序为:
    1.查找c4中是否有test()方法,如果没有则查找c2中,c2中没有则查找c1中,c1中没有,不会继续查找父类了,会反回来查找c3类,c3类没有则找c0类,最后返回结果
    

    该规则同样适用下面情况

    • 多态:

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

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

      •  举例: 

        python:
        
        ```
        def func(arg):
        pass
        
        arg 可以是字符串、数字、列表、字典等
        
        ```
        
        java或c++
        
        ```
        def func(int,arg)
        pass
        
        arg 只能处理int类型的数据
        def func(str,arg)
        pass
        arg只能处理字符串类型的数据,如果数据类型不符合的话。直接报错
        
        ```
        伪代码
      •  java如何支持多态

        class A:
        pass
        class B(A):
        pass
        class C(A)
        pass
        
        def func(B,arg):
        pass
        此时arg指定类型为B,那么只能为B的对象类型
        def func(A,arg)
        pass
        此时指定arg类型为A类型,而B和C都继承A,所以ABC类型都可以使用了
        
        所以类似java的编程语言,都是利用类的继承关系来实现多态
        伪代码
  • 相关阅读:
    jQuery全选反选全不选
    Ubuntu安装VMware Workstation8.0.3
    ubuntu安装的软件如何启动
    ubuntu装VirtualBox遇到的问题
    你是优秀的PHP程序员吗?
    VMWare 三种工作模式(bridged、hostonly、NAT)
    最近要做的事
    090224
    2月23日 月曜日
    周五 26日
  • 原文地址:https://www.cnblogs.com/pycode/p/class.html
Copyright © 2020-2023  润新知