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')

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

posted @ 2019-06-18 18:48  Never&say&die  阅读(123)  评论(0编辑  收藏  举报