Python不仅支持面向过程编程,同时也支持面向对象编程。面向过程的思想是把一个项目、一件事情按照一定的顺序,从头到尾一步一步地做下去,先做什么,后做什么,一直到结束。面向对象的思想是把一个项目、一件事情分成更小的项目,或者说分成一个个更小的部分,每一部分负责什么方面的功能,最后再由这些部分组合而成为一个整体。编写小程序(少于500行代码)时,使用面向过程编程基本上不会有任何问题。但对于中等和大型项目来说,面向对象将给代码的编写和维护带来很多优势。本文主要介绍python中面向对象的主要概念。
一、python面向对象的一些重要术语:
- 类:一个模型,一个图纸。
- 实例:根据模型做出来的东西就是实例。
- 对象:实例和对象是一回事。
- 实例化:就是根据模型做具体东西的过程。
- self:本类对象。
- 属性:属性就是类里面的一个变量,有类变量和实例变量,类变量是类在定义的时候就有的,实例变量是在实例化的时候才产生的变量。这个可以理解为,人是一个类,他的名字、年龄、性别就是它的属性。
- 方法:方法就是类的功能,也就是定义在类里面的函数,它实现了某个功能,比如说人有睡觉的功能。
- 继承:继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类。私有方法、私有变量不会被继承。
- 抽象类:一个规范,
- 封装:三个层面的封装,第一,类本身就是一种封装;第二,类中定义私有的,只在类的内部使用外部无法访问;第三,明确区分内外,内部的实现逻辑,外部无法知晓,并且为封装到内部的逻辑提供一个访问接口给外部使用
- 静态方法:只是写在类里面的一个方法,不能使用类变量,调用不了其他的类方法
- 实例方法:必须要实例化之后才能使用的函数。
- 实例变量:类的属性就是变量,必须要实例化之后才能使用的变量
- 类变量:在类里面直接定义的变量
- 类方法:不用实例化,通过类名就可以直接调用的方法,用实例也可以调用
- 属性方法:看起来像变量的一个函数。
- 构造函数:类在实例化的时候自动调用的方法,即类在实例化的时候做的某些初始化操作,比如说人,你造一个汽车的时候,它得有颜色、型号等等。
- 析构函数:实例被销毁的时候自动调用的方法
- 私有方法:只能在类里面调用,出了类就不行了
- 私有变量:只能在里面用,出了类就不行了
二、面向过程和面向对象示例
1 #============================================
2 #面向过程:将事情实现的过程按步骤写成函数,一步步调用
3 #============================================
4 #执行者
5 #1、4s店,买车
6 #2、保险公司
7 #3、税务局
8 #4、交管所 上牌
9 #============================================
10 def buyCar():
11 print('买车')
12 def baoxian():
13 print('保险')
14 def jiaoshui():
15 print('交税')
16 def shangpai():
17 print('上牌')
18 buyCar()
19 baoxian()
20 jiaoshui()
21 shangpai()
22 #===============================================
23 #面向对象:将事情拆分为对象,每个对象里对应实现自己的功能
24 #===============================================
25 #1、买车处 -》指挥者
26 #1、4s店,买车
27 #2、保险公司
28 #3、税务局
29 #4、交管所 上牌
30 #===============================================
31 class BuyCar:
32 def buyCar(self,):
33 print('买车')
34
35 def baoxian(self,):
36 print('保险')
37
38 def jiaoshui(self,):
39 print('交税')
40 def shangpai(self):
41 print('上牌')
42 xw = BuyCar() #实例化
43 xw.buyCar() #调用实例方法
44 xw.buyCar()
45 xw.baoxian()
46 xw.jiaoshui()
47 xw.shangpai()
三、定义类、封装、继承和多态
1、定义类:
定义类使用class关键字,类名一般我们开发的时候首字母要大写。python中有经典类和新式类,他俩在python3中没有区别,在python2中经典类在多继承的时候是深度优先,新式类是广度优先。python3中统一是广度优先。
class Person(): # 定义类,这个是新式类
country = 'China' # 类属性
def __init__(self, name, uid): # 构造函数
self.name = name # 实例属性
self.uid = uid
def __del__(self): # 析构函数
print('这个是析构函数')
def info(self): # 方法
print('name is %s uid is %s ' % (self.name, self.uid))
class Person1: #经典类
#属性就是变量
#功能就是函数
country='China' #类变量
def __init__(self,uid,name): #构造函数 实例化时自动执行的函数
print('self的内存地址:',id(self))
self.id = uid #实例变量 实例化才能使用,存在实例里面
self.name = name
def cook(self): #实例函数 实例化后才能执行的函数
print('%s鱼香肉丝'%self.name)
def housework(self):
print('%s正在做家务' %self.name)
if __name__ == '__main__':
Person.country='Japan' #修改的是公共类变量,之后的调用会受影响
xh=Person1(1,'xiaohei') #实例化,因为在上面的构造函数里面指定了必须传uid和name,所以在实例化的时候要把name和uid传进去
print('xh的内存地址',id(xh)) #xh就是self,与构造函数里
print('类变量公共的',xh.country)
xh.cook()#调用实例方法
xh.housework()
xh.country='USA' #修改的只是xh的,不影响小白的
xb=Person1(2,'xiaobai')
print(xb.country)
xb.cook()
xb.housework()
2、封装
三个层面的封装,第一,类本身就是一种封装;第二,类中定义私有的,只在类的内部使用外部无法访问;第三,明确区分内外,内部的实现逻辑,外部无法知晓,并且为封装到内部的逻辑提供一个访问接口给外部使用
1 import pymysql
2 class Db:
3 4 def __init__(self,host,user,password,db,port=3306,charset='utf8'):
5 #构造函数,类在实例化的时候会自动执行构造函数
6 self.db_info = {'user':user,'password':password,"db":db,"port":port,'charset':charset,
7 'autocommit':True,'host':host}
8 self.__connect() #调用类自己的私有方法,连接数据库
9 def __del__(self):
10 self.__close() #调用类的私有方法
11 print('关闭数据库')
12
13 def __connect(self): #加__后变成私有方法,只能在类的内部调用,外部访问不到
14 try:
15 self.conn = pymysql.connect(**self.db_info) # 建立连接
16 except Exception as e:
17 print("连接不上数据库")
18 raise Exception("连接不上数据库,请检查数据库连接信息")
19 else:
20 self.cur = self.conn.cursor(pymysql.cursors.DictCursor) #创建游标
21
22 def execute_many(self,sql):
23 self.cur.execute(sql) #执行sql,获取全部数据
24 return self.cur.fetchall()
25
26 def execute_one(self,sql):
27 self.cur.execute(sql) #执行sql,获取一条数据
28 return self.cur.fetchone()
29
30 def __close(self): #私有方法,关闭数据库的连接
31 self.conn.close()
32 self.cur.close()
33
34 def export_excel(self,table_name):
35 pass
36
37 if __name__ == '__main__':
38 mysql = Db('xxx.24.3.40','xxx,'123456','jxz') #类实例化,init函数有多少个参数就传入对应的参数
39 result = mysql.execute_one('select * from app_myuser;') #实例方法可调用多
40 result = mysql.execute_one('select * from app_myuser;')
3、继承
继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。
- 含义一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)
- 含义二:声明某个子类兼容于某个基类,定义一个接口类,子类继承接口类,并且实现接口中定义的方法。
- 接口继承:实际上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无须关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这个在程序设计上叫做归一化。(归一化使得高层的外部使用者可以不加区分的处理所有的接口兼容的对象集合)
1 #========================单继承=========================================================
2 class F(object):
3 '''这个是父类'''
4 def __init__(self,name,sex):
5 self.name = name
6 self.sex = sex
7 def info(self):#方法
8 print('name is %s sex is %s '%(self.name,self.sex))
9
10 class S(F):#继承F这个类
11 pass
12 s1 = S('小黑','男')#实例化子类
13 s1.info()#因为继承父类,所以父类的方法他都有
14
15 #那如果在父类里面有一个方法,子类里面也有的话,但是子类想重写一下父类的方法,增加新功能下面这么写:
16 class BaseDb:
17 def __init__(self,host,password,port,db):
18 self.db_info = {'host':host,'password':password,
19 'port':port,'db':db}
20
21 def connect(self):
22 pass
23
24 class MySql(BaseDb):
25 #def __init__(self,host):
26 # self.db_info['autocommit'] = True #重写父类方法属性
27
28 #在父类的方法基础上做扩展
29 def __init__(self,host,password,port,db,user,charset='utf8'):
30 #Mysql.__init__(host,password,port,db)#修改父类的方法,经典类的写法
31 super().__init__(host,password,port,db) #新式类的写法,与上面的效果一样
32 self.db_info['user'] = user
33 self.db_info['charset'] = charset
34 self.db_info['autocommit'] = True
35
36 def connect(self):
37 pass
1 #==================多继承=======================================================
2 # 多继承,上面写的都是单继承的,python里面还支持多继承,多继承就是继承多个父类
3 # 在python3中多继承都是广度优先的,在python2中有点不同,经典类是深度优先,新式类是广度优先。
4 class Lw:
5 money = 500000
6 def make_money(self):
7 print('挣钱 50000')
8 def __driver(self): #siy
9 print('开车')
10
11 class Ll:
12 def cook(self):
13 print('做饭')
14 def make_money(self):
15 print('挣钱一万')
16
17 class Xw(Lw,Ll):
18 def make_money(self): #重写
19 print('挣钱')
20
21 if __name__ == '__main__':
22 xw = Xw()
23 # print(Xw.mro())
24 print(xw.money)
25 xw.make_money()
26 xw.cook()
4、多态
python里面是不直接支持多态的,可以通过别的方法来实现多态。通过下面的例子就可以实现一种接口,多种实现,对于下面的cry方法来说,不管你传入的是什么对象,只要有cry的方法,都会去调用它的cry方法,不用再一个个的去调用了。
1 #多态实例
2 class Animal(object):
3 '''
4 父类
5 '''
6 def __init__(self, name):
7 self.name = name
8
9 class Dog(Animal):
10 '''
11 狗类,有叫的方法
12 '''
13 def cry(self):
14 print('狗 [%s] 汪汪汪' % self.name)
15
16 class Cat(Animal):
17 '''
18 猫类,有叫的方法
19 '''
20 def cry(self):
21 print('猫 [%s] 喵喵喵' % self.name)
22
23 def cry(obj):
24 '''
25 定义一个函数,去调用传进来的实例的cry方法
26 '''
27 obj.cry()
28
29 d1 = Dog('大黄') # 实例化狗
30 d2 = Dog('小黄') # 实例化狗
31 c1 = Cat('小白') # 实例化猫
32 c2 = Cat('小黑') # 实例化猫
33 cry(d1) # 把对象d1传进来
34 cry(d2) # 把对象d2传进来
35 objs = [d1, d2, c1, c2] # 把上面实例化的对象都放到一个list里面
36 for obj in objs: # 循环统一调用
37 cry(obj)