今日内容
封装
接口
一、封装
1、什么是封装
封装就是将复杂的丑陋的、隐私的细节隐藏到内部,对外提供简单的使用接口的过程。
2、为社么要封装
封装有两个目的:一是为了保证关键数据的安全性,而是为了对外部隐藏实现细节,隔离复杂度。
3、什么时候应该封装
当有一些数据不希望外界可以直接修改或者有一些函数不希望给外界使用的时候,可以使用封装。
4、封装的使用
在需要封装的属性或者函数的名字前加双下划线,如下实例:
class Person(object): def __init__(self,id,name,age): self.__id = id self.name = name self.age = age def __address(self): print("地址是。。。".self.name)
被封装的属性或者方法是不能直接获取或者修改的,可以通过间接的方法获取或者修改。
class Downloader: def __init__(self,filename,url,buffer_size): self.filename = filename self.url = url self.__buffer_size= buffer_size def start_download(self): if self.__buffer_size <= 1024*1024: print("开始下载....") print("当前缓冲器小",self.__buffer_size) else: print("内存炸了! ") def set_buffer_size(self,size): #可以在方法中添加额外的逻辑 if not type(size) == int: print("大哥 缓冲区大小必须是整型") else: print("缓冲区大小修改成功!") self.__buffer_size = size def get_buffer_size(self): return self.__buffer_size
上例代码中的封装属性buffer_size属性是不可被外界直接获取和修改的,但是将其放在一个可被调用的set_buffrt_size方法中,通过给改方法传参达到修改buffer_size的目的,通过方法get_buffer_size达到获取buffer_size的目的。
5、property装饰器
在调用方法的时候需要加括号,调用属性的时候不需要加括号,在不知道是方法还是属性的情况下容易出现使用错误,不便于调用,为了让两种调用的形式保持一致,可以通过调用property装饰器实现需求。
当调用的方法不用传参数的时候:
class Downloader: def __init__(self,filename,url,buffer_size): self.filename = filename self.url = url self.__buffer_size= buffer_size @proprety def start_download(self): if self.__buffer_size <= 1024*1024: print("开始下载....") print("当前缓冲器小",self.__buffer_size) else: print("内存炸了! ") def set_buffer_size(self,size): #可以在方法中添加额外的逻辑 if not type(size) == int: print("大哥 缓冲区大小必须是整型") else: print("缓冲区大小修改成功!") self.__buffer_size = size @proprety def get_buffer_size(self): return self.__buffer_size
当被调用的方法中需要传参时:
class Downloader: def __init__(self,filename,url,buffer_size): self.filename = filename self.url = url self.__buffer_size= buffer_size @proprety def start_download(self): if self.__buffer_size <= 1024*1024: print("开始下载....") print("当前缓冲器小",self.__buffer_size) else: print("内存炸了! ") @proprety def set_buffer_size(self): return self.__buffer_size @set_buffer_size.setter def set_buffer_size(self,size): #可以在方法中添加额外的逻辑 if not type(size) == int: print("大哥 缓冲区大小必须是整型") else: print("缓冲区大小修改成功!") self.__buffer_size = size @proprety def get_buffer_size(self): return self.__buffer_size
6、计算属性
所谓计算属性就是获取自己属性的值,并计算得到新的值赋值给另一个属性,另一个属性就叫做计算属性。
当获取的属性的值改变时,计算属性的值时不变的,此时可以通过定义一个方法,将计算的过程放入其中,可以解决计算属性的值不变的过程。
class Squre(object): def __init__(self,line): self.line = line self.s = self.line**2 s = Squre(3) print(s.s) # 9 s.line = 4 print(s.s) # 9 # 解决办法 class Squre(object): def __init__(self,line): self.line = line @proprety def s(self): return self.line**2 s = Squre(3) print(s.s) # 9 s.line = 4 print(s.s) # 16
二、接口
1、什么叫接口
接口是一组功能的集合,但是接口中仅包含功能的名字,不包含具体的实现代码。接口本质是一套协议标准,遵循这个标准的对象就能被调用 。
class USB: def open(self): pass def close(self): pass def read(self): pass def write(self): pass class Mouse(USB): def open(self): print("鼠标开机.....") def close(self): print("鼠标关机了...") def read(self): print("获取了光标位置....") def write(self): print("鼠标不支持写入....") def pc(usb_device): usb_device.open() usb_device.read() usb_device.write() usb_device.close() m = Mouse() # 将鼠标传给电脑 pc(m) class KeyBoard(USB): def open(self): print("键盘开机.....") def close(self): print("键盘关机了...") def read(self): print("获取了按键字符....") def write(self): print("可以写入灯光颜色....") # 来了一个键盘对象 k = KeyBoard() pc(k)
在上述案例中,PC的代码一旦完成,后期无论什么样的设备,只要遵循了USB接口协议,都能够被电脑所调用。接口主要是方便了对象的使用者,降低使用者的 学习难度,只要学习一套使用方法,就可以以不变应万变 。
2、python中的“接口”
在python中,追求的时不限制程序员取如何编写代码,所以并没有接口这一说法。比如上述代码中USB类可以不用写,在写鼠标和键盘的功能函数时,只要程序员遵守要求编写代码即可,在python中,一个程序员应该自觉遵守规则。
3、abc模块的使用
抽象类:指的是包含抽象方法(没有函数体的方法)的类,用来限制子类中必须定义的抽象方法。上述代码中的USB类即为一个抽象类。
假如某个程序员不遵守抽象类中的抽象方法的定义,定义了其它的方法或者没有定义某种方法,此时可以通过调用abc模块进行限制,不按照规定的抽象方法定义就报错。
import abc class AClass(metaclass=abc.ABCMeta): @abc.abstractmethod def run(self): pass @abc.abstractmethod def run1(self): pass class B(AClass): def run(self): print("runrunrurn...") b = B()
上诉代码中的B类没有定义run1()方法,程序无法正常运行。