面向对象之封装
Posted sr-program
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象之封装相关的知识,希望对你有一定的参考价值。
一:封装
【1】基础概念
(1)什么是封装:
(1)字面意思是将什么封存在什么里面 达到隐藏的效果
例如:将电脑里的硬件封装在机盒中
(2)在程序中是将复杂的 丑陋的的细节封装在内部 对外部提供简易的接口 供人们使用
例如:电脑开机需要调度大量的硬件 但是这些硬件我们本身根本不需要考虑 直接使用开机键这个简单的接口就行
(2)封装的好处:
(1)保证数据的安全性:
(2)对外部隔离内部细节 降低复杂度
(3)封装使用场景:
(1)一些数据不希望外界直接修改的时
例如:数据库中的个人信息如果外部访问可以随时修改 会导致数据随时被篡改的危险
(2)一些函数不希望给外部直接使用的时候
例如:电脑开机的时候 加载操作系统 这些方式本身人为不需要管 因为只需要定义好 由硬件直接操作就可以 人为不需要干预
(4)封装的使用方式:
(1):对属性进行封装
例如:
class Person: def __init__(self,name,id_card): self.name = name self.__id_card = id_card def show_id_cart(self): return print(self.__id_card) p = Person(‘SR‘,123456789) print(p.id_card) # 123456789原始身份证信息 p.id_card = 987654321 print(p.id_card) # 987654321 身份证被修改 # 对数据进行封装 p.show_id_cart() # 123456789原始函数
PS:上述通过对属性进行封装 提高数据的安全性
(2)对方法进行封装
例如:
# class Person: # def __init__(self,name,id_card): # self.name = name # self.__id_card = id_card # # def show_id_cart(self): # return print(self.__id_card) # # # p = Person(‘SR‘,123456789) # # print(p.id_card) # 123456789原始身份证信息 # # p.id_card = 987654321 # # print(p.id_card) # 987654321 身份证被修改 # # # 对数据进行封装 # p.show_id_cart() # 123456789原始函数 class PC: def __init__(self,kind,price,): self.kind = kind self.price = price def open(self): print("接通电源") self.__check_device() print("载入内核") self.__start_services() print("初始化内核") print("启动GUI") self.__login() # 这些函数人们都是不需要使用的 进行封装 # 假如不开机 直接调用这些函数 也不合适 def __check_device(self): print("硬件检测1") print("硬件检测2") print("硬件检测3") print("硬件检测4") def __start_services(self): print("启动服务1") print("启动服务2") print("启动服务3") print("启动服务4") def __login(self): print("login....") print("login....") p = PC(‘apple‘,18888) p.open() # 正常启动 p.__login() # 报错
PS:
(1)对方法进行封装 防止不必要的方法被外界调用
(2)将不必须要的方法封装 只需要给外部提供一个可以访问的接口即可 降低复杂度
(5)封装特点:
(1)内部可以访问内部被封装的函数或者属性
(2)外部不可以直接访问内部被封装的函数或者属性
【2】封装扩展:
(1)权限问题
(1)默认属于公有的 大家都可以使用
(2)被封装之后即属于私有的 只能由当前类自己使用 外部不能直接调用
(2)如何访问被封装的属性:
(1)产生背景
(1)如果内部属性与方法被进行封装 导致外部不能直接读取 那么这些属性存在也没有直接意义
例如:上述用户不能直接读取直接的身份证,电脑使用开机键 也不能去取内部加载程序
(2)通过特殊的方法进行访问内部被封装属性或者方法
例如:
# # class Person: # # def __init__(self,name,id_card): # # self.name = name # # self.__id_card = id_card # # # # def show_id_cart(self): # # return print(self.__id_card) # # # # # # p = Person(‘SR‘,123456789) # # # # print(p.id_card) # 123456789原始身份证信息 # # # # p.id_card = 987654321 # # # # print(p.id_card) # 987654321 身份证被修改 # # # # # 对数据进行封装 # # p.show_id_cart() # 123456789原始函数 # # # # class PC: # def __init__(self,kind,price,): # self.kind = kind # self.price = price # # def open(self): # print("接通电源") # self.__check_device() # print("载入内核") # self.__start_services() # print("初始化内核") # print("启动GUI") # self.__login() # # # 这些函数人们都是不需要使用的 进行封装 # # 假如不开机 直接调用这些函数 也不合适 # def __check_device(self): # print("硬件检测1") # print("硬件检测2") # print("硬件检测3") # print("硬件检测4") # # def __start_services(self): # print("启动服务1") # print("启动服务2") # print("启动服务3") # print("启动服务4") # # def __login(self): # print("login....") # print("login....") # # # p = PC(‘apple‘,18888) # # p.open() # 正常启动 # # p.__login() # 报错 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: # 定义下载数据 类内部可以访问内部封装属性 self.__buffer_size = size # 只允许每次下载1M d = Downloader(‘新闻联播‘,‘百度‘,1024*1024) # d.start_download() # 自己私定义下载属性 因此需要对内部数据进行封装 # d.buffer_size = 1024*1024*10 # d.start_download() ‘‘‘ 1:虽然现在通过封装导致内部属性不能被随便修改 2:但是却将内部属性给限制死了 假如电脑配置比较差 每次只能读取0.5M的 3:现在却只能下载1m ‘‘‘ # 外部调用新的函数 d.set_buffer_size(1024*1024/2) d.start_download() # 524288.0 下载大小 ‘‘‘ 但是这样也没有意义 封装没有必要了 不如直接赋值为某个值 但是现在这个属于函数 可以添加额外的逻辑 或者属性 例如:加入用户上传字符串 现在不合理 我通过现在用户只能上传数字 ‘‘‘ d.set_buffer_size(‘132132‘) # 丢雷楼某 顶你个肺啊 不知道输入数字啊 d.set_buffer_size(1024*512) d.start_download() # 524288
PS:内部通过创建新的函数 主要可以进行一些逻辑上的判断
(3)装饰器
class User_info: def __init__(self,name,id_cart): self.name = name # 为了防止内部数据被外部随便修改 进行封装 self.__id_cart = id_cart @property def id(self): return self.__id_cart user = User_info(‘SR‘,12345678) # 被装饰之前 print(user.id()) # 12345678 被装饰之前 # 装饰后 print(user.id) # 12345678
(2)setter
(1)可以将私有属性按照普通属性的形式 进行修
例如:
class User_info: def __init__(self,name,id_cart): self.name = name # 为了防止内部数据被外部随便修改 进行封装 self.__id_cart = id_cart @property def id(self): return self.__id_cart @id.setter def id(self,new_id): # 添加条件限制 if type(new_id) == int: self.__id_cart = new_id # 查看该函数是否被行 print(‘代码正在执行‘) # 代码正在执行 print(self.__id_cart) # 987654321 else: print(‘丢雷楼某 顶你个肺啊 能不能好好输入啊!‘) user = User_info(‘SR‘,12345678) user.id = 987654321 print(user.id) # 987654321 user.id = ‘SR‘ print(user.id) # 丢雷楼某 顶你个肺啊 能不能好好输入啊!
(3)delete
class User_info: def __init__(self,name,id_cart): self.name = name # 为了防止内部数据被外部随便修改 进行封装 self.__id_cart = id_cart @property def id(self): return self.__id_cart @id.setter def id(self,new_id): # 添加条件限制 if type(new_id) == int: self.__id_cart = new_id # 查看该函数是否被行 print(‘代码正在执行‘) # 代码正在执行 print(self.__id_cart) # 987654321 else: print(‘丢雷楼某 顶你个肺啊 能不能好好输入啊!‘) @id.deleter def id(self): print(‘删除属性‘) # 删除属性 del self.__id_cart user = User_info(‘SR‘,12345678) del user.id #此时代码并没有被真正删除 print(user.id) # 删除属性
(4)封装的实现原理:
(1)就是在加载类的时候将__替换成了 _类名__
例如:
class Number: def __init__(self,number): self.__number = number @property def number(self): return self.__number n = Number(123) print(n.__dict__) # ‘_Number__number‘: 123 print(n._Number__number) # 123
(5)计算属性:
(1)属性的值 不能直接获取 必须通过计算获取
例如:
class Spure: def __init__(self,len): self.len = len @property def area(self): return self.len*self.len s = Spure(10) s.len = 20 print(s.area) # 400 s.len = 4 print(s.area) # 16
(6)接口:
(1)接口是一组功能的集合 但是接口只包含功能的名字 不包含功能代码
(2)其实本质就是一套标准协议 遵循这个标准协议的代码 就能被调用
(3)如果子类没有按照规范进行编写 也不能阻止代码运行
(2)抽象类
(1)没有具体功能(函数体代码)的类
(2)限制子类中必须定义的方法
(3)鸭子类型
(1)python具体不会限制人们该怎么写代码
(2)如果这个对象长的像鸭子 走路像鸭子就是鸭子类型
(3)即你只要按照相关协议来编写代码 也可以达到提高扩展性的目的
以上是关于面向对象之封装的主要内容,如果未能解决你的问题,请参考以下文章