一、接口与统一化设计
1.归一化让使用者无需关心对象的类是什么,只需要知道这些对象都具备某些功能就可以了,这极大地降低了使用者的使用难度。
2.归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合。
继承的两种用途:
3.继承基类的方法,并且做出自己的改变或者拓展(代码重用):实践中,继承的这种用途意义并不是很大,甚至常常是有害的,因为他使得子类与基类出现强耦合。
4.声明某个子类兼容与某基类,定义一个接口类(模仿java的interface),接口类中定义了一些接口名(就是函数名)且功能,子类继承接口类,并未实现接口类,并且实现接口类,并且实现接口类中的功能
例子:
class Interface:#定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。 def read(self): #定接口函数read pass def write(self): #定义接口函数write pass class Txt(Interface): #文本,具体实现read和write def read(self): print('文本数据的读取方法') def write(self): print('文本数据的写方法') class Sata(Interface): #磁盘,具体实现read和write def du(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的写方法') class Process(Interface): def read(self): print('进程数据的读取方法') def xie(self): print('进程数据的写方法') t=Txt() s=Sata() p=Process() t.read() s.read() p.read()
以上子类的方法必须要跟父类保持一致,不能强制性子类跟父类保持一致。
以下用抽象类解决此问题
抽象类 import abc class Interface(metaclass=abc.ABCMeta):#定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。 all_type='file' @abc.abstractmethod def read(self): #定接口函数read pass @abc.abstractmethod def write(self): #定义接口函数write pass class Txt(Interface): #文本,具体实现read和write def read(self): pass def write(self): pass t=Txt() print(t.all_type)
二.面向对象之封装
1.只要变量__开头在类外部不能被引用, 在类内部是可以的
例子:
lass Foo: __N=111111 #_Foo__N def __init__(self,name): self.__Name=name #self._Foo__Name=name def __f1(self): #_Foo__f1 print('f1') def f2(self): self.__f1() #self._Foo__f1() f=Foo('egon') # print(f.__N) # f.__f1() # f.__Name # f.f2()
这种隐藏需要注意的问题:
这种隐藏只是一种语法上变形操作,并不会将属性真正隐藏起来
封装函数属性:为了隔离复杂度
例子:
#取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱 #对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做 #隔离了复杂度,同时也提升了安全性 class ATM: def __card(self): print('插卡') def __auth(self): print('用户认证') def __input(self): print('输入取款金额') def __print_bill(self): print('打印账单') def __take_money(self): print('取款') def withdraw(self): self.__card() self.__auth() self.__input() self.__print_bill() self.__take_money() a=ATM() a.withdraw()
三.静态属性
例子:
例:BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)
成人的BMI数值:
过轻:低于18.5
正常:18.5-23.9
过重:24-27
肥胖:28-32
非常肥胖, 高于32
体质指数(BMI)=体重(kg)÷身高^2(m)
EX:70kg÷(1.75×1.75)=22.86
'''
class People: def __init__(self,name,weight,height): self.name=name self.weight=weight self.height=height @property def bmi(self): return self.weight / (self.height**2) # p=People('egon',75,1.80) # p.height=1.86 # print(p.bmi()) # print(p.bmi) #访问,设置,删除(了解) class Foo: def __init__(self,x): self.__Name=x @property def name(self): return self.__Name @name.setter def name(self,val): if not isinstance(val,str): raise TypeError self.__Name=val @name.deleter def name(self): # print('=-====>') # del self.__Name raise PermissionError f=Foo('egon') # print(f.name) # # # f.name='Egon' # f.name=123123123213 # print(f.name)
四.反射
通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
setattr 设置值
getattr 获取值
delattr 删除
hasattr 判断对象有没有
例子: class Ftpserver: def __init__(self,host,port): self.host=host self.port=port def run(self): while True: cmd=input('>>: ').strip() if not cmd:continue if hasattr(self,cmd): func=getattr(self,cmd) func() def get(self): print('get func') def put(self): print('put func') f=Ftpserver('192.168.1.2',21) f.run()
五、item用法
例子
class Foo: def __getitem__(self, item): print('=====>get') return self.__dict__[item] def __setitem__(self, key, value): self.__dict__[key]=value # setattr(self,key,value) def __delitem__(self, key): self.__dict__.pop(key)
六、__str__用法
class People: def __init__(self,name,age,sex): self.name=name self.age=age self.sex=sex def __str__(self): #在对象被打印时触发执行 return '<name:%s age:%s sex:%s>' %(self.name,self.age,self.sex) p1=People('egon',18,'male') p2=People('alex',38,'male') print(p1) print(p2) f=Foo() # f.x=1 # print(f.x) # print(f.__dict__) f['x']=123123123123 # del f['x'] print(f['x'])
七、__del__用法 释放
如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到了__del__
class Foo: def __init__(self,x): self.x=x def __del__(self): #在对象资源被释放时触发 print('-----del------') print(self) f=Foo(100000) del f print('=======================>')
八、异常处理
异常就是程序运行时发生错误的信号(在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止),在python中,错误触发的异常如下
1.1、异常的种类
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
1.2 异常处理
为了保证程序的健壮性与容错性,即在遇到错误时程序不会崩溃,我们需要对异常进行处理,
如果错误发生的条件是可预知的,我们需要用if进行处理:在错误发生之前进行预防
例子:
AGE=10 while True: age=input('>>: ').strip() if age.isdigit(): #只有在age为字符串形式的整数时,下列代码才不会出错,该条件是可预知的 age=int(age) if age == AGE: print('you got it') break 如果错误发生的条件是不可预知的,则需要用到try...except:在错误发生之后进行处理 #基本语法为 try: 被检测的代码块 except 异常类型: try中一旦检测到异常,就执行这个位置的逻辑 #举例 try: f=open('a.txt') g=(line.strip() for line in f) print(next(g)) print(next(g)) print(next(g)) print(next(g)) print(next(g)) except StopIteration: f.close()