一、面向对象编程
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': , '__dict__': , '__weakref__': , '__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
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__)
③ 修改类名称空间的内容
class OldboyStudent:
school='oldboy'
def choose_course(self):
print('is choosing course')
OldboyStudent.country='CHINA'
print(OldboyStudent.__dict__)
④ 删除类名称空间的内容
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>
> # 绑定方法
说明:类汇总定义的函数,类可以使用,但是,类定义的函数大多数情况下都是绑定对对象用的,因此,类中定义的函数都自带
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__)
==============================执行结果如下===================================
(,)
① Python3和Python2中继承的区别
- 在Python3中,如果一个类没有继承任何类,默认继承
object
类- 在Python2中,如果一个类没有继承任何类,默认不会继承
object
类- 新式类:只要是继承了
object
的类以及该类的子类,都是新式类- 经典类:没有继承
object
的类以及该类的子类,都是经典类- 在Python3中都是新式类,只有Python2中才区别新式类与经典类
② 继承多个父类
class Parent1:
pass
class Parent2:
pass
class Sub1(Parent1,Parent2):
pass
print(Sub1.__bases__)
==============================执行结果如下===================================
(, )
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}