【Python】第三模块:面向对象&网络编程基础 第1章 面向对象
- 我的失败与梦想(一)
- 我的失败与梦想之为何创办路飞学城
- 01-编程范式
- 02-面向过程编程
- 03-面向对象编程介绍
- 04-定义类与实例化出对象
- 05-如何使用类
- 06-如何使用对象
- 07-属性查找与绑定方法
- 08-Python中一切皆对象
- 09-面向对象可拓展性总结
- 10-小练习1
- 11-小练习2
- 12-继承与重用性
- 13-派生
- 14-继承的实现原理
- 15-在子类中重用父类的方法或属性
- 16-组合
- 17-抽象类与归一化
- 18-多态与多态性
- 19-封装之如何隐藏属性
- 20-封装的意义
- 21-封装与可拓展性
- 22-Property的使用
- 23-绑定与非绑定方法介绍
- 24-绑定方法与非绑定方法的使用
- 25-反射
- 26-内置方法介绍
- 27-元类介绍
- 28-自定义元类控制类的创建
- 29-自定义元类与控制类的实例化行为
- 30-自定义元类与控制类的实例化行为的应用
- 31-面向对象的软件开发与作业介绍
- 32-什么是异常处理
- 33-try...except...详细用法
我的失败与梦想(一)
我的失败与梦想之为何创办路飞学城
01-编程范式
1、什么是面向对象编程?!编程范式
- 数据结构:字符串、整型、列表、元组、字典、集合等,用来高效地存储数据;
- 算法:编写程序的逻辑或者解决问题的流程;
- 编程范式:武林中的各种流派;一大是面向过程,另一大是面向对象;
02-面向过程编程
1、面向过程编程;
核心是过程二字,过程是指解决问题的步骤,即设计一条流水线,先做什么,后做什么,再做什么,是一种机械式的思维方式;
- 优点:把复杂的问题流程化,进而简单化;
- 缺点:可拓展性比较差,应用场景:扬长避短,系统监控脚本,系统部署脚本,即需求变动不大的场景;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/12 0012 5:21
#需求,写一个网站用户注册功能;使用面向过程的编程范式;
import json,re def interactive(): name = input('>>:').strip() passwd = input('>>:').strip() #拓展需求; email = input('>>:').strip() return { 'name':name, 'passwd':passwd, 'email':email, } def check(user_info): is_valid = True if len(user_info['name']) == 0: print('用户名不能为空。') is_valid = False if len(user_info['passwd']) < 6: print('密码不能少于6位。') is_valid = False # 拓展需求; if not re.search(r'@.*?\.com$',user_info['email']): print('邮箱格式不合法。') is_valid = False return { 'is_valid':is_valid, 'user_info':user_info, } def register(check_info): if check_info['is_valid']: with open(file='db.json',mode='w',encoding='utf-8') as f: json.dump(check_info['user_info'],f) #定义主函数main() def main(): user_info = interactive() check_info = check(user_info) register(check_info) if __name__ == '__main__': main()
03-面向对象编程介绍
1、面向对象:特征与技能的结合体即对象,比如孙悟空:外形特征毛脸雷公嘴,手持金箍棒,具备七十二变化,火眼金睛等技能(上帝的思维方式,在上帝眼里,一切皆对象!);
- 优点:是面向过程的缺点,即可拓展性强;
- 缺点:是面向过程的优点,编程复杂性高;
- 应用场景:用户需求经常变化,比如和互联网应用、游戏、企业内部应用,比如OA、ERP;
04-定义类与实例化出对象
1、类的定义:即一系列对象相似的特征与技能的结合体(一系列相似的对象成为类),比如人类,猪类,狗类,电脑类,笔类,花类;
强调:站在不同的角度,得到的分类是不一样的,比如站在实体的角度,人和铅笔、计算机是一类;站在生物的角度,以上就不是相同的一类;
2、先有类还是先有对象?!
- 在现实世界中:先有对象,对象自我学习后总结出类的概念,比如人类,猪类、狗类、生物类;
- 在程序中:一定得先定义类,后通过调用类来产生对象;类相当于模版!比如公司招聘人的时候,会定义一个岗位招聘标准,这个标准就相当于类!那么研发部的全体成员成为技术类群体;
3、站在路飞学城的角度,大家都是学生;
- 在现实世界中:对象1、2、3的特征与技能;
- 总结现实中路飞学城的学生类:1、相似的特征;2、相似的技能;
- 在程序中,一定是先定义类,后产生对象,注意该顺序;
4、定义类的方式(方法);
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/12 0012 5:47 "" """ 1、将对象进行分类,比如PC、笔记本; """ #使用clasee关键字,先定义类; class LuffyStudent:#类名首字母大写; school = 'luffycity' def learn(self):#技能就是功能,通过函数方式进行定义! print('is learning.') def eat(self): print('is eating.') def sleep(self): print('is sleeping.') #后产生对象; student1 = LuffyStudent()#类产生对象的这个过程也称为实例化的过程;类名加()有别于函数名加括号; student2 = LuffyStudent() student3 = LuffyStudent() print(student1)#<__main__.LuffyStudent object at 0x000001E494370B00>#对象在类中的内存地址; print(student2)#<__main__.LuffyStudent object at 0x000001E494370B38> print(student3)#<__main__.LuffyStudent object at 0x000001E494370AC8>
05-如何使用类
1、类的增删改查;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/12 0012 6:05 #先定义类; class LuffyStudent:#类名首字母大写; school = 'luffycity'#特征,以变量的形式定义; def learn(self):#技能1,以函数的形式定义; print('is learning.') def eat(self):#技能2,以函数的形式定义; print('is eating.') def sleep(self):#技能3,以函数的形式定义; print('is sleeping.') #查看类的名称空间; print(LuffyStudent.__dict__)#{'__module__': '__main__', 'school': 'luffycity', 'learn': <function LuffyStudent.learn at 0x000001A59EE71AE8>, 'eat': <function LuffyStudent.eat at 0x000001A59EE71EA0>, 'sleep': <function LuffyStudent.sleep at 0x000001A59EE71B70>, '__dict__': <attribute '__dict__' of 'LuffyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'LuffyStudent' objects>, '__doc__': None} print(LuffyStudent.__dict__['school'])#luffycity print(LuffyStudent.__dict__['learn'])#<function LuffyStudent.learn at 0x0000021C5B221AE8> """ 类内部定义的变量称之为:数据属性; 类内部定义的函数称之为:函数属性; """ #import time #time.sleep(1) #查看; print(LuffyStudent.school)#luffycity print(LuffyStudent.learn)#<function LuffyStudent.learn at 0x000002A0CD0B1AE8> #增加; LuffyStudent.country = 'China'#定义新的数据属性(即公共的特性,变量名),进行赋值; #print(LuffyStudent.__dict__) #使用专门的语法进行; print(LuffyStudent.country)#China #删除; del LuffyStudent.country print(LuffyStudent.__dict__)#发现country已经被删除; #print(LuffyStudent.country)#AttributeError: type object 'LuffyStudent' has no attribute 'country' #改; LuffyStudent.school = 'Luffycity'#即重新赋值; print(LuffyStudent.school)#Luffycity """ 小结: 1、函数名加(),执行函数; 2、类名加(),实例化得到一个对象; 3、类的用途:对类属性的操作——增删改查;实例化产生出对象;
4、类与函数的区别,类在定义阶段,就已经被执行;
5、类的两大操作,第一,类的增删改查;第二,类的实例化产生对象; """
06-如何使用对象
1、对象的增删改查操作;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/12 0012 6:41 #__init__方法,用来为对象定制对象自己独有的特征;比如崔晓昭、崔晓珊、崔晓思、崔晓磊都属于崔家类,但都有各自的属性;比如职业、年龄、身高、体重、价值观等等; #先定义类; class LuffyStudent:#类名首字母大写; school = 'luffycity' #student1,'王二丫','女',18 def __init__(self,name,sex,age): self.name = name self.sex = sex self.age = age #student1.Name='王二丫' #student2.Sex='女' #student3.Age=18 def learn(self): print('is learning.') def eat(self): print('is eating.') def sleep(self): print('is sleeping.') #后产生对象; #student1 = LuffyStudent()#TypeError: __init__() missing 3 required positional arguments: 'name', 'sex', and 'age' #进行类的实例化的时候,Python会自动调用__init__对象; student1 = LuffyStudent('王二丫','女',18) #加上__init__方法后,实例化的步骤; """ 1、先产生一个空对象student1; 2、LuffyStudent.__init__(student1,'王二丫','女',18) """ #查询; print(student1.__dict__)#{'Name': '王二丫', 'Sex': '女', 'Age': 18} print(student1.name)#王二丫 print(student1.age)#18 print(student1.sex)#女 #改-即对对象的重新赋值操作; student1.Name = '李静瓶' print(student1.__dict__)#{'Name': '李静瓶', 'Sex': '女', 'Age': 18} print(student1.Name)#李静瓶 #删除 del student1.Name#使用del 方法; print(student1.__dict__) #增加 student1.Course = 'Python全栈开发'#{'name': '王二丫', 'sex': '女', 'age': 18, 'Course': 'Python全栈开发'} print(student1.__dict__) #如何产生对象2:student2操作 student2 = LuffyStudent('李三炮','男',38) print(student2.__dict__)#{'Name': '李三炮', 'Sex': '男', 'Age': 38} print(student2.name)#李三炮 print(student2.age)#38 print(student2.sex)#男 #问题1:在对象中,能否访问到类里面的公共属性呢?!
07-属性查找与绑定方法
1、绑定方法与属性查找;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/12 0012 7:04 #先定义类; class LuffyStudent:#类名首字母大写; school = 'luffycity' #student1,'王二丫','女',18 def __init__(self,name,sex,age): self.Name = name self.Sex = sex self.Age = age #student1.Name='王二丫' #student2.Sex='女' #student3.Age=18 def learn(self): #print('is learning.') print('%s is learning'%self.Name) def eat(self): print('is eating.') def sleep(self): print('is sleeping.') #后产生对象; #student1 = LuffyStudent()#TypeError: __init__() missing 3 required positional arguments: 'name', 'sex', and 'age' #Python会自动调用__init对象; student1 = LuffyStudent('王二丫','女',18) student2 = LuffyStudent('李三炮','男',38) student3 = LuffyStudent('张铁蛋','男',48) print(student1.__dict__) print(student2.__dict__) print(student3.__dict__) "" {'Name': '王二丫', 'Sex': '女', 'Age': 18} {'Name': '李三炮', 'Sex': '男', 'Age': 38} {'Name': '张铁蛋', 'Sex': '男', 'Age': 48} "" #对象:特征与技能的结合体,比如孙悟空这个角色; #类:类是一系列对象相似的特征与相似的技能的结合体; #类中的数据属性:是所有的对象公共的即共有的; print(LuffyStudent.school) print(student1.school,id(student1.school)) print(student2.school,id(student2.school)) print(student3.school,id(student3.school)) """ luffycity luffycity 2904853177648 luffycity 2904853177648 luffycity 2904853177648 """ #类中的函数属性:是绑定给对象使用的,绑定到不同的对象是不同的绑定方法; #对象调用绑定方法时候,会把对象本身,当做第一个函数传入,传给self; print(LuffyStudent.learn) print(student1.learn) print(student2.learn) print(student3.learn) """ <function LuffyStudent.learn at 0x00000234A0FC1B70>#函数; <bound method LuffyStudent.learn of <__main__.LuffyStudent object at 0x00000234A0FC5C88>>#bound method绑定方法; <bound method LuffyStudent.learn of <__main__.LuffyStudent object at 0x00000234A0FC5CC0>> <bound method LuffyStudent.learn of <__main__.LuffyStudent object at 0x00000234A0FC5CF8>> """ #LuffyStudent.learn()#TypeError: learn() missing 1 required positional argument: 'self' LuffyStudent.learn(student1)#王二丫 is learning student1.learn()#王二丫 is learning """ 小结: 1、类中定义的函数是给对象使用的,绑定给对象使用,不同的对象具备相同的技能,但内存地址不一致; """ student1.x = 'from student1'#给对象增加一个属性; LuffyStudent.x = 'from LuffyCity class ' print(student1.__dict__)#{'Name': '王二丫', 'Sex': '女', 'Age': 18, 'x': 'from student1'} print(student1.x)#from student1
08-Python中一切皆对象
1、一切皆对象的解释说明;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/12 0012 7:30 "" """ 小结: 1、站的角度不同,定义出的类是截然不同的; 2、现实生活中的类不完全等于程序中的类,比如现实中的公司类,在程序中有时需要拆分成部门类、业务类等; 3、有时候为了编程需求,程序中也有可能会定义现实中不存在的类,比如策略类,现实中并不存在,但是在程序中却是一个很常见的类; 补充: 1、Python当中一切皆对象,Python3.x中统一了类与数据类型的概念; """ #先定义类; class LuffyStudent:#类名首字母大写; school = 'luffycity' #student1,'王二丫','女',18 def __init__(self,name,sex,age): self.Name = name self.Sex = sex self.Age = age #student1.Name='王二丫' #student2.Sex='女' #student3.Age=18 def learn(self): #print('is learning.') print('%s is learning'%self.Name) def eat(self): print('is eating.') def sleep(self): print('is sleeping.') print(LuffyStudent) print(list) """ <class '__main__.LuffyStudent'> <class 'list'> """ l1 = [1,2,3]#等价于,l1 = list([1,2,3]) l2 =[]#等价于,l2 = list([]) #列表的内置方法; l1.append(4) print(l1)#[1, 2, 3, 4] print(l2)#[] list.append(l1,4)#虽然可以实现功能,但是没人这么用,我们都是使用对象的绑定方法;比如l1.append() print(l1)#[1, 2, 3, 4, 4],效果等价于l1.append(4)
#总结:针对于对象,我们使用的都是对象的绑定方法来操作;可以简单理解,类就是我们自定义的list、tuple、set等数据类型;
09-面向对象可拓展性总结
1、面向对象拓展性总结;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/12 0012 7:40 "" class Chinese: country = 'China' def __init__(self,name,sex,age): self.Name = name self.Sex = sex self.Age = age #student1.Name='王二丫' #student2.Sex='女' #student3.Age=18 def learn(self): #print('is learning.') print('%s is learning'%self.Name) def eat(self): print('%s is eating.'%self.Name) p1 = Chinese('egon',18,'male') p2 = Chinese('alex',38,'female') p3 = Chinese('wqp',48,'female') print(p1.country)#china print(p2.country)#china print(p3.country)#china p1.eat() p2.eat() p3.eat() """ egon is eating. alex is eating. wqp is eating. """
从代码级别看面向对象 1、在没有学习类这个概念时,数据与功能是分离的; def exc1(host,port,db,charset): conn=connect(host,port,db,charset) conn.execute(sql) return xxx def exc2(host,port,db,charset,proc_name)#proc_name是MySQL中的存储过程; conn=connect(host,port,db,charset) conn.call_proc(sql) return xxx #每次调用都需要重复传入一堆参数; exc1('127.0.0.1',3306,'db1','utf8','select * from tb1;') exc2('127.0.0.1',3306,'db1','utf8','存储过程的名字') 2、我们能想到的解决方法是,把这些变量都定义成全局变量; HOST=‘127.0.0.1’#大写字母代表常量; PORT=3306 DB=‘db1’ CHARSET=‘utf8’ def exc1(host,port,db,charset): conn=connect(host,port,db,charset) conn.execute(sql) return xxx def exc2(host,port,db,charset,proc_name) conn=connect(host,port,db,charset) conn.call_proc(sql) return xxx exc1(HOST,PORT,DB,CHARSET,'select * from tb1;') exc2(HOST,PORT,DB,CHARSET,'存储过程的名字') 3、但是2的解决方法也是有问题的,按照2的思路,我们将会定义一大堆全局变量,这些全局变量并没有做任何区分,即能够被所有功能使用,然而事实上只有HOST,PORT,DB,CHARSET是给exc1和exc2这两个功能用的。言外之意:我们必须找出一种能够将数据与操作数据的方法组合到一起的解决方法,这就是我们说的类了 class MySQLHandler:#注意此处没有(); def __init__(self,host,port,db,charset='utf8'): self.host=host self.port=port self.db=db self.charset=charset self.conn=connect(self.host,self.port,self.db,self.charset) def exc1(self,sql): return self.conn.execute(sql) def exc2(self,sql): return self.conn.call_proc(sql) obj=MySQLHandler('127.0.0.1',3306,'db1') obj.exc1('select * from tb1;') obj.exc2('存储过程的名字') 总结使用类可以: 1、将数据与专门操作该数据的功能整合到一起; 2、可扩展性高; 3、定义类并产生三个对象; class Chinese: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex p1=Chinese('egon',18,'male') p2=Chinese('alex',38,'female') p3=Chinese('wpq',48,'female') 如果我们新增一个类属性,将会立刻反映给所有对象,而对象却无需修改; class Chinese: country='China' def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def tell_info(self): info=''' 国籍:%s 姓名:%s 年龄:%s 性别:%s ''' %(self.country,self.name,self.age,self.sex) print(info)
p1=Chinese('egon',18,'male') p2=Chinese('alex',38,'female') p3=Chinese('wpq',48,'female') print(p1.country) p1.tell_info()
10-小练习1
1、练习No.01;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/12 0012 21:03 "" """ 1、练习1:编写一个学生类,产生一堆学生对象; 要求: 有一个计算器(属性),统计总共实例化了多少个对象。count方法统计; """ class Student:#定义一个Student类名,注意首字母大写; school = 'luffycity' count = 0#在类中定义计数器变量count def __init__(self,name,age,sex):#约定俗称,大家都写self,可以写成其他的,但是没人这么干! self.name = name self.age = age self.sex = sex #self.Come = come Student.count +=1#通过类名的count方法统计调用次数,每调用一次,自增1; #self.count = self.count+1 def learn(self): print('%s is learning'%self.name) #实例化; stu1=Student('alex','male',38) stu2=Student('jinxing','female',78) stu3=Student('egon','male',18) print(Student.count) print(stu1.count) print(stu2.count) print(stu3.count) print(stu1.__dict__) print(stu2.__dict__) print(stu3.__dict__) """ 3 3 3 3 {'Name': 'alex', 'Age': 'male', 'Sex': 38} {'Name': 'jinxing', 'Age': 'female', 'Sex': 78} {'Name': 'egon', 'Age': 'male', 'Sex': 18} """
11-小练习2
1、练习No.02;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/12 0012 21:20 "" """ 1、练习2:模仿LOL定义两个英雄类; 要求: 1、英雄需要有昵称、攻击力、生命值等属性; 2、实例化出两个英雄对象; 3、英雄之间可以互殴,被殴打的一方开始掉血,血量小于0则判定为死亡; """ #定义LOL中英雄的名称; class Garen: camp = 'Demacia'#德玛西亚; def __init__(self,nickname,life_value,aggresivity): self.nickname = nickname self.life_value = life_value self.aggresivity = aggresivity def attact(self,enemy): enemy.life_value -= self.aggresivity class Riven: camp = 'Noxus'#xxxx; def __init__(self,nickname,life_value,aggresivity): self.nickname = nickname self.life_value = life_value self.aggresivity = aggresivity def attact(self,enemy): enemy.life_value -= self.aggresivity g1=Garen('草丛伦',100,30) r1 = Riven('可爱的芮雯雯',80,50) #打印初始生命值; print(r1.life_value)#80 g1.attact(r1) #打印被攻击一次后的生命值; print(r1.life_value)#50
12-继承与重用性
1、初识继承;
继承指的是类与类之间的关系,是一种什么“是”什么的关系,继承的功能之一就是用来解决代码重用问题;
继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可以成为基类或超类,新建的类称为派生类或子类;
- python中类的继承分为:单继承和多继承;
class ParentClass1: #定义父类; pass class ParentClass2: #定义父类; pass class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass; pass class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类; pass
- 查看继承
>>> SubClass1.__bases__ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类; (<class '__main__.ParentClass1'>,) >>> SubClass2.__bases__ (<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)
- 经典类与新式类
1.只有在python2中才分新式类和经典类,python3中统一都是新式类; 2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类; 3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类; 4.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类;
2、如何来理解抽象,抽出对象或类相似的地方,叫做抽象;
3、抽象分成两个层次:
- 1、将奥巴马和梅西这俩对象比较像的部分抽取成类;
- 2、将人、猪、狗这三个类比较像的部分抽取成父类;
- 3、抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度);
继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
# #!/usr/bin/env python # # -*- coding:utf-8 -*- # # __Author__:Administrator # # Version:python3.6.5 # # Date:2018/6/12 0012 21:38 # #定义一个父类1; # class ParentClass1: # pass # #定义一个父类2; # class ParentClass2: # pass # #定义一个子类1; # class SubClass1(ParentClass1): # pass # #定义一个子类2;同时继承两个父类; # class SubClass2(ParentClass1,ParentClass2): # pass
#__bases__方法,查看继承了哪个父类;
# print(SubClass1.__bases__)#(<class '__main__.ParentClass1'>,) # print(SubClass2.__bases__)#(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>) #解决代码之间冗余问题; class Hero:#定义一个英雄类; x = 3 def __init__(self,nickname,life_value,aggresivity):#属性; self.nickname = nickname self.life_value = life_value self.aggresivity = aggresivity def attact(self,enemy):#攻击技能; enemy.life_value -= self.aggresivity class Garen(Hero): #x = 2 pass#德玛西亚; class Riven(Hero): pass g1=Garen('刚们',29,30) print(g1.nickname,g1.life_value,g1.aggresivity)#刚们 29 30; #继承,实现代码的重用性! #那么问题来了,属性的查找顺序是怎样的? #g1.x =1 print(g1.x) #属性查找的小练习; class Foo: def f1(self): print('from Foo.f1') def f2(self): print('from Foo.f2') self.f1()#b.f1(),注意查找顺序,从下往上查找; class Bar(Foo): def f1(self): print('from Bar.f1') b = Bar() print(b.__dict__) b.f2() b.f1()#注意查找顺序; """
from Foo.f2
from Bar.f1 from Bar.f1 """
13-派生
1、派生的概念引入;
- 在继承的基础上,衍生出新的技能;
- 当子类派生出新的技能时候,优先使用自身;
- 当然子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/12 0012 22:17 #派生的概念引入; class Hero:#定义一个英雄类; def __init__(self,nickname,life_value,aggresivity):#属性; self.nickname = nickname self.life_value = life_value self.aggresivity = aggresivity def attact(self,enemy):#攻击技能; enemy.life_value -= self.aggresivity class Garen(Hero): camp ='Demacia'#德玛西亚; class Riven(Hero): camp = 'Noxus' g = Garen('草丛伦',100,30) r = Riven('锐雯雯',80,50) print(g.camp)#Demacia g.attact(r) print(r.life_value)#50
14-继承的实现原理
1、继承的实现原理;
python到底是如何实现继承的,对于我们定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如;
>>> F.mro() #等同于F.__mro__
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>,
<class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
- 子类会先于父类被检查;
- 多个父类会根据它们在列表中的顺序被检查;
- 如果对下一个类存在两个合法的选择,选择第一个父类;
在Java和C#中子类只能继承一个父类,而Python中子类可以同时继承多个父类,如果继承了多个父类,那么属性的查找方式有两种,分别是:深度优先和广度优先;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/12 0012 22:27 "" """
Python分为两种类;
1、新式类; 2、经典类; 在Python2中,没有继承object的类以及它的子类都称之为经典类;
在Python2中,继承了object的类以及它的子类都称之为新式类; """ # class Foo: # pass # class Bar(Foo): # pass # #在Python3中统一为新式类,一个类没有继承object类,默认就继承object; # class Foo(): # pass # print(Foo.__bases__) #验证多继承情况下的属性查找顺序; class A(object):#Python2中经典类去掉object # def test(self): # print('from A') pass#AttributeError: 'F' object has no attribute 'test' class B(A): # def test(self): # print('from B') pass class C(A): # def test(self): # print('from C') pass class D(B): # def test(self): # print('from D') pass class E(C): # def test(self): # print('from E') pass class F(D,E): # def test(self): # print('from F') pass #FDBECA # f=F() # f.test() print(F.mro())#[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性;
#新式类继承顺序:F->D->B->E->C->A;
#经典类继承顺序:F->D->B->A->E->C;
#python3中统一都是新式类;
#pyhon2中才分新式类与经典类;
15-在子类中重用父类的方法或属性
1、子类中重用父类的方法或属性;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/13 0013 23:22 # class Hero:#定义一个英雄类; # def __init__(self,nickname,life_value,aggresivity):#属性; # self.nickname = nickname # self.life_value = life_value # self.aggresivity = aggresivity # def attact(self,enemy):#攻击技能; # enemy.life_value -= self.aggresivity # class Garen(Hero): # camp ='Demacia'#德玛西亚; # def attack(self,enemy): # Hero.attact(self.enemy)#在子类当中,重用父类的方法,即指名道姓的重用父类的方法; # print('from Garen Class') # # class Riven(Hero): # camp = 'Noxus' # # g = Garen('草丛伦',100,30) # r = Riven('锐雯雯',80,50) # # print(r.life_value)#80 # g.attact(r)#进行攻击; # print(r.life_value)#50; # class Hero:#定义一个英雄类; # def __init__(self,nickname,life_value,aggresivity):#属性; # self.nickname = nickname # self.life_value = life_value # self.aggresivity = aggresivity # def attact(self,enemy):#攻击技能; # enemy.life_value -= self.aggresivity # class Garen(Hero): # camp ='Demacia'#德玛西亚; # def __init__(self,nickname,life_value,aggresivity,weapon): # #self.nickname = nickname # #self.life_value = life_value # #self.aggresivity = aggresivity # self.weapon = weapon # Hero.__init__(self,nickname,life_value,aggresivity)#实现了代码节省的方法; # def attack(self,enemy): # Hero.attact(self.enemy)#指名道姓; # print('from Garen Class') # # # # #g = Garen('草丛伦',100,30)#TypeError: __init__() missing 1 required positional argument: 'weapon' # g = Garen('草丛伦',100,30,'金箍棒') # print(g.__dict__)#{'nickname': '草丛伦', 'life_value': 100, 'aggresivity': 30, 'weapon': '金箍棒'} "" """ 1、在子类派生出的新的方法中重用父类的方法,有两种实现方式; 方式一:指名道姓(不依赖继承); 方式二:super()方法(依赖继承); """ #方式二:super()方法; # class Hero:#定义一个英雄类; # def __init__(self,nickname,life_value,aggresivity):#属性; # self.nickname = nickname # self.life_value = life_value # self.aggresivity = aggresivity # def attack(self,enemy):#攻击技能; # enemy.life_value -= self.aggresivity # # class Garen(Hero): # camp = 'Demacia'#德玛西亚; # def attack(self,enemy): # super(Garen,self).attack(enemy)#依赖继承的方式,进行重用父类的方法; # print('from Garen Class') # # class Riven(Hero): # camp = 'Noxus' # # g = Garen('草丛伦',100,30) # r = Riven('锐雯雯',80,50) # g.attack(r) # print(r.life_value) # class Hero:#定义一个英雄类; # def __init__(self,nickname,life_value,aggresivity):#属性; # self.nickname = nickname # self.life_value = life_value # self.aggresivity = aggresivity # def attact(self,enemy):#攻击技能; # enemy.life_value -= self.aggresivity # class Garen(Hero): # camp ='Demacia'#德玛西亚; # def attack(self,enemy): # Hero.attact(self.enemy)#指名道姓; # print('from Garen Class') # # class Riven(Hero): # camp = 'Noxus' # # g = Garen('草丛伦',100,30) # r = Riven('锐雯雯',80,50) # # print(r.life_value)#80 # g.attact(r) # print(r.life_value)#50 # class Hero:#定义一个英雄类; # def __init__(self,nickname,life_value,aggresivity):#属性; # self.nickname = nickname # self.life_value = life_value # self.aggresivity = aggresivity # def attack(self,enemy):#攻击技能; # enemy.life_value -= self.aggresivity # class Garen(Hero): # camp ='Demacia'#德玛西亚; # def __init__(self,nickname,life_value,aggresivity,weapon): # #self.nickname = nickname # #self.life_value = life_value # #self.aggresivity = aggresivity # #self.weapon = weapon # #Hero.__init__(self,nickname,life_value,aggresivity)# # #super(Garen,self).__init__(nickname,life_value,aggresivity)#与下方实现效果等价; # super().__init__(nickname,life_value,aggresivity)#Python3中super方法的简写方式; # self.weapon = weapon # def attack(self,enemy): # Hero.attack(self,enemy)#指名道姓; # print('from Garen Class') # # #g = Garen('草丛伦',100,30)#TypeError: __init__() missing 1 required positional argument: 'weapon' # g = Garen('草丛伦',100,30,'金箍棒') # print(g.__dict__)#{'nickname': '草丛伦', 'life_value': 100, 'aggresivity': 30, 'weapon': '金箍棒'}
#证明如下: class A: def f1(self): print('from A') class B: def f2(self): print('from B') class C(A,B): pass print(C.mro())#[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]#c的mro排列顺序查找;
16-组合
1、什么是组合;
- 软件重用的重要方式除了继承之外还有另外一种方式,即:组合
- 组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合;
2、组合与继承都是有效地利用已有类的资源的重要方式,但是二者的概念和使用场景皆不同;
1)继承的方式
通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物;
当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生是人;
2)组合的方式
用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python和linux课程,教授有学生s1、s2、s3...
示例:继承与组合
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/16 0016 21:05 # class Teacher:#定义讲师类; # school = 'luffycity' # def __init__(self,name,age,sex,level,salary): # self.name = name # self.age = age # self.sex = sex # self.level = level # self.salary = salary # def teach(self): # print('%s is teaching Python course'%self.name) # # #定义学生类; # class Student:#定义学生类; # school = 'luffycity' # def __init__(self,name,age,sex,class_time): # self.name = name # self.age = age # self.sex = sex # self.class_time = class_time # def learn(self): # print('%s is learning Python course'%self.name) "" """ 以上出现了代码重用的现象,so抽取学生和讲师公共的部分,定义People类; """ #定义People类; class People: school = 'luffycity' def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex class Teacher(People):#通过继承方式,定义讲师类; def __init__(self,name,age,sex,level,salary): super().__init__(name,age,sex) self.level = level self.salary = salary def teach(self): print('%s is teaching Python course'%self.name) #定义学生类; class Student(People):#通过继承方式,定义学生类; school = 'luffycity' def __init__(self,name,age,sex,class_time): super().__init__(name, age, sex) self.class_time = class_time def learn(self): print('%s is learning Python course'%self.name) #定义课程类; class Course: def __init__(self,course_name,course_price,course_period): self.course_name = course_name self.course_price = course_price self.course_period = course_period #再定义课程信息类; def Tell_info(self): print('课程名《%s》 课程价格《%s》 课程周期《%s》'%(self.course_name,self.course_price,self.course_period)) class Date: def __init__(self,year,month,day): self.year = year self.month = month self.day = day def tell_info(self): print('%s-%s-%s'%(self.year,self.month,self.day)) #通过类实例化,产生对象; teacher1 = Teacher('alex',18,'male',10,3000) teacher2 = Teacher('egon',28,'male',10,3000) python = Course('Python',3000,'3months') linux = Course('Linux',4000,'4months') teacher1.course = python teacher2.course = python print(python) print(teacher1.course) print(teacher2.course) """ <__main__.Course object at 0x000001CD7CF35F98> <__main__.Course object at 0x000001CD7CF35F98> <__main__.Course object at 0x000001CD7CF35F98> """ #teacher1 = Teacher('alex',18,'male',10,3000,'Python',3000,'3months') #teacher2 = Teacher('egon',28,'male',10,3000,'Python',3000,'3months') #如何查看老师课程信息; print(python.course_name) print(python.course_period) print(python.course_price) #等价于如下所示; print(teacher1.course.course_name)#Python print(teacher1.course.course_period)#3months print(teacher1.course.course_price)#3000 #查看老师的课程信息的方法; teacher1.course.Tell_info()#这种方式就叫做组合;课程名《Python》 课程价格《3000》 课程周期《3months》 student1 = Student('张三',28,'female','08:30:00') student1.course1 = python student1.course2 = linux #查看学生的课程信息的方法; student1.course1.Tell_info()#课程名《Python》 课程价格《3000》 课程周期《3months》 student1.course2.Tell_info()#课程名《Linux》 课程价格《4000》 课程周期《4months》 student3 = Student('崔晓昭',28,'male','09:00:00') d = Date(1993,9,11) student3.birth = d student3.birth.tell_info()#1993-9-11 "" """ 小结: 1、#什么有什么,即可使用组合的方式进行代码重用; 2、#什么是什么,即使用继承的方式进行代码重用; """
17-抽象类与归一化
1、抽象类的初识;
1)接口与归一化设计;
2、什么是接口?!
hi boy,给我开个查询接口。。。此时的接口指的是:自己提供给使用者来调用自己功能的方式\方法、入口,java中的interface使用如下:
=================第一部分:Java 语言中的接口很好的展现了接口的含义: IAnimal.java /* * Java的Interface接口的特征: * 1)是一组功能的集合,而不是一个功能; * 2)接口的功能用于交互,所有的功能都是public,即别的对象可操作; * 3)接口只定义函数,但不涉及函数实现; * 4)这些功能是相关的,都是动物相关的功能,但光合作用就不适宜放到IAnimal里面了*/ package com.oo.demo; public interface IAnimal { public void eat(); public void run(); public void sleep(); public void speak(); } =================第二部分:Pig.java:猪”的类设计,实现了IAnnimal接口 package com.oo.demo; public class Pig implements IAnimal{ //如下每个函数都需要详细实现 public void eat(){ System.out.println("Pig like to eat grass"); } public void run(){ System.out.println("Pig run: front legs, back legs"); } public void sleep(){ System.out.println("Pig sleep 16 hours every day"); } public void speak(){ System.out.println("Pig can not speak"); } } =================第三部分:Person2.java /* *实现了IAnimal的“人”,有几点说明一下: * 1)同样都实现了IAnimal的接口,但“人”和“猪”的实现不一样,为了避免太多代码导致影响阅读,这里的代码简化成一行,但输出的内容不一样,实际项目中同一接口的同一功能点,不同的类实现完全不一样; * 2)这里同样是“人”这个类,但和前面介绍类时给的类“Person”完全不一样,这是因为同样的逻辑概念,在不同的应用场景下,具备的属性和功能是完全不一样的 */ package com.oo.demo; public class Person2 implements IAnimal { public void eat(){ System.out.println("Person like to eat meat"); } public void run(){ System.out.println("Person run: left leg, right leg"); } public void sleep(){ System.out.println("Person sleep 8 hours every dat"); } public void speak(){ System.out.println("Hellow world, I am a person"); } } =================第四部分:Tester03.java package com.oo.demo; public class Tester03 { public static void main(String[] args) { System.out.println("===This is a person==="); IAnimal person = new Person2(); person.eat(); person.run(); person.sleep(); person.speak(); System.out.println("\n===This is a pig==="); IAnimal pig = new Pig(); pig.eat(); pig.run(); pig.sleep(); pig.speak(); } } java中的interface
3、为何要使用接口?
归一化的好处在于:
1)归一化让使用者无需关心对象的类是什么,只需要的知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度;
2)归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合;
就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。
再比如:我们有一个汽车接口,里面定义了汽车所有的功能,然后由本田汽车的类,奥迪汽车的类,大众汽车的类,他们都实现了汽车接口,这样就好办了,大家只需要学会了怎么开汽车,那么无论是本田,还是奥迪,还是大众我们都会开了,开的时候根本无需关心我开的是哪一类车,操作手法(函数调用)都一样;
4、模仿java中的interface
在python中根本就没有一个叫做interface的关键字,如果非要去模仿接口的概念
可以借助第三方模块:http://pypi.python.org/pypi/zope.interface
也可以使用继承,其实继承有两种用途
一:继承基类的方法,并且做出自己的改变或者扩展(代码重用):实践中,继承的这种用途意义并不很大,甚至常常是有害的。因为它使得子类与基类出现强耦合;
二:声明某个子类兼容于某基类,定义一个接口类(模仿java的Interface),接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/16 0016 22:12 #抽象类的概念引入及应用场景; import abc class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod#通过抽象类,来实现标准化; def run(self): pass @abc.abstractmethod def eat(self): pass class People(Animal): # pass#TypeError: Can't instantiate abstract class People with abstract methods eat, run def run(self): print('People is running') def eat(self): print('People is eating')
class Pig(Animal): def run(self): print('People is running') def eat(self): print('People is eating') class Dog(Animal): def run(self): print('People is running') def eat(self): print('People is eating') #类实例化产生对象; peo1 = People() pig1 = Pig() dog1 = Dog() # peo1.eat() pig1.eat() dog1.eat() "" """ People is eating People is eating People is eating 小结: 1、抽象类的本质还是一个类; 2、抽象类与类还是有一点儿区别的,抽象类只能被继承,不能被实例化,功能是为了规范子类; 3、抽象类的作用是基于继承演变而来的,做归一化的好处,把所有的接口都规范起来,降低使用者的使用复杂度; """ #抽象类的概念引入及应用场景; #animal = Animal()#TypeError: Can't instantiate abstract class Animal with abstract methods eat, run
18-多态与多态性
1、多态与多态性初识;
1)多态;
多态指的是一类事物有多种形态,比如:动物有多种形态:人,狗,猪;
文件有多种形态:文本文件,可执行文件;
2)多态性;
一 什么是多态动态绑定(在继承的背景下使用时,有时也称为多态性);
多态性是指在不考虑实例类型的情况下使用实例,多态性分为静态多态性和动态多态性;
静态多态性:如任何类型都可以用运算符+进行运算;
动态多态性:如下
peo=People() dog=Dog() pig=Pig() #peo、dog、pig都是动物,只要是动物肯定有talk方法 #于是我们可以不用考虑它们三者的具体是什么类型,而直接使用 peo.talk() dog.talk() pig.talk() #更进一步,我们可以定义一个统一的接口来使用 def func(obj): obj.talk()
2、 为什么要用多态性(多态性的好处)
python本身就是支持多态性的,这么做的好处是什么呢?
1)增加了程序的灵活性
以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal);
2)增加了程序额可扩展性
通过继承animal类创建了一个新的类,使用者无需更改自己的代码,还是用 func(animal)去调用 ;
3、鸭子类型
Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子;
python程序员通常根据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,可以继承该对象;
也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度;
利用标准库中定义的各种‘与文件类似’的对象,尽管这些对象的工作方式像文件,但他们没有继承内置文件对象的方法;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/16 0016 22:43 #多态,同一种事物的多种形态 "" """ 1、水的多种形态; 2、动物的多种形态; 3、文件的多种形态; """ import abc class Animal(metaclass=abc.ABCMeta): #同一类事物:动物 @abc.abstractmethod def talk(self): pass class People(Animal): #动物的形态之一:人 def talk(self): print('say hello') class Dog(Animal): #动物的形态之二:狗 def talk(self): print('say wangwang') class Pig(Animal): #动物的形态之三:猪 def talk(self): print('say aoao') class Cat(Animal):#猫 def talk(self): print('say miaomiao') #多态性-指的是可以在不考虑对象的类型下而直接使用对象; peo1 = People() dog1 = Dog() pig1 = Pig() cat1 = Cat() peo1.talk() dog1.talk() pig1.talk() cat1.talk() #静态多态性; #动态多态性; def func(animal): animal.talk() func(peo1) func(pig1) func(dog1) func(cat1) #Python崇尚鸭子类型;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/16 0016 22:55 #鸭子类型引入; class File: def read(self): pass def write(self): pass
class Disk: def read(self): print('disk read') def write(self): print('disk write') class Text: def read(self): print('text read') def write(self): print('text write') disk = Disk() text = Text() disk.read() disk.write() text.read() text.write() #序列类型——列表list、元组tuple、字符串str; l = list([1,2,3]) t = tuple(('a','b')) s = str('hello') print(l.__len__()) print(t.__len__()) print(s.__len__()) #按照原来的方法; def len(obj): return obj.__len__() print(len(l)) print(len(t)) print(len(s))
19-封装之如何隐藏属性
1、封装概念初识;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/17 0017 14:34 class A: __X=1#_A__x=1,在定义阶段就被定义; def __init__(self,name):#self._A__name = name self.__name = name def __foo(self): print('run foo') def bar(self): self.__foo()#self._A__foo() print('from bar') #print(A.__X)#AttributeError: type object 'A' has no attribute '__X' #print(A.__foo)#AttributeError: type object 'A' has no attribute '__foo' a = A('egon') #print(a.__name)#AttributeError: 'A' object has no attribute '__name' print(a.__dict__)#{'_A__name': 'egon'} """ 这种变形的特点: 1、外部无法直接访问obj.__AttrName; 2、在类内部是可以直接使用:obj.AttrName 3、子类无法覆盖父类__开头的属性; """ class Foo: def __func(self):#_Foo__func print('from foo') class Bar(Foo): def __func(self):#_Bar__func print('from bar') #b = Bar() #b.func() """ 总结这样的变形需要注意的问题: 1、 """ class B: __x = 1 def __init__(self,name): self.__name = name#类定义阶段发生隐藏; #验证问题1: #print(B._B__x)#1,虽然能正常打印,但是不建议这么使用,因为这种形式就是Python在做隐藏; #验证问题2; # B.__y =2 # print(B.__dict__)#{'__module__': '__main__', '_B__x': 1, '__init__': <function B.__init__ at 0x00000216F511C048>, '__dict__': <attribute '__dict__' of 'B' objects>, '__weakref__': <attribute '__weakref__' of 'B' objects>, '__doc__': None, '__y': 2} # b = B('egon') # print(b.__dict__)#{'_B__name': 'egon'} #print(B.__x)#AttributeError: type object 'B' has no attribute '__x' #验证问题3: # class A: # def foo(self): # print('A.bar') # def bar(self): # print('A.bar') # self.foo() # class B(A): # def foo(self): # print('B.foo') # # b = B() # b.bar() """ A.bar B.foo """ class A: def __foo(self): print('A.bar') def bar(self): print('A.bar') self.__foo() class B(A): def __foo(self): print('B.foo') b = B() b.bar() """ A.bar A.bar """
20-封装的意义
1、为什么要封装?
1)我们的身体没有一处不体现着封装的概念:你的身体把膀胱尿道等等这些尿的功能隐藏了起来,然后为你提供一个尿的接口就可以了(接口就是你的丁丁)你总不能把膀胱挂在身体外面,上厕所的时候就跟别人炫耀:hi,man,你瞅我的膀胱,看看我是怎么尿的。
2)电视机本身是一个黑盒子,隐藏了所有细节,但是一定会对外提供了一堆按钮,这些按钮也正是接口的概念,所以说,封装并不是单纯意义的隐藏;
3)快门就是傻瓜相机为傻瓜们提供的方法,该方法将内部复杂的照相功能都隐藏起来了;
提示:在编程语言里,对外提供的接口(接口可理解为了一个入口),可以是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/17 0017 15:15 #封装数据属性;明确的区分内外,控制外部对隐藏属性的操作行为; class People: def __init__(self,name,age): self.__name = name self.__age = age def tell_info(self): print('Name:<%s> Age:<%s>'%(self.__name,self.__age)) #开通一个接口,可修改name或age 的值; def set_info(self,name,age): if not isinstance(name,str): print('名字必须是字符串类型') return elif not isinstance(age,int): print('年龄必须是数字类型') return self.__name = name self.__age = age p = People('egon',18) p.tell_info()#Name:<egon> Age:<18> p.set_info('EGON',18) p.tell_info()#Name:<EGON> Age:<18> #传入不合法的值; p.set_info(1993,26)#名字必须是字符串类型 p.tell_info() #封装方法:隔离复杂度;用傻瓜相机来对比专业单反,来解释复杂度,对用户来讲,使用特别简答; class Atm: def __card(self): print('插卡') def __auth(self): print('用户认证') def __input(self): print('输入提款金额') def __bill(self): print('打印账单') def __take_money(self): print('取款') #进行隐藏属性; def withdraw(self): self.__card() self.__auth() self.__input() self.__bill() self.__take_money() a = Atm() a.withdraw() """ 插卡 用户认证 输入提款金额 打印账单 取款 """
21-封装与可拓展性
1、可拓展性举例;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/17 0017 15:40 #封装带来的可拓展性;非常的灵活去拓展功能,但是对于使用者来说,是隐藏的; class Room: def __init__(self,name,owner,weight,length,height): self.name = name self.owner = owner self.__weight = weight self.__length = length self.__height = height def tell_area(self): return self.__weight * self.__length * self.__height r = Room('卫生间','alex',10,10,3) r.tell_area() print(r.tell_area())#300 立方米;
22-Property的使用
1、使用property方法的优点介绍;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/17 0017 18:01 #体质指数(BMI)= 体重(kg)/身高*身高(m) class People: def __init__(self,name,weight,height): self.name = name self.weight = weight self.height = height #定义一个新函数bmi; #添加一个property装饰器属性; @property def bmi(self): return self.weight / (self.height ** 2) #实例化产生对象; p = People('tqtl',110,1.85) #如下方法太僵化,重复调用; #p.bmi=p.weight / (p.height ** 2) #print(p.bmi)#32.14024835646457 #直接调用函数; #print(p.bmi())#32.14024835646457,虽然实现了功能,但是由原来的“名词性质调用”变成了“动词性质的调用”; #最好的调用方法; print(p.bmi)#32.14024835646457 """ 1、添加了property属性后,恢复到之前的名词调用方式,相对于使用print(p.bmi())方式,给用户的感觉没有发生变化; """ #新增需求,自定义了身高指数 p.height = 1.90 print(p.bmi)#30.470914127423825 #但是不能为p.bmi属性赋值,因为他是动态计算出来的,会报错; #p.bmi = 38 #print(p.bmi)#AttributeError: can't set attribute; #补充property的用法; class People: def __init__(self,name): self.__name = name # @property # def get_name(self): # return self.__name @property#使用property的好处,相当于做了一个伪装,将动词属性的调用方式,改为名词属性的调用方式; def name(self): return self.__name #为了实现赋值功能,再次定义; @name.setter def name(self,val): if not isinstance(val,str): print('名称必须是字符串') return self.__name =val #实现删除操作; @name.deleter def name(self): print('不允许删除') #实例化产生对象; p = People('tqtl') #print(p.get_name)#tqtl #新需求,不想让用户使用p.get_name,使用者容易造成误解,怎么办?使用property装饰器; print(p.name)#tqtl #不能直接赋值;p.name = 'TQTL',如何解决?不太常用; p.name = 'TQTL' print(p.name)#TQTL,实现了重新赋值操作; #新需求又来了,如何定义删除功能呢?同上 del p.name#不允许删除 print(p.name)
23-绑定与非绑定方法介绍
1、绑定与非绑定方法详解;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:python3.6.5 # Date:2018/6/17 0017 20:17 "" """ 在类内部定义的函数,分为两大类: 一、绑定方法:绑定给谁,就应该由谁来调用,谁来调用,就会把调用者当做第一个参数自动传入; 1)绑定到对象的方法:在类内定义的没有被任何装饰器修饰的; 2)绑定到类的方法:在类内部定义的,被装饰器classmethod修饰的方法; 二、非绑定方法:没有自动传值这么一说;就类中定义的一个普通工具,对象和类都可以使用;使用staticmethod关键字; 非绑定方法:不与类或者对象绑定: """ #实例演示: class Foo: def __init__(self,name): self.name = name def tell(self): print('名字是%s'%self.name) @classmethod def func(cls):#cls = Foo print(cls) @staticmethod#真正意义上的普通函数; def func1(x,y): #return x + y print(x+y) f = Foo('tqtl') # print(Foo.tell)#<function Foo.tell at 0x0000015F867A0D90> # Foo.tell(f)#名字是tqtl # print(f.tell)#名字是tqtl #print(Foo.func)#<bound method Foo.func of <class '__main__.Foo'>> #Foo.func()#<class '__main__.Foo'> #print(Foo)#<class '__main__.Foo'> print(Foo.func1)#<function Foo.func1 at 0x00000276CAC20E18> print(f.func1)#<function Foo.func1 at 0x00000276CAC20E18> Foo.func1(1,2)#3 f.func1(1,3)#4
24-绑定方法与非绑定方法的使用
1、应用场景讲解;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:Python3.6.5 # Date:2018/6/17 0017 20:37 import settings import hashlib import time class People: def __init__(self,name,age,sex): self.id = self.create_id() self.name = name self.age = age self.sex = sex def tell_info(self):#绑定到对象的方法; print('Name:%s Age:%s Sex:%s'%(self.name,self.age,self.sex)) @classmethod def from_conf(cls): obj = cls( settings.name, settings.age, settings.sex, ) return obj#一定有return返回值; @staticmethod#使用该关键字,声明函数为基本函数; def create_id(): m = hashlib.md5(str(time.time()).encode('utf-8'))#使用str()方法将时间转换为字符串,因为不可变数据类型才可被hash; return m.hexdigest() #实例化产生对象; p = People('tqtl',18,'male') #绑定给对象,就应该由对象来调用,自动将对象本身当做第一个参数传入; #p.tell_info() #tell_info(p) #绑定给类,就应该由类来调用,自动将类本身当做第一个参数传入; p = People.from_conf() p.tell_info()#Name:alex Age:18 Sex:female #非绑定方法,不与类或者对象绑定,谁都可以调用,没有自动传值一说; #开始实例化产生对象; p1 = People('egon',18,'male') p2 = People('alex',28,'female') p3 = People('peiqi',38,'female') p4 = People('tqtl',8,'male') print(p1.id)#1ca14d661c87f8cf51e12f0250ea9f14 print(p2.id)#1ca14d661c87f8cf51e12f0250ea9f14 print(p3.id)#1ca14d661c87f8cf51e12f0250ea9f14 print(p4.id)#1ca14d661c87f8cf51e12f0250ea9f14
25-反射
1、反射的实际应用;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:Python3.6.5 # Date:2018/6/17 0017 20:57 #通过字符串,映射到对象的属性; class People: def __init__(self,name,age): self.name = name self.age = age def talk(self): print('%s is talking'%self.name) obj = People('tqtl',18) #print(obj.name)#tqtl #print(obj.talk)#<bound method People.talk of <__main__.People object at 0x000001C1FB49FA20>> #choice = input('>>>:')#choice = 'name' #print(obj.choice)#print(obj.'name')#这么写语法错误; #hasattr() hasattr(obj,'name')#obj.name print(hasattr(obj,'name'))#True print(hasattr(obj,'talk'))#True getattr(obj,'name') getattr(obj,'name',None) print(getattr(obj,'name'))#tqtl print(getattr(obj,'talk',None))#<bound method People.talk of <__main__.People object at 0x00000133664749B0>> setattr(obj,'sex','male') print(obj.sex)#male delattr(obj,'age') print(obj.__dict__)#{'name': 'tqtl', 'sex': 'male'} #通过字符串来访问到对象或类的属性的一种方法; #具体应用场景-反射应用 class Service: def run(self): while True: inp = input('>>>:').strip()#cmd = 'get a.txt' cmds = inp.split()#cmds = ['get','a.txt'] #print(cmds) if hasattr(self,cmds[0]): func = getattr(self,cmds[0]) func(cmds) # cmd = input('>>>').strip() # print(cmd) def get(self,cmds):#下载功能; print('get ...',cmds) def put(self,cmds):#上传功能; print('put ...',cmds) obj = Service() obj.run() """ >>>:get a.txt get ... ['get', 'a.txt'] >>>:put a.txt put ... ['put', 'a.txt'] >>>: """
26-内置方法介绍
1、内置方法详解(_item__\__str__\__del__);
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:Python3.6.5 # Date:2018/6/17 0017 21:20 #item系列; class Foo: def __init__(self,name): self.name = name def __getitem__(self, item): #print('getitem') # print(item) return self.__dict__.get(item) def __setitem__(self, key, value): #print('setitem') #print(key,value) self.__dict__[key] = value def __delitem__(self, key): #print('delitem') #print(key) #self.__dict__.pop() del self.__dict__[key] obj = Foo('tqtl') #查看属性; #obj['name']#完成obj.name print(obj['namexxxx'])#None #设置属性; obj.sex = 'male' obj['sex']='male' print(obj.__dict__) print(obj.sex)#male #删除属性; #之前的套路: #del obj.name #现在的套路; del obj['name'] print(obj.__dict__)#male """ 小结: 把对象做成一个像字典一样的对象去操作; 把类定制化成dict类型的东西,进行增删改查操作; """ d = {'name':'tqtl'} print(isinstance(d,dict))#True #__str__方法; class People: def __init__(self,name,age): self.name =name self.age = age def __str__(self): #print('=====>str')#TypeError: __str__ returned non-string (type NoneType) return '<name:%s,age:%s>'%(self.name,self.age) obj = People('tqtl',26) #print(obj)#<__main__.People object at 0x000001CD512E4BE0> print(obj)#<name:tqtl,age:26> #print语句,打印对我们有用的信息; #__del__方法;回收系统资源 # f = open(file='settings.py',mode='rb')#本质上是一个赋值操作; # f.read() # f.close()#申请的资源,用完之后,要回收;给操作系统发送信号,回收操作系统资源; # print() class Open: def __init__(self,filename): print('Open file......') self.filename = filename def __del__(self): print('回收操作系统资源:self.close()') f = Open('settings.py') print('----main-----')# """ Open file...... ----main----- 回收操作系统资源:self.close() """
27-元类介绍
1、元类概念初识以及原理剖析;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:Python3.6.5 # Date:2018/6/17 0017 22:34 "" """ 知识储备:exec 1、参数1:字符串形式的命令; 2、参数2:全局作用域(字典形式),如果不指定,默认就使用globals() 3、参数3:局部作用域(字典形式),如果不指定,默认就使用locals() """ # g = { # 'x':1, # 'y':2 # } # l = {} # exec(""" # global x,m # x = 10 # m =100 # # z =3 # """,g,l) # print(g) # print(l) """ C:\\Users\\Administrator\PycharmProjects\LFXC2018\venv\Scripts\python.exe "C:/Users/Administrator/PycharmProjects/LFXC2018/第三模块 面向对象/27-元类介绍.py" {'x': 10, 'y': 2, '__builtins__': {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'callable': <built-in function callable>, 'chr': <built-in function chr>, 'compile': <built-in function compile>, 'delattr': <built-in function delattr>, 'dir': <built-in function dir>, 'divmod': <built-in function divmod>, 'eval': <built-in function eval>, 'exec': <built-in function exec>, 'format': <built-in function format>, 'getattr': <built-in function getattr>, 'globals': <built-in function globals>, 'hasattr': <built-in function hasattr>, 'hash': <built-in function hash>, 'hex': <built-in function hex>, 'id': <built-in function id>, 'input': <built-in function input>, 'isinstance': <built-in function isinstance>, 'issubclass': <built-in function issubclass>, 'iter': <built-in function iter>, 'len': <built-in function len>, 'locals': <built-in function locals>, 'max': <built-in function max>, 'min': <built-in function min>, 'next': <built-in function next>, 'oct': <built-in function oct>, 'ord': <built-in function ord>, 'pow': <built-in function pow>, 'print': <built-in function print>, 'repr': <built-in function repr>, 'round': <built-in function round>, 'setattr': <built-in function setattr>, 'sorted': <built-in function sorted>, 'sum': <built-in function sum>, 'vars': <built-in function vars>, 'None': None, 'Ellipsis': Ellipsis, 'NotImplemented': NotImplemented, 'False': False, 'True': True, 'bool': <class 'bool'>, 'memoryview': <class 'memoryview'>, 'bytearray': <class 'bytearray'>, 'bytes': <class 'bytes'>, 'classmethod': <class 'classmethod'>, 'complex': <class 'complex'>, 'dict': <class 'dict'>, 'enumerate': <class 'enumerate'>, 'filter': <class 'filter'>, 'float': <class 'float'>, 'frozenset': <class 'frozenset'>, 'property': <class 'property'>, 'int': <class 'int'>, 'list': <class 'list'>, 'map': <class 'map'>, 'object': <class 'object'>, 'range': <class 'range'>, 'reversed': <class 'reversed'>, 'set': <class 'set'>, 'slice': <class 'slice'>, 'staticmethod': <class 'staticmethod'>, 'str': <class 'str'>, 'super': <class 'super'>, 'tuple': <class 'tuple'>, 'type': <class 'type'>, 'zip': <class 'zip'>, '__debug__': True, 'BaseException': <class 'BaseException'>, 'Exception': <class 'Exception'>, 'TypeError': <class 'TypeError'>, 'StopAsyncIteration': <class 'StopAsyncIteration'>, 'StopIteration': <class 'StopIteration'>, 'GeneratorExit': <class 'GeneratorExit'>, 'SystemExit': <class 'SystemExit'>, 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, 'ImportError': <class 'ImportError'>, 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, 'OSError': <class 'OSError'>, 'EnvironmentError': <class 'OSError'>, 'IOError': <class 'OSError'>, 'WindowsError': <class 'OSError'>, 'EOFError': <class 'EOFError'>, 'RuntimeError': <class 'RuntimeError'>, 'RecursionError': <class 'RecursionError'>, 'NotImplementedError': <class 'NotImplementedError'>, 'NameError': <class 'NameError'>, 'UnboundLocalError': <class 'UnboundLocalError'>, 'AttributeError': <class 'AttributeError'>, 'SyntaxError': <class 'SyntaxError'>, 'IndentationError': <class 'IndentationError'>, 'TabError': <class 'TabError'>, 'LookupError': <class 'LookupError'>, 'IndexError': <class 'IndexError'>, 'KeyError': <class 'KeyError'>, 'ValueError': <class 'ValueError'>, 'UnicodeError': <class 'UnicodeError'>, 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, 'AssertionError': <class 'AssertionError'>, 'ArithmeticError': <class 'ArithmeticError'>, 'FloatingPointError': <class 'FloatingPointError'>, 'OverflowError': <class 'OverflowError'>, 'ZeroDivisionError': <class 'ZeroDivisionError'>, 'SystemError': <class 'SystemError'>, 'ReferenceError': <class 'ReferenceError'>, 'BufferError': <class 'BufferError'>, 'MemoryError': <class 'MemoryError'>, 'Warning': <class 'Warning'>, 'UserWarning': <class 'UserWarning'>, 'DeprecationWarning': <class 'DeprecationWarning'>, 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, 'SyntaxWarning': <class 'SyntaxWarning'>, 'RuntimeWarning': <class 'RuntimeWarning'>, 'FutureWarning': <class 'FutureWarning'>, 'ImportWarning': <class 'ImportWarning'>, 'UnicodeWarning': <class 'UnicodeWarning'>, 'BytesWarning': <class 'BytesWarning'>, 'ResourceWarning': <class 'ResourceWarning'>, 'ConnectionError': <class 'ConnectionError'>, 'BlockingIOError': <class 'BlockingIOError'>, 'BrokenPipeError': <class 'BrokenPipeError'>, 'ChildProcessError': <class 'ChildProcessError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, 'ConnectionResetError': <class 'ConnectionResetError'>, 'FileExistsError': <class 'FileExistsError'>, 'FileNotFoundError': <class 'FileNotFoundError'>, 'IsADirectoryError': <class 'IsADirectoryError'>, 'NotADirectoryError': <class 'NotADirectoryError'>, 'InterruptedError': <class 'InterruptedError'>, 'PermissionError': <class 'PermissionError'>, 'ProcessLookupError': <class 'ProcessLookupError'>, 'TimeoutError': <class 'TimeoutError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-Z plus Return to exit, 'exit': Use exit() or Ctrl-Z plus Return to exit, 'copyright': Copyright (c) 2001-2018 Python Software Foundation. All Rights Reserved. Copyright (c) 2000 BeOpen.com. All Rights Reserved. Copyright (c) 1995-2001 Corporation for National Research Initiatives. All Rights Reserved. Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. All Rights Reserved., 'credits': Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands for supporting Python development. See www.python.org for more information., 'license': Type license() to see the full license text, 'help': Type help() for interactive help, or help(object) for help about object.}, 'm': 100} {'z': 3} Process finished with exit code 0 """ #Python中一切皆对象;对象可以怎么使用呢? """ 1、都可以被引用; 2、都可以当做函数的参数传入; 3、都可以当做容器类的元素; 4、都可以当做函数的返回值; 5、从Python一切皆对象的角度来看,那么类也是对象; """ #什么叫元类?! class Foo: pass obj = Foo() print(type(obj))#<class '__main__.Foo'> print(type(Foo))#<class 'type'> class Bar: pass print(type(Bar))#<class 'type'> """ 小结: 1、产生类的类,称之为元类,默认所使用class关键字定义的类,他们的元类是type; """ #2、定义类的两种方式; #方式一:class关键字; class Chinese: country = "China" def __init__(self,name,age): self.name = name self.age = age def talk(self): print('%s is talking'%self.name) print(Chinese)#<class '__main__.Chinese'> #方式二:type关键字 #定义类的三要素;类名、类的基类们,类的名称空间; class_name = 'Chinese' class_bases = (object,) class_body = """ def __init__(self,name,age): self.name = name self.age = age def talk(self): print('%s is talking'%self.name) """ class_dic = {} exec(class_body,globals(),class_dic) print(class_dic)#{'__init__': <function __init__ at 0x000002BCE6762E18>, 'talk': <function talk at 0x000002BCE86E0A60>} Chinese1=type(class_name,class_bases,class_dic) print(Chinese1)#<class '__main__.Chinese'> obj1 = Chinese1('tqtl',25) print(obj1,obj1.name,obj1.age)#<__main__.Chinese object at 0x0000017351444BA8>tqtl 25
28-自定义元类控制类的创建
1、自定义元类控制控制类详解;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:Python3.6.5 # Date:2018/6/17 0017 23:09 #如何自己定制元类; class Mymeta(type):#自定义元类,要继承type; def __init__(self,class_name,class_bases,class_dic): if not class_name.istitle(): raise TypeError('类名的首字母必须大写') if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): raise TypeError('必须有注释且不能为空;')#抛出异常; #主动抛出异常关键字raise; print(class_dic) #print(class_name)#Chinese # print(class_bases)#(<class 'object'>,) #print(class_dic)#{'__module__': '__main__', '__qualname__': 'Chinese', 'country': 'China', '__init__': <function Chinese.__init__ at 0x0000020E7C740D90>, 'talk': <function Chinese.talk at 0x0000020E7C740A60>} super(Mymeta,self).__init__(class_name,class_bases,class_dic) #class chinese(object,metaclass=Mymeta):#TypeError: 类名的首字母必须大写 class Chinese(object,metaclass=Mymeta): ''' 这里是注释哦,出现了__doc__': '\n 这里是注释哦\n ' ''' country = "China" def __init__(self,name,age): self.name = name self.age = age def talk(self): print('%s is talking'%self.name) #Chinese = type(class_name,class_bases,class_dic) #raise TypeError('类型错误') """ 小结: 1、自定义元类控制创建类的属性; """ class Foo: pass print(Foo.__dict__)#{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
29-自定义元类与控制类的实例化行为
1、自定义元类控制实例化行为详解;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:Python3.6.5 # Date:2018/6/17 0017 23:33 "" """ #知识储备__call__方法; class Foo: def __call__(self,*args,**kwargs): print(self) print(args) print(kwargs) obj = Foo()#() #obj()#{} obj(1,2,3,a=1,b=2,c=4)#{'a': 1, 'b': 2, 'c': 4} #元类内部也应该有一个__call__方法,会在调用Foo时候出发执行; """ class Mymeta(type):#自定义元类,要继承type; def __init__(self,class_name,class_bases,class_dic): if not class_name.istitle(): raise TypeError('类名的首字母必须大写') if '__doc__' not in class_dic or not class_dic['__doc__'].strip(): raise TypeError('必须有注释且不能为空;')#抛出异常; #主动抛出异常关键字raise; print(class_dic) super(Mymeta,self).__init__(class_name,class_bases,class_dic) #定制call方法; def __call__(self, *args, **kwargs): print(self) print(args) print(kwargs) print('======>') #第一件事:先造一个空对象obj;obj obj = object.__new__(self) # Chinese.__init__(obj.*args.**kwargs) # 第二件事:初始化obj; self.__init__(obj,*args,**kwargs) #第三件事:返回obj; return obj class Chinese(object,metaclass=Mymeta): ''' 这里是注释哦,出现了__doc__': '\n 这里是注释哦\n ' ''' country = "China" def __init__(self,name,age): self.name = name self.age = age def talk(self): print('%s is talking'%self.name) obj = Chinese('tqtl',18)#相当于:Chinese.__call__(Chiese,'tqtl',18)#======> obj2 = Chinese('tqtl',age=18)#{'age': 18}#======> #在Chinese('tqtl',18)内部产生三件事; #1、先造出空对象obj; #2、初始化obj; #3、返回obj;
30-自定义元类与控制类的实例化行为的应用
1、代码举例,虽说有些抽象,先记录下;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:Python3.6.5 # Date:2018/6/18 0018 9:20 #单例模式 #实现方式一: class Mysql: __instance = None def __init__(self): self.host = '127.0.0.1' self.port = 3306 @classmethod def singleton(cls): if not cls.__instance: obj = cls() cls.__instance = obj return cls.__instance def conn(self): pass def execute(self): pass # obj1 = Mysql() # obj2 = Mysql() # obj3 = Mysql() # print(obj1) # print(obj2) # print(obj3) obj1 = Mysql.singleton() obj2 = Mysql.singleton() obj3 = Mysql.singleton() print(obj1 is obj2)#True print(obj1 is obj3) print(obj2 is obj3) #实现方式二:元类的方式 class Mymeta(type): def __init__(self,class_name,class_bases,class_dic): if not class_name.istitle(): raise TypeError('类名首字母必须大写') elif '__doc__' not in class_dic or not class_dic['__doc__'].strip(): raise TypeError('必须有注释,且注释不能为空') super(Mymeta, self).__init__(class_name,class_bases,class_dic)#继承父类的属性; self.__instance=None def __call__(self,*args,**kwargs): if not self.__instance: obj = object.__new__(self) self.__init__(obj) self.__instance=obj #obj = object.__new__(self) #self.__init__(obj,*args,**kwargs) return self.__instance class Mysql(object,metaclass=Mymeta): ''' 链接MySQL老数据 ''' def __init__(self): self.host = '127.0.0.1' self.port = 3306 @classmethod def singleton(cls): if not cls.__instance: obj = cls() cls.__instance = obj return cls.__instance def conn(self): pass def execute(self): pass obj1 = Mysql() obj2 = Mysql() obj3 = Mysql() print(obj1 is obj2 is obj3)#True """ 小结: 1、元类是面向对象当中一个深层次的方法,先定义为选学内容; """
31-面向对象的软件开发与作业介绍
1、博文参考;
http://www.cnblogs.com/linhaifeng/articles/7341318.html
32-什么是异常处理
1、什么是异常?!
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:Python3.6.5 # Date:2018/6/18 0018 9:56 "" """ 什么是异常?!异常时错误发生的信号,一旦程序发生错误,并且程序没有处理这个错误,那个就会抛出异常,并且程序的运行随之终止; 错误分为两种: 1、语法错误;在程序执行前就要立刻改正过来; 2、逻辑错误; """ #No.001-ValueError: invalid literal for int() with base 10: 'cuixiaozhao' #int('cuixiaozhao') #No.002-NameError: name 'name' is not defined #name #No.003-IndexError: list index out of range #list1 = [1,2,3] #list1[1000] #No.004-KeyError: 'name' #dict1 = {} #dict1['name'] #No.005-AttributeError: type object 'Foo' has no attribute 'cxz' #class Foo: # pass #Foo.cxz #No.006-ZeroDivisionError: division by zero #1/0 #No.007-TypeError: 'int' object is not iterable #for i in 3: # print(i) #No.008-ModuleNotFoundError: No module named 'cuixiaozhao' #import cuixiaozhao #No.009-被终止; #import time #time.sleep(1000) """ 1、如何进行异常处理?! 强调1:如果错误发生的条件是可以预知的,此时应该使用if判断去预防异常; 强调2:如果错误发生的条件是不可以预知的,此时应该使用异常处理机制,try ... except """ try:#表示监测代码; with open(file='a.txt',mode='r',encoding='utf-8') as f: #next(f) print(next(f),end='') print(next(f),end='') print(next(f),end='') print(next(f),end='') print(next(f),end='') print(next(f),end='') print(next(f),end='') print(next(f),end='') print(next(f),end='') print(next(f),end='') except StopIteration: print('出错啦!') print('=========>1') print('=========>2') print('=========>3') print('=========>4') print('=========>5')
33-try...except...详细用法
1、异常处理的使用说明及try...except的详解;
#!/usr/bin/env python # -*- coding:utf-8 -*- # __Author__:Administrator # Version:Python3.6.5 # Date:2018/6/18 0018 10:21 #异常的多分支;被监测的代码块,有可能会抛出异常,有多重可能性,并且我们需要针对每一种异常类型,都定制专门的处理逻辑; # try: # print('========>1') # #name # print('========>2') # list1 = [1,2,3] # #list1[100] # print('========>3') # dict1 = {} # dict1['name'] # print('========>3') # except NameError as e: # print('-=----------',e)#-=---------- name 'name' is not defined # except IndexError as e: # print('-->',e) # except KeyError as e: # print('---------->',e) #print('继续执行下一个模块的代码;') #万能异常:Exception:被监测的代码块,有可能会抛出异常,有多重可能性,并且我们需要针对每一种异常类型,都定制专门的处理逻辑; #应用场景:我们针对所有的异常类型,都只用一种处理逻辑就可以啦! try: print('========>1') name print('========>2') list1 = [1,2,3] list1[100] print('========>3') dict1 = {} dict1['age'] print('========>4') except Exception as e: print('异常发生啦!',e) print('继续执行下一个模块的代码;') #异常多分支与万能异常的综合运用; try: print('========>1') name print('========>2') list1 = [1,2,3] list1[100] print('========>3') dict1 = {} dict1['name'] print('========>3') except NameError as e: print('-=----------',e)#-=---------- name 'name' is not defined except IndexError as e: print('-->',e) except KeyError as e: print('---------->',e) except Exception as e: print('Exception是统一的处理方法',e) print('继续执行下一个模块的代码;') #异常处理的其他结构; try: print('========>1') name print('========>2') list1 = [1,2,3] list1[100] print('========>3') dict1 = {} dict1['name'] print('========>3') except NameError as e: print('-=----------',e)#-=---------- name 'name' is not defined except IndexError as e: print('-->',e) except KeyError as e: print('---------->',e) except Exception as e: print('Exception是统一的处理方法',e) else: print('在被检测的代码没有发生异常时候执行') finally: print('不管被监测的代码块有没有误发生异常,都会执行!')#比如打开文件的操作,不管有没有出错,都应该使用f.close()进行关闭文件,此时就用到 print('继续执行下一个模块的代码;') #主动出发异常,raise,异常类型(值) class People: def __init__(self,age,name): if not isinstance(name,str): raise TypeError('名字必须传入str类型') elif not isinstance(age,int): raise TypeError('年龄必须传入int类型') self.name = name self.age = age #p1 = People(333,18) #p2 = People('cuixiaozhao',18) #p3 = People('lijingping','18') #断言assert info = {} info['name'] = 'tqtl' #info['age'] = 26 # if 'name' not in info: # raise KeyError('必须有name这个key') # if 'age' not in info: # raise KeyError('必须有age这个key') #assert ('name' in info) and ('age' in info)#取代以上代码;AssertionError #自定义异常,即自定义类; class MyException(BaseException): def __init__(self,msg): super(MyException,self).__init__() self.msg = msg def __str__(self): return '<%s>'%self.msg raise MyException('我自定义的异常类型哦!')# raise MyException('我自定义的异常类型哦!') #__main__.MyException: <我自定义的异常类型哦!> "" """ 千万不要把异常处理当做万能的,不要依赖异常处理; 使用场景: 1、错误一定会发生,但是无法预知,而且不能因为错误发生而终止程序的运行,即使用异常处理,进行抛出异常操作; 2、错误本身可预知,比如if判断,不应该使用异常处理; """