封装,多态,内置函数,反射
封装
什么是封装:
一个为内部提供支持的方法或者属性,不应该让外界直接访问,那就封装起来,这就是封装
封装的原理:
python是通过 变形的方式来实现的封装
如何变形 在名称带有双下划线开头的变量名字前添加_类名 如_Person__id_card
当然通过变形后的名字可以直接访问被隐藏的属性 但通过不应该这么做
变形仅在类的定义阶段发生一次 后续再添加的带有双下划线的任何属性都不会变形 就是普通属性
封装的好处:
1.提高安全性
封装属性
2.隔离复杂度
封装方法
封装属性:
class Student: def __init__(self,name,age,gender,id_card): self.name = name self.age = age self.gender = gender self.__id_card = id_card def show_id_card(self): # 可以在这里添加额外的任何逻辑代码 来限制外部的访问 #在类的内部 可以访问 print(self.__id_card)
对私有属性的访问以及修改
class Student: def __init__(self,name,age,gender,id_card): self.name = name self.age = age self.gender = gender self.__id_card = id_card # 访问被封装的属性 称之为访问器 def get_id_card(self,pwd): # 可以在这里添加额外的任何逻辑代码 来限制外部的访问 # 在类的内部 可以访问 if pwd =="123": return self.__id_card raise Exception("密码错误!") # 修改被封装的属性 称之为设置器 def set_id_crad(self,new_id): # 身份证必须是字符串类型 # 长度必须是18位 if isinstance(new_id,str) and len(new_id) == 18: self.__id_card = new_id else: raise Exception("身份证号码 必须是字符串 且长度必须为18!")
Property
作用: 将一个方法伪装成普通属性
为什么用 property 希望将访问私有属性和普通属性的方式变得一致
与property相关的 两个装饰器
setter
用点语法 给属性赋值时触发
deleter
用点语法删除属性时触发
class Person: def __init__(self,name,age,gender,id_card): self.name = name self.age = age self.gender = gender self.__id_card = id_card @property def id_card(self): return self.__id_card @id_card.setter def id_card(self,new_id_card): self.__id_card = new_id_card @id_card.deleter def id_card(self): del self.__id_card # p = Person("rose",19,"woman","123455467") #获取私有的属性 # print(p.id_card) #修改私有的属性 # p.id_card = "1234567890" # print(p.id_card) #删除一个私有的属性 # del p.id_card # print(p.id_card) class User: def __init__(self,name,height,weitght): self.name = name self.height = height self.weitght = weitght # self.BMI = height/(weitght**2) @property def BMI(self): return self.height/(self.weitght**2) @BMI.setter def BMI(self,new_bmi): print("不能被修改!") u = User("老男孩",170,60) print(u.BMI) u.weitght = 70 print(u.BMI) #不能修改计算属性,计算属性是通过计算得来的,不是复制得来的 u.BMI = 90View Code
多态
什么是多态:
多态不是一个具体的技术 或代码
指的是 多个不同类型对象 可以响应同一个方法 ,产生不同结果
多态的带来的好处:
只需要学习基类中的使用方法即可, 不需要关心具体的哪一个类 以及实现的 以不变应万变 提高了灵活性
提高扩展性
如何实现多态:
鸭子类型 就是典型的多态 多种不同类型 使用方法一样
class Cat(): def bark(self): print("喵喵喵") def run(self): print("四条腿跑!") def sleep(self): print("趴着睡!") class Pig(): def bark(self): print("哼哼哼!") def run(self): print("四条腿跑!") def sleep(self): print("侧躺着睡!") # 一个用来管理动物的方法 只要你传入是一个动物 我就按照动物的标准来使用 完全不用考虑你具体是什么类型 def management_animal(animal): print("==================正在溜%s=============" % animal.__class__.__name__) animal.bark() animal.run() animal.sleep()
总结多态和封装重点
封装
什么是封装 *****
封装的好处 *****
如何封装
封装的原理
多态:
多态指的是 多个不同类型对象可以响应同一个方法产生不同的结果 *****
好处
好处: 只需要学习基类中的使用方法即可, 不需要关心具体的哪一个类 以及实现的 以不变应万变 提高了灵活性
提高扩展性
常用的内置函数
__str__
class Person: def __init__(self,name,age): self.name = name self.age = age def __str__(self): print("执行str 函数") p = Person("rose",18) p.__str__() # print(p)
__del__
当对象被删除前会自动调用 该方法 声明时候会删除对象? 1.程序运行结束 解释器退出 将自动删除所有数据 2.手动调用del 时也会删除对象 注意:该函数不是用来删除对象的 使用场景 当你的对象在创建时,开启了不属于解释器的资源 例如打开了一个文件 必须保证当对象被删除时 同时关闭额外的资源 如文件 也称之为析构函数 构造 的反义词 构造 指的是从无到有 析构 值从有到无 简单的说就对象所有数据全部删除 总结:__del__该函数 用于 在对象删除前做一些清理操作 class Person: def __init__(self,name,path,mode="rt",encoding="utf-8"): self.name = name self.file = open(path,mode,encoding=encoding) # 读取数据的方法 def read_data(self): return self.file.read() def __del__(self): print("del run!") self.file.close()View Code
反射
英文中叫反省 (自省)
面向对象中的反省 指的是,一个对象必须具备,发现自身属性,以及修改自身属性的能力;
一个对象在设计初期,可能考虑不够周全后期需要删除或修改已经存在的属性, 和增加属性
反射就是通过字符串来操作对象属性
涉及到的方法
hasattr 判断是否存在某个属性
getattr 获取某个属性的值
setattr 新增或修改某个属性
delattr 删除某个属性
案例:
class MY_CMD: def dir(self): os.system("dir") def ipconfig(self): os.system("ipconfig") cmd = MY_CMD() while True: name = input("请输入要执行的功能:") if hasattr(cmd,name): method = getattr(cmd,name) print(method) method() else: print("sorry this method is not exists....!")
动态导入模块
#D:\pypro\day26多态封装\动态导入模板\core.py import importlib from 动态导入模板 import conf def run(): for path in conf.decorations: pathName,className = path.rsplit(".",1) mk = importlib.import_module(pathName) if not hasattr(mk,className): return obj = getattr(mk,className) o = obj() # print(o) o.run() run() #D:\pypro\day26多态封装\动态导入模板\conf.py decorations = [ "动态导入模板.my_decoration.Table", "动态导入模板.my_decoration.Light", "动态导入模板.my_decoration.Bed", ] #D:\pypro\day26多态封装\动态导入模板\my_decoration.py class Table: def run(self): print("装修桌子好了") class Light: def run(self): print("装修灯好了") class Bed: def run(self): print("装修床好了")
直接写import 称之为静态导入 建立在一个基础上:提前已经知道有这个模块
动态导入 指的是 在需要的任何时候 通过指定字符串类型的包名称来导入需要的模块
import importlib
mk = importlib.import_module(m_name)
mk 即导入成功的模块
该方式常用在框架中 因为框架设计者不可能提前预知后续需要的模块和类