美文网首页
Python面向对象编程(一)

Python面向对象编程(一)

作者: itxone | 来源:发表于2018-06-27 00:03 被阅读0次

    一、面向对象编程

    1. 面向对象编程和面向过程编程的区别

    • 面向过程编程:机械思维,简化复杂的流程,可扩展性差
    • 面向对象编程:上帝思维,编程复杂度高于面向过程,可扩展性强

    2. 什么是面向对象编程

    • 对象是特征和技能的结合体
    • 创造对象,给对象赋予特征和技能,让对象干活
    • 修改一个对象,对其他地方不影响
    • 面向对象编程,主要解决的是可扩展性

    3. 类

    • 类由对象组成,是一系列对象的结合体,这些对象具有相似的特征和技能
    • 在面向对象编程中,站的角度不同,分的类不同
    • 在现实世界中现有具体的对象,才有分类
    • 但是在程序中,必须先定义类,后调用类,来产生对象

    ① 定义类

    • 定义类的语法:class 类的名字:,类的名字使用驼峰语法
      类的名字,就是类中名字的容器

    类的作用:

    • 类当做容器,存放类里面的名字
    • 调用类,就会产生对象
    class OldboyStudent:
        school='oldboy'
    
        def choose_course(self):
            print('is choosing course')
    
        print('=========')
    ================================执行结果如下======================================
    =========
    

    说明:类体代码在类定义阶段就会执行,并产生一个类的名称空间

    ② 查看类的名称空间

    • 类的名字.__dict__
    class OldboyStudent:
        school='oldboy'
    
        def choose_course(self):
            print('is choosing course')
    
    print(OldboyStudent.__dict__)
    ================================执行结果如下======================================
    {'__module__': '__main__', 'school': 'oldboy', 'choose_course': <function OldboyStudent.choose_course at 0x0000029B42F7D158>, '__dict__': <attribute '__dict__' of 'OldboyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'OldboyStudent' objects>, '__doc__': None}
    

    ② 取出类的名称空间的内容

    class OldboyStudent:
        school='oldboy'
    
        def choose_course(self):
            print('is choosing course')
    # 取出类的名称空间的内容
    print(OldboyStudent.__dict__['school'])
    print(OldboyStudent.__dict__['choose_course'])
    OldboyStudent.__dict__['choose_course']('需要写内容') # 调用类中的函数,但是要加函数self
    ================================执行结果如下======================================
    oldboy
    <function OldboyStudent.choose_course at 0x000001923570D158>
    is choosing course
    

    ③ 增加查类名称空间的内容

    class OldboyStudent:
        school='oldboy'
    
        def choose_course(self):
            print('is choosing course')
    
    OldboyStudent.country='China' # 相当于OldboyStudent.__dict__['country']='China'
    print(OldboyStudent.__dict__)
    
    image.png

    ③ 修改类名称空间的内容

    class OldboyStudent:
        school='oldboy'
    
        def choose_course(self):
            print('is choosing course')
    
    OldboyStudent.country='CHINA'
    print(OldboyStudent.__dict__)
    
    image.png

    ④ 删除类名称空间的内容

    class OldboyStudent:
        school='oldboy'
    
        def choose_course(self):
            print('is choosing course')
    
    del OldboyStudent.school  # 删除
    
    print(OldboyStudent.__dict__)
    

    ⑤ 调用类

    • 语法格式:类的名字(),调用类就是产生对象
    • 调用类的过程,又称类的实例化,实例化的结果成为类的对象或类的实例
    • 调用类会获得一个返回值,这个返回值就是类的对象(实例)

    4. 类的属性

    • 先在现实世界中总结对象(根据特征和技能),得到现实世界中的类,再定义为程序中的类,调用类,产生程序中的对象(公共类和独有对象)
    # 定义类
    class OldboyStudent:
        # 特征
        school='oldboy'
    
        # 技能
        def choose_course(self):
            print('is choosing course')
    
    # 类属性的查看类
    print(OldboyStudent.school)  # OldboyStudent.__dict__['school']
    # 类属性的增加(没有的名字)
    OldboyStudent.x=1  # OldboyStudent.__dict__['x']=1
    # 类属性的修改(已有的名字)
    OldboyStudent.school='Oldboy'
    # 类属性的删除
    del OldboyStudent.x
    
    • OldboyStudent.a 点后面的名字a称为属性,表示在类的名称空间中找到属性的值
      变量和函数组成,变量是数据,函数是功能
    • 类中定义的函数,是类的函数属性
    • 类中定义的变量,是类的数据属性
    class OldboyStudent:
        # 特征
        school='oldboy'
    
        # 技能
        def choose_course(self):
            print('is choosing course')
    
    # 类用来生产对象,类调用几次就生产几次
    stu1=OldboyStudent()
    stu2=OldboyStudent()
    stu3=OldboyStudent()
    print(stu1)
    print(stu2)
    print(stu3)
    ==============================执行结果如下===================================
    <__main__.OldboyStudent object at 0x000002574C24BDA0>
    <__main__.OldboyStudent object at 0x000002574C24BE10>
    <__main__.OldboyStudent object at 0x000002574C24BDD8>
    
    # 类产生的对象,这个对象可访问类中的属性,比如:
    # 对象访问类的属性和类访问属性语法一样
    print(OldboyStudent.school)
    print(stu1.school)   # 作用同上
    ==============================执行结果如下===================================
    oldboy
    oldboy
    
    class OldboyStudent:
        school='oldboy'
        def choose_course(self):
            print('is choosing course')
    
    # 生产对象
    stu1=OldboyStudent()
    stu1.name='itxone'
    stu1.age=18
    stu1.sex='male'
    print(stu1.name,stu1.age,stu1.sex)
    ==============================执行结果如下===================================
    itxone 18 male
    

    5. 为对象定义独有的属性

    • 对象本身也是名称空间,即存放自己独有的名字的容器,因此,增加对象的属性,就是在对象的名称空间中增加名字
    • 而类中存放的是对象共有的属性(数据属性和函数属性)

    ① 查看对象的名称空间,默认是空的字典

    class OldboyStudent:
        school='oldboy'
        def choose_course(self):
            print('is choosing course')
    
    stu1=OldboyStudent()
    print(stu1.__dict__)
    ==============================执行结果如下===================================
    {}
    
    class OldboyStudent:
        school='oldboy'
        def choose_course(self):
            print('is choosing course')
    
    stu1=OldboyStudent()
    # 添加属性
    stu1.name='itxone'
    stu1.age=18
    stu1.sex='male'
    print(stu1.__dict__)
    ==============================执行结果如下===================================
    {'name': 'itxone', 'age': 18, 'sex': 'male'}
    

    ② 当许多对象都要传入重复的name age sex属性时,就可以将功能,定义到类中

    • 添加__init__方法,表示在调用类时,会自动触发该功能
    class OldboyStudent:
        school='oldboy'
        # 对象在造出来的时候,就带有对象的独有属性
        def __init__(obj,x,y,z):
            obj.name=x
            obj.age=y
            obj.sex=z
    
        def choose_course(self):
            print('is choosing course')
    
    stu1=OldboyStudent('itxone',18,'male')
    print(stu1.__dict__)
    ==============================执行结果如下===================================
    {'name': 'itxone', 'age': 18, 'sex': 'male'}
    

    调用类时发生两件事:

    • 先创建一个空对象stu1
    • 然后自动触发类中的__init__功能,将对象stu1和括号内的参数一起传入

    属性查找

    • 对象属性查找顺序:先从对象自己的名称空间找,再从类的名称空间中找,如果都没有就报错
    • def __init__(self,x,y,z):中的self是约定俗成写法,表示传的是对象自己

    统计生产了多少次对象

    class OldboyStudent:
        school='oldboy'
        count=0   # 类中名称空间的名字
        def __init__(self,x,y,z):
            self.name=x
            self.age=y
            self.sex=z
            OldboyStudent.count+=1 # 调用了类中名称空间的名字,类中的属性变了,所有的都变了(类的属性共享)
    
        def choose_course(self):
            print('is choosing course')
            
    # 生产对象
    stu1=OldboyStudent('itxone',18,'male')
    stu2=OldboyStudent('itxone',18,'male')
    stu3=OldboyStudent('itxone',18,'male')
    print(OldboyStudent.count)
    print(stu1.count)
    print(stu2.count)
    print(stu3.count)
    ==============================执行结果如下===================================
    3
    3
    3
    3
    

    6. 绑定方法

    • 类名称空间中,定义的数据属性和函数属性,都是共享给所有对象使用的,类中函数大多是绑定给对象用的
    • 对象名称空间中,定义的只有数据属性,而且是对象独有的数据属性

    ① 类访问类中函数和对象访问类中的函数的区别

    • 类中定义的函数属性,类使用这个函数属性,就当做普通函数使用,遵循函数的参数规则
    • 而对象使用类中的函数,是绑定给对象用的
    • 绑定的效果:绑定给哪个对象,就由哪个对象调用,并且将这个绑定对象作为函数的第一个参数自动传入
    • 不同的对象,可以重复使用类中的函数,即函数的功能
    class OldboyStudent:
        school='oldboy'
        count=0
    
        def __init__(self,x,y,z):
            self.name=x
            self.age=y
            self.sex=z
            OldboyStudent.count+=1
    
        def choose_course(self):  # self就是绑定的对象,自动传入
            print('%s is choosing course' %self.name)
    
    stu1=OldboyStudent('itxone',18,'male')
    stu1.choose_course()
    print(stu1)
    print(stu1.choose_course)
    ==============================执行结果如下===================================
    itxone is choosing course
    <__main__.OldboyStudent object at 0x0000028F1966BE10>
    <bound method OldboyStudent.choose_course of <__main__.OldboyStudent object at 0x0000028F1966BE10>>  # 绑定方法
    

    说明:类汇总定义的函数,类可以使用,但是,类定义的函数大多数情况下都是绑定对对象用的,因此,类中定义的函数都自带self参数,表示自动传入绑定的对象

    ② 使用绑定方法的优点:

    • 使用绑定方法,不用再重复输入相似的代码,减少了代码量,节省内存空间
    • 对象的技能就是绑定方法,通过对象传入对象全部数据(传对象的名称空间,比如姓名,年龄等可以一起传),使类中的函数可以使用这个对象的所有数据
    • 因此,给一个对象,给的是对象的所有数据和处理这些数据的绑定方法
    class Foo:
        pass
    
    obj=Foo() # 创造一个对象
    print(obj)
    ==============================执行结果如下===================================
    <__main__.Foo object at 0x0000013EAF70A5F8>
    

    ③ 自定义的绑定方法和内置的绑定方法

    • Python3中统一了类与类型的概念,类就是类型,类型就是类
    # 自定义的绑定方法
    class Foo: # 定义的一个类
        def func(self,x):  # 类中的函数
            pass
    
    obj=Foo()  # Foo()类,创造了一个obj的对象
    obj.func(1) # obj.func是绑定方法 相当于Foo.func(obj,1)
    
    # 内置的绑定方法(以下为伪代码)
    class list: # list是定义的一个类
        def append(self,x): # append的就是类中的函数
            pass
    
    lb=[1,2,3] # 相当于lb=list([1,2,3])
    lb.append(123) # 绑定方法,相当于list.append(lb,123)
    

    小结

    • 对象是一个高度整合的产物,整合了数据和专门操作该数据的方法(绑定方法)
    class Foo:
        def __init__(self,host,port,db,charset):
            self.host=host
            self.port=port
            self.db=db
            self.charset=charset
            
        def excl(self,sql):
            conn= connect(self.host,self.port,self.db,self.charset)
            conn.execute(sql)
            return xxx
    # 生产一个对象,传入固定的参数
    obj1=Foo('1.1.1.1',3306,'db1','utf-8')
    # 绑定方法只需要传入一个参数就可以,不用重复传'1.1.1.1',3306,'db1','utf-8'
    obj1.excl('select * from t1')
    obj1.excl('select * from t2')
    obj1.excl('select * from t3')
    
    # 如果传入固定的参数有变动,在产生一个对象即可,节省了很多代码
    obj2=Foo('10.10.10.10',3307,'db1','utf-8')
    obj2.excl('select * from t4')
    obj2.excl('select * from t5')
    

    面向对象的特性之一:继承和派生

    1. 什么是继承

    • 继承是一种新建类的方式,新建的类称为子类,被继承的类称为父类
    • 子类会具备父类的属性,子类可以使用父类的功能
    • 注意:继承是类与类之间的关系

    2. 为什么要有继承

    • 继承的优点:可以减少代码的冗余

    3. 如何用继承

    • 定义子类的语法:class 子类名(父类名)
    • 在Python中,支持一个类同时继承多个父类
    # 父类
    class Parent1:
        pass
    
    # 子类
    class Sub(Parent1)
        pass
    
    # 查看子类继承关系
    print(Sub1.__bases__)
    ==============================执行结果如下===================================
    (<class '__main__.Parent1'>,)
    

    ① Python3和Python2中继承的区别

    • 在Python3中,如果一个类没有继承任何类,默认继承object
    • 在Python2中,如果一个类没有继承任何类,默认不会继承object
    • 新式类:只要是继承了object的类以及该类的子类,都是新式类
    • 经典类:没有继承object的类以及该类的子类,都是经典类
    • 在Python3中都是新式类,只有Python2中才区别新式类与经典类

    ② 继承多个父类

    class Parent1:
        pass
    
    class Parent2:
        pass
    
    class Sub1(Parent1,Parent2):
        pass
    
    print(Sub1.__bases__)
    ==============================执行结果如下===================================
    (<class '__main__.Parent1'>, <class '__main__.Parent2'>)
    

    4. 寻找继承关系的流程

    • 找对象的相似之处,就可以总结出类,找类相似之处,就可以总结出父类
    • 对象查找属性的顺序:对象自己--->对象的类--->父类--->父类......
    class Foo:
        def f1(self):
            print('Foo.f1')
    
        def f2(self):
            print('Foo.f2')
            self.f1()
    
    class Bar(Foo):
        def f1(self):
            print('Bar.f1')
    
    obj=Bar()
    obj.f2()
    ==============================执行结果如下===================================
    Foo.f2
    Bar.f1
    

    5. 子类派生

    • 派生:子类中新定义的属性(技能),子类在使用时,始终以自己的为准

    ① 未使用派生

    • 未使用派生和继承,代码冗余过多
    class OldboyStudent():
        school = 'oldboy'
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
        def choose_course(self):
            print('%s is choosing course' %self.name)
    
    class OldboyTeacher():
        school = 'oldboy'
        def __init__(self,name,age,sex,level):
            self.name=name
            self.age=age
            self.sex=sex
            self.level=level
        def score(self):
            print('%s in scoring' %self.name)
    
    stu1=OldboyStudent('xut',18,'male')
    tea1=OldboyTeacher('xdw',18,'male',10)
    
    stu1.choose_course()
    tea1.score()
    ==============================执行结果如下===================================
    xut is choosing course
    xdw in scoring
    

    ② 使用派生方式一

    • 在子类派生出新功能中,重用父类功能方式:指定道姓访问一个类的函数,该方式与继承无关
    • 不推荐使用这种派生,如果套的太多就,是强耦合的过程
    # 总结出共点,分出类
    class OldboyPeople:
        school='oldboy'
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
    class OldboyStudent(OldboyPeople):
        def choose_course(self):
            print('%s is choosing course' %self.name)
    
    class OldboyTeacher(OldboyPeople):
        def __init__(self,name,age,sex,level):
            # self.name=name
            # self.age=age
            # self.sex=sex
            # 派生出新的功能,指定道姓访问一个类的函数
            OldboyPeople.__init__(self,name,age,sex)
            self.level=level
        def score(self):
            print('%s in scoring' %self.name)
    
    stu1=OldboyStudent('xut',18,'male')
    tea1=OldboyTeacher('xdw',18,'male',10)
    print(stu1.__dict__)
    print(tea1.__dict__)
    ==============================执行结果如下===================================
    {'name': 'xut', 'age': 18, 'sex': 'male'}
    {'name': 'xdw', 'age': 18, 'sex': 'male', 'level': 10}
    

    ③ 子类派生出来的功能,不一定和父类有直接关系

    # 总结出共点,分出类
    class OldboyPeople:
        school='oldboy'
        def __init__(self,name,age,sex):
            self.name=name
            self.age=age
            self.sex=sex
    
    class OldboyStudent(OldboyPeople):
        def choose_course(self):
            print('%s is choosing course' %self.name)
    
    class OldboyTeacher(OldboyPeople):
        def __init__(self,name,age,sex,level):
            # self.name=name
            # self.age=age
            # self.sex=sex
            OldboyPeople.__init__(self,name,age,sex)
            self.level=level
        # 派生打分功能,和父类没有直接关系
        def score(self,stu_obj,num):
            print('%s in scoring' %self.name)
            stu_obj.score=num
    
    stu1=OldboyStudent('xut',18,'male')
    tea1=OldboyTeacher('xdw',18,'male',10)
    
    tea1.score(stu1,99)
    print(stu1.__dict__)
    ==============================执行结果如下===================================
    xdw in scoring
    {'name': 'xut', 'age': 18, 'sex': 'male', 'score': 99}
    

    相关文章

      网友评论

          本文标题:Python面向对象编程(一)

          本文链接:https://www.haomeiwen.com/subject/ilyvyftx.html