zoukankan      html  css  js  c++  java
  • 面向对象编程知识点综合

    一、面向对象编程与面向过程编程对比

      1、面向过程编程:核心过程二字,过程指的是解决问题的步骤,既先干什么、再干什么、后干什么,基于该思想的编程就好比在生产一条流水线,是一种机械式的思维方式。

        优点:复杂的问题流程化进而简单化

        缺点:可扩展性差

      2、面向对象编程:核心是对象二字,对象是技能与特征的结合体,基于该思想编写程序就好比在创造一个世界,世界是由一个个对象组成的,在上帝眼里任何存在的事物都是对象,任何不存在的事物也都可以创造出来,是一种上帝式的思维方式

        优点:可扩展性强

        缺点:编程的复杂度要高于面向过程

    二、类与对象

      对象:对象是技能与特征的结合体

      类:对象相同特征与技能的结合体

        对象是具体存在的事物,而类则是抽象出来的概念,站在不同角度总结出来的类与对象是不同的

        在现实世界中,现有一个个具体存在的对象,然后随着人类文明的发展才总结出类的概念

    #在现实世界中,站在老男孩学校的角度:先有对象,再有类
    对象1:李坦克
        特征:
            学校=oldboy
            姓名=李坦克
            性别=男
            年龄=18
        技能:
            学习
            吃饭
            睡觉
    
    对象2:王大炮
        特征:
            学校=oldboy
            姓名=王大炮
            性别=女
            年龄=38
        技能:
            学习
            吃饭
            睡觉
    
    对象3:牛榴弹
        特征:
            学校=oldboy
            姓名=牛榴弹
            性别=男
            年龄=78
        技能:
            学习
            吃饭
            睡觉
    
    
    现实中的老男孩学生类
        相似的特征:
            学校=oldboy
        相似的技能:
            学习
            吃饭
            睡觉
    View Code

        在程序中,是先定义出类的概念后调用类来产生对象

    #在程序中,务必保证:先定义(类),后使用(产生对象)
    PS:
      1. 在程序中特征用变量标识,技能用函数标识
      2. 因而类中最常见的无非是:变量和函数的定义
    
    #程序中的类
    class OldboyStudent:
        school='oldboy'
        def learn(self):
            print('is learning')
            
        def eat(self):
            print('is eating')
        
        def sleep(self):
            print('is sleeping')
      
    
    
    #注意:
      1.类中可以有任意python代码,这些代码在类定义阶段便会执行
      2.因而会产生新的名称空间,用来存放类的变量名与函数名,可以通过OldboyStudent.__dict__查看
      3.对于经典类来说我们可以通过该字典操作类名称空间的名字(新式类有限制),但python为我们提供专门的.语法
      4.点是访问属性的语法,类中定义的名字,都是类的属性
    
    #程序中类的用法
    .:专门用来访问属性,本质操作的就是__dict__
    OldboyStudent.school #等于经典类的操作OldboyStudent.__dict__['school']
    OldboyStudent.school='Oldboy' #等于经典类的操作OldboyStudent.__dict__['school']='Oldboy'
    OldboyStudent.x=1 #等于经典类的操作OldboyStudent.__dict__['x']=1
    del OldboyStudent.x #等于经典类的操作OldboyStudent.__dict__.pop('x')
    
    
    #程序中的对象
    #调用类,或称为实例化,得到对象
    s1=OldboyStudent()
    s2=OldboyStudent()
    s3=OldboyStudent()
    
    #如此,s1、s2、s3都一样了,而这三者除了相似的属性之外还各种不同的属性,这就用到了__init__
    #注意:该方法是在对象产生之后才会执行,只用来为对象进行初始化操作,可以有任意代码,但一定不能有返回值
    class OldboyStudent:
        ......
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
        ......
    
    
    s1=OldboyStudent('李坦克','',18) #先调用类产生空对象s1,然后调用OldboyStudent.__init__(s1,'李坦克','男',18)
    s2=OldboyStudent('王大炮','',38)
    s3=OldboyStudent('牛榴弹','',78)
    
    
    #程序中对象的用法
    #执行__init__,s1.name='牛榴弹',很明显也会产生对象的名称空间
    s2.__dict__
    {'name': '王大炮', 'age': '', 'sex': 38}
    
    s2.name #s2.__dict__['name']
    s2.name='王三炮' #s2.__dict__['name']='王三炮'
    s2.course='python' #s2.__dict__['course']='python'
    del s2.course #s2.__dict__.pop('course')
    View Code

      __init__方法

    #方式一、为对象初始化自己独有的特征
    class People:
        country='China'
        x=1
        def run(self):
            print('----->', self)
    
    # 实例化出三个空对象
    obj1=People()
    obj2=People()
    obj3=People()
    
    # 为对象定制自己独有的特征
    obj1.name='egon'
    obj1.age=18
    obj1.sex='male'
    
    obj2.name='lxx'
    obj2.age=38
    obj2.sex='female'
    
    obj3.name='alex'
    obj3.age=38
    obj3.sex='female'
    
    # print(obj1.__dict__)
    # print(obj2.__dict__)
    # print(obj3.__dict__)
    # print(People.__dict__)
    
    
    
    
    
    #方式二、为对象初始化自己独有的特征
    class People:
        country='China'
        x=1
        def run(self):
            print('----->', self)
    
    # 实例化出三个空对象
    obj1=People()
    obj2=People()
    obj3=People()
    
    # 为对象定制自己独有的特征
    def chu_shi_hua(obj, x, y, z): #obj=obj1,x='egon',y=18,z='male'
        obj.name = x
        obj.age = y
        obj.sex = z
    
    chu_shi_hua(obj1,'egon',18,'male')
    chu_shi_hua(obj2,'lxx',38,'female')
    chu_shi_hua(obj3,'alex',38,'female')
    
    
    
    
    
    #方式三、为对象初始化自己独有的特征
    class People:
        country='China'
        x=1
    
        def chu_shi_hua(obj, x, y, z): #obj=obj1,x='egon',y=18,z='male'
            obj.name = x
            obj.age = y
            obj.sex = z
    
        def run(self):
            print('----->', self)
    
    
    obj1=People()
    # print(People.chu_shi_hua)
    People.chu_shi_hua(obj1,'egon',18,'male')
    
    obj2=People()
    People.chu_shi_hua(obj2,'lxx',38,'female')
    
    obj3=People()
    People.chu_shi_hua(obj3,'alex',38,'female')
    
    
    
    
    # 方式四、为对象初始化自己独有的特征
    class People:
        country='China'
        x=1
    
        def __init__(obj, x, y, z): #obj=obj1,x='egon',y=18,z='male'
            obj.name = x
            obj.age = y
            obj.sex = z
    
        def run(self):
            print('----->', self)
    
    obj1=People('egon',18,'male') #People.__init__(obj1,'egon',18,'male')
    obj2=People('lxx',38,'female') #People.__init__(obj2,'lxx',38,'female')
    obj3=People('alex',38,'female') #People.__init__(obj3,'alex',38,'female')
    
    
    # __init__方法
    # 强调:
    #   1、该方法内可以有任意的python代码
    #   2、一定不能有返回值
    class People:
        country='China'
        x=1
    
        def __init__(obj, name, age, sex): #obj=obj1,x='egon',y=18,z='male'
            # if type(name) is not str:
            #     raise TypeError('名字必须是字符串类型')
            obj.name = name
            obj.age = age
            obj.sex = sex
    
    
        def run(self):
            print('----->', self)
    
    
    # obj1=People('egon',18,'male')
    obj1=People(3537,18,'male')
    
    # print(obj1.run)
    # obj1.run() #People.run(obj1)
    # print(People.run)
    View Code

    类是一系列对象相同特征与技能的结合体,既类体中最常见的就是变量与函数体,但其实类体中是可以存在任意python代码的,

    类体中会在定义阶段立即执行,会产生一个类的名称空间,用来将类体代码执行过程中产生的名字都丢进去

    总结:①类本质就是一个名称空间,或者说就是一个用来存放变量与函数的容器,

         ②类的用途之一就是当做名称空间,从其内部取出名字来使用

       ③类的用途之二是用来调用类产生对象

    调用类产生对象:调用类的过程称之为类的实例化,调用类的返回值称之为类的一个对象

    View Code

      调用类发生了:

        1、产生一个空对象

        2、触发类中的__init__方法,将对象连同调用类括号内指定的参数一同传入__init__  

          类中定义的变量是类的数据属性,类可以用,对象也可以用,大家都指向同一个地址,类变量值一旦改变,所有对象都跟着改变

          类中定义的函数是类的函数属性,类可以用,类来调用就是一个普通的函数,但其实类中定义的函数就是给对象用的,而且是绑定给对象用的

          绑定方法:指向类的函数(特殊之处是绑定给谁就应该由谁调用)

          类的函数:该传几个参数就传几个参数

    三大特性之继承:

      利用继承能来解决类与类之间的代码冗余问题

      继承是一种新建类的方法,新建的类称之为子类(派生类),被继承的类称之为父类、基类、超类

      继承的特性:子类可以遗传、重用父类的属性

    python中继承类的特点:

      1、在python中一个子类可以同时继承多个父类

      2、在继承背景下说,python中类分为两种:新式类和经典类

        新式类:但凡继承了object的类以及该类的子类都是新式类

          python中一个类即便没有显示的继承任何类,默认就会继承object,即在python3中所有的类都是新式类

        经典类:没有继承object的类以及该类的子类都是经典类

       在单继承的基础下属性查找的顺序是:对象——》对象类——》父亲——》父类。。。

    子类中重用父类的属性:

      方式一:

          在子类派生出的新方法中指名道姓的引用某一个类中的函数

          与继承无关,访问的是父类中的函数没有自动传值功能

    继承解决的是类与类之间代码冗余的问题,一定是一个类是另外一个类的子类

    总结对象之间的相似之处得到类,总结类之间的相似之处得到的就是父类

      多继承背景下属性查找的顺序:对象--》对象的类--》按照从左往右的顺序一个个的分支找下去

    一旦出现菱形继承问题,新式类与经典类在属性查找上的区别是:

      新式类:广度优先查找,在最后一个分支查找顶级类

      经典类:深度优先查找,在第一个分支就查找顶级类

    mro()查找的顺序:

      在子类派生出的新的方法中重用父类功能的方式二

        在子类中用super()方法

          python2中:super(自己的类名,对象自己)

          python3中:super()

      调用super()方法会得到一个特殊的对象,该对象是专门用来引用父类中的属性,完全参照mro()列表 访问是绑定方法,有自动传值的效果

    组合:

      组合指的是一个对象拥有一个属性,该属性的值属于另外一个类的对象

      组合通过一个对象添加属性(属性的值是另外一个类的对象)的方式,可以间接的将两个类关联、整合,从而减少类之间的代码冗余问题

    多态:

      多态指的是同一事物的不同形态

      在多态背景下,可以不用考虑对象具体的类型的前提下直接使用对象多态的精髓:统一

      父类只是用来建立规范的,不能用来实例化的,更无需实现内部方法。

      python崇尚鸭子类型

    封装:

      装:往容器、名称空间内存入名字

      封:代表存放于名称空间的名字给藏起来,这种隐藏对外不对内

      在类内定义的属性前加__开头(没有__结尾)

    总结:

      1、__开头的属性实现的隐藏仅仅只是一种语法上的变形,并不会真正的限制类外部的访问

      2、该变形操作只在类定义阶段检测语法时发生一次,类定义阶段之后新增的__开头的属性不会变形

      3、如果父类不想让子类覆盖自己的属性,可以在属性前加__开头

      4、peoperty装饰器是用来将类内的函数属性伪装为数据属性

    绑定方法与非绑定方法

    一:绑定方法(绑定给谁,谁来调用就自动将它本身当作第一个参数传入):

        1. 绑定到类的方法:用classmethod装饰器装饰的方法。

                    为类量身定制

                    类.boud_method(),自动将类当作第一个参数传入

                  (其实对象也可调用,但仍将类当作第一个参数传入)

        2. 绑定到对象的方法:没有被任何装饰器装饰的方法。

                   为对象量身定制

                   对象.boud_method(),自动将对象当作第一个参数传入

                 (属于类的函数,类可以调用,但是必须按照函数的规则来,没有自动传值那么一说)

    import settings
    class MySQL:
        def __init__(self,host,port):
            self.host=host
            self.port=port
    
        @classmethod
        def from_conf(cls):
            print(cls)
            return cls(settings.HOST,settings.PORT)
    
    print(MySQL.from_conf) #<bound method MySQL.from_conf of <class '__main__.MySQL'>>
    conn=MySQL.from_conf()
    
    conn.from_conf() #对象也可以调用,但是默认传的第一个参数仍然是类

    二:非绑定方法:用staticmethod装饰器装饰的方法

            1. 不与类或对象绑定,类和对象都可以调用,但是没有自动传值那么一说。就是一个普通工具而已

        注意:与绑定到对象方法区分开,在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,可不是普通函数,对象调用该方法会自动传值,而staticmethod装饰的方法,不管谁来调用,都没有自动传值一说

    import hashlib
    import time
    class MySQL:
        def __init__(self,host,port):
            self.id=self.create_id()
            self.host=host
            self.port=port
        @staticmethod
        def create_id(): #就是一个普通工具
            m=hashlib.md5(str(time.time()).encode('utf-8'))
            return m.hexdigest()
    
    
    print(MySQL.create_id) #<function MySQL.create_id at 0x0000000001E6B9D8> #查看结果为普通函数
    conn=MySQL('127.0.0.1',3306)
    print(conn.create_id) #<function MySQL.create_id at 0x00000000026FB9D8> #查看结果为普通函数
    View Code

    classmethod与staticmethod的区别

    import settings
    class MySQL:
        def __init__(self,host,port):
            self.host=host
            self.port=port
    
        @staticmethod
        def from_conf():
            return MySQL(settings.HOST,settings.PORT)
    
        # @classmethod #哪个类来调用,就将哪个类当做第一个参数传入
        # def from_conf(cls):
        #     return cls(settings.HOST,settings.PORT)
    
        def __str__(self):
            return '就不告诉你'
    
    class Mariadb(MySQL):
        def __str__(self):
            return '<%s:%s>' %(self.host,self.port)
    
    
    m=Mariadb.from_conf()
    print(m) #我们的意图是想触发Mariadb.__str__,但是结果触发了MySQL.__str__的执行,打印就不告诉你:
    View Code

    三、 元类

      元类源自一句话,在python中一切皆对象,而对象都是由类实例化得到的,既然这样那样类也是对象,也是通过实例化得到的,内置类为type

    调用关系是:

      调用元类——》自定义的类

      调用自定义的类——》自定义的对象

    自定义类的三个关键组成部分

      1 类名

      2 类的基类们

      3 类的名称空间

    class关键字的底层的工作原理

       1、先拿到类名(oldboyteacher)

      2、再拿到类的基类们:(object,)

      3、拿到类的名称空间(执行类体代码,将产生的名字放到类的名称空间也就是一个字典里,补充exec)

      4、调用元类实例化得到自定义的类:、oldboyTeacher=type('oldboyTeacher',(object){})

    实现代码

    class_name="OldboyTeacher"
    class_bases=(object,)
    class_dic={}
    class_body='''
        school=self.shcool
        def  __init__(self,...)
           .............
        def score(......)         
        ...........
    exec('x=1',{},class_dic)
     
    print(class_dic)
    OldboyTeacher_type(class_name,class_bases,class_dic)
    View Code

    自定义元类来控制类的产生:

      但凡继承了type的类才能称之为自定义的元类,否则就是一个普通的类

      对象之所以可以调用是因为对象有一个函数__call__

      实例化发生的三件事:

        1、产生一个空对象

        2、执行__init__方法,完成对象初始化属性的操作

        3、返回初始化好的那个对象

    自定义类来控制类的调用

     

  • 相关阅读:
    JavaScript的BOM编程,事件-第4章
    C#获取程序目录
    e3商城_day05
    第三届中国云计算用户大会笔记和心得
    Android应用源码 概览
    电脑用bat脚本给手机批量自动安装apk文件 autoInstall.bat
    网上的很多Android项目源码有用吗?Android开发注意的地方。
    Android 简历 怎么写? 月薪10K,20K+, 怎么拿到面试?
    android 职业 转行
    我的Python学习之路(2)
  • 原文地址:https://www.cnblogs.com/chenchuanjide/p/9512446.html
Copyright © 2011-2022 走看看