• day20-面向对象基础


    面向对象基础

    面向过程编程与面向对象编程

    面向过程编程

    面向过程编程的核心是过程,过程指的是解决问题的步骤。基于面向过程编程的思想编写程序好比在设计一条流水线,是一种机械式的思维方式。

    • 优点:逻辑清晰(逻辑一步一步的,比较系统)
    • 缺点:扩展性差(上一个函数的输出是下一个函数的输入,如果改动某项功能时会影响其他功能)

    面向对象编程

    面向对象编程的核心是对象,在python中一切皆对象,对象就是特征和技能的结合体。基于面向对象编程就是定义出一个个鲜明独特的对象,然后通过对象之间交互编程

    • 优点:扩展性非常强
    • 缺点:编程的复杂度要高于面向过程

    类与对象

    类的意思是分类、类别。比如在学校中:按照学生和老师可以划分两类,一个是学生类,他们都具有名字、学号、班级以及选课、听课;一个是老师类,他们都有名字以及授课。因此给出类的定义:类就是一系列对象相似的特征与技能的结合体

    对象

    在python中一切皆对象,根据划分称为某类下的一个对象,比如猫是动物类的对象,人是人类的对象

    在显示世界中:先有对象,再有类;在程序中,务必保证先定义类,后产生对象

    定义类和对象

    定义类:

    # 注意类中定义变量使用驼峰体
    class OldboyStudent:
        school = 'oldboy'
        def choose_course(self):
            print('is choosing course')
            
    oldboystudent_dict = OldboyStudent.__dict__  ## 双下划线开头的方法会在某种情况下自动触发
    

    曾经定义函数,函数只检测语法,不执行代码,但是定义类的时候,代码会在类定义阶段就立刻执行,并且会产生一个类的名称空间,也就是说类的本身其实就是一个容器/名称空间,是用来存放名字的,这是类的用途之一

    print(oldboystudent_dict)    # 打印的是该类名称空间里具有的名字,如我们定义的school,choose_course和内置的其他属性
    
    {'__module__': '__main__', 'school': 'oldboy', 'choose_course': <function OldboyStudent.choose_course at 0x000001BCAD3A2048>, '__dict__': <attribute '__dict__' of 'OldboyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'OldboyStudent' objects>, '__doc__': None}
    
    print(oldboystudent_dict['school'])  # 取school的值
    
    oldboy
    
    print(oldboystudent_dict['choose_course'])
    print(type(oldboystudent_dict['choose_course']))  
    
    <function OldboyStudent.choose_course at 0x000001BCAD3A2048>
    <class 'function'>
    
    oldboystudent_dict['choose_course']('nick')
    
    is choosing course
    
    print(OldboyStudent.school)
    
    oldboy
    
    OldboyStudent.choose_course('nick')
    
    is choosing course
    

    定义对象:调用类即可产生对象,调用类的过程,又称为类的实例化,实例化的结果称为类的对象/实例

    stu1 = OldboyStudent()  # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例
    print(1, stu1.school)
    stu1.choose_course()
    
    stu2 = OldboyStudent()  # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例
    print(2,stu2.school)
    stu2.choose_course()
    
    1 oldboy
    is choosing course
    2 oldboy
    is choosing course
    

    定制对象独有特征

    类中定义的函数是类的函数属性,类可以使用,对象也可以使用。如果类的属性改了,则对象的属性也会随之改变。但同一类中的对象都会具自己独特的特征,比如张三身高180,李四身高175。

    class OldboyStudent:
        school = 'oldboy'
        def choose_course(self):
            print('is choosing course')
            
    stud1 = OldboyStudent()
    stud2 = OldboyStudent()
    
    print(stud1.__dict__)
    
    {}
    
    print(stud2.__dict__)
    
    {}
    

    对象本质类似于类,也是一个名称空间,但是对象的名称空间存放对象独有的名字,而类中存放的是对象们共有的名字。因此我们可以直接为对象单独定制名字。

    stud1.name = 'nick'
    stud1.age = 18
    print(stud1.name,stud1.age)
    
    nick 18
    
    print(OldboyStudent.name)  # 在对象中定义的独有属性,不属于类
    
    ---------------------------------------------------------------------------
    
    AttributeError                            Traceback (most recent call last)
    
    <ipython-input-49-d5096aff41d0> in <module>
    ----> 1 print(OldboyStudent.name)
    AttributeError: type object 'OldboyStudent' has no attribute 'name'
    

    使用上述方法虽然让我们定制属性更简单,但是还是太麻烦了,如果可以在实例化对象的时候自动触发定时属性,那就更方便了,因此可以使用类的__init__方法。

    class OldboyStudent:
        school = 'oldboy'
        # 调用类的时候自动触发
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def choose_course(self):
            print('is choosing course')
    
    stud1 = OldboyStudent('nick', 18)
    print(stud1.__dict__, stud1.name, stud1.age)
    
    {'name': 'nick', 'age': 18} nick 18
    

    通过上述现象可以发现,调用类的时候创造了一个空对象,同时自动触发类中__init__功能,将stud1以及调用类括号内的参数一同传入

    对象属性查找顺序

    class OldboyStudent:
        school = 'oldboy'
        name = 'tank'
        # 调用类的时候自动触发
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def choose_course(self):
            print('is choosing course')
    
    stud1 = OldboyStudent('nick', 18)
    print(stud1.name, stud1.school)
    
    nick oldboy
    
    print(stud1.height)
    
    ---------------------------------------------------------------------------
    
    AttributeError                            Traceback (most recent call last)
    
    <ipython-input-61-ff2d39934944> in <module>
    ----> 1 print(stud1.height)
    AttributeError: 'OldboyStudent' object has no attribute 'height'
    
    • 类中定义name为tank,定义对象时传入name为nick,在打印stud1.name时打印的是nick。可见:当类和对象同时定义属性时,先从对象本身查找
    • 类中定义school为oldboy,对象中未定义,打印stud1.school时打印的是oldboy。可见:当对象中未定义该属性时,从类中查找
    • 类和对象都未定义时,则报错

    总结:查找属性先从对象本身查找,对象没有去类中查找,类中也没有则报错

    类与对象的绑定方法

    class OldboyStudent:
        school = 'oldboy'
        name = 'tank'
        # 调用类的时候自动触发
        def __init__(self, name, age):
            self.name = name
            self.age = age
        def choose_course(self):
            print('is choosing course')
    
    stud1 = OldboyStudent('nick', 18)  # 每次实例化对象的时候都会自动调用__init__方法(排在第一位)
    
    stud1.choose_course()
    
    is choosing course
    
    OldboyStudent.choose_course()  # 报错,提示缺少参数self
    
    ---------------------------------------------------------------------------
    
    TypeError                                 Traceback (most recent call last)
    
    <ipython-input-77-d104c34c78e5> in <module>
    ----> 1 OldboyStudent.choose_course()  # 报错,提示缺少参数self
    TypeError: choose_course() missing 1 required positional argument: 'self'
    
    OldboyStudent.choose_course('nick')  # 将nick传给形参self,类似于普通函数调用
    
    is choosing course
    

    在类调用类中定义的函数时,需要传值给self;在对象调用类中定义的函数时,不需要传入参数。

    总结:

    • 类中定义的函数是类的函数属性,类可以使用,但使用的就是一个普通的函数而已,意味着需要完全遵循函数的参数规则,该传几个值就传几个
    • 类中定义的函数对象也可以使用,而且是绑定给对象用的,绑定给谁,就应该由谁来调用,谁来调用就会将谁当作第一个参数自动传入。所以不需要传参给self
    • 类定义的函数大多情况下都是绑定给对象用的,所以在类中定义的函数都应该自带一个参数self

    类与数据类型

    之前在学习定义数据时,比如定义一个列表,可以使用lis = list([1,2,3])。其实list就是一个类,lis就是list类中的一个实例化对象。只不过这个list类是python为我们封装好的,我们可以直接调用生成一个列表。而append就是list类定义的一个函数方法,对象lis也可以直接调用。其他数据类型也是同理

    总结:python3中统一了类与类型的概念,类就是类型。因此数据类型就是将数据分成不同的类,生成一个具体的数据时就是在生成一个类的对象

    对象的高度整合

    • 以未来我们要连接数据库举例,如果没有面向对象的思想,我们只要想要使用一个方法,就必须得这样做
    import pymysql  # 连接mysql的三方库,可以pip3 install pymysql安装
    def exc1(host, port, db, charset, sql):
        conn = pymysql.connect(host, port, db, charset)
        conn.execute(sql)
        return xxx
    def exc2(proc_name):
        conn = pymysql.connect(host, port, db, charsett)
        conn.call_proc(sql)
        return xxx
    exc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t1')
    exc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t2')
    exc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t3')
    exc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t4')
    
    • 有了面向对象之后,对于上述的例子,我们可以这样做
    import pymysql
    class Foo:
        def __init__(self, host, port, db, chartset):
            self.host = host
            self.port = port
            self.db = db
            self.charset = chartset
        def exc1(self, sql):
            conn = pymysql.connect(self.host, self.port, self.db, self.charset)
            conn.execute(sql)
            return xxx
        def exc2(self, proc_name):
            conn = pymysql.connect(self.host, self.port, self.db, self.charsett)
            conn.call_proc(sql)
            return xxx
    obj1 = Foo('1.1.1.1', 3306, 'db1', 'utf-8')
    obj1.exc1('select * from t1')
    obj1.exc1('select * from t2')
    obj1.exc1('select * from t3')
    obj1.exc1('select * from t4')
    

    总结:对象其实就是一个高度整合的产物,整合数据与专门操作该数据的方法(绑定方法)

  • 相关阅读:
    Jmeter运行原理
    hihoOffer收割练习20题目2
    hihoOffer收割练习20题目1
    STL-map容器
    STL-map容器
    2017多校合练1
    2017多校合练1
    STL之map基础知识
    STL之map基础知识
    DP入门
  • 原文地址:https://www.cnblogs.com/863652104kai/p/11046939.html
Copyright © 2020-2023  润新知