阅读目录python
一、封装 二、封装属性 三、封装方法 四、封装原理 五、property装饰器 六、多态 七、__str__内置函数 八、__del__内置函数 九、反射 十、动态导入模块 十一、反射在框架中的应用
##封装安全
#什么是封装? 对外部隐藏内部的属性,以及实现细节 , 给外部提供使用的接口 注意:封装有隐藏的意思,但不是单纯的隐藏 学习封装的目的.就是为了可以限制外界对内部数据的访问 python中属性的权限分为两种 1.公开的 没有任何限制 谁都能访问 2.私有的 只有当前类自己可以访问 默认为公共的 #为何须要封装 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 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!") # stu1 = Student("rose",20,"man","111111111111111111") # # print(stu1.name) # print(stu1.id_card) # stu1.id_card = "123" # print(stu1.id_card) stu1 = Student("rose",20,"man","111111111111111111") # print(stu1.id_card) # print(stu1.__id_card) # stu1.show_id_card() # stu1.set_id_crad("222222222222222222") # stu1.show_id_card() # id = stu1.get_id_card() # print(id) # stu1.set_id_crad(123) stu1.set_id_crad("555555555555555555") # print(stu1.get_id_card()) print(stu1.get_id_card("1232"))
##封装方法函数
什么样的方法应该被封装起来 ? 答:一个为内部提供支持的方法,不该该让外界直接访问,那就封装起来 ,以下例中的 user_auth等... #示例1 class ATM: def withdraw(self): self.__user_auth() self.__input_money() self.__save_record() # 输入帐号和密码 # 显示余额 # 输入取款金额 # 保存记录 def __user_auth(self): print("请输入帐号密码....") def __input_money(self): print("余额为100000000,请输入取款金额!") def __save_record(self): print("记录流水....") atm = ATM() # atm.user_auth() # atm.input_money() # atm.save_record() # atm.withdraw() # atm.save_record()
##封装原理学习
python是经过 变形的方式来实现的封装 如何变形 在名称带有双下划线开头的变量名字前添加_类名 如_Person__id_card 固然经过变形后的名字能够直接访问被隐藏的属性 但经过不该该这么作 变形仅在类的定义阶段发生一次 后续再添加的带有双下划线的任何属性都不会变形 就是普通属性 #示例1 class Person: def __init__(self,name,age,id_card): self.name = name self.age = age self.__id_card = id_card def get_id_card(self): return self.__id_card p = Person("rose",20,"321123123123123123") print(p.name) # p.__id_card = "321" # print(p.__dict__) # print(p._Person__id_card) p.__gender = "man" print(p.__dict__)
##property装饰器ui
做用: 将一个方法假装成普通属性 为何用 property 但愿将访问私有属性和普通属性的方式变得一致 与property相关的 两个装饰器 setter 用点语法 给属性赋值时触发 deleter 用点语法删除属性时触发 #示例 class Teacher: def __init__(self,name,age,salary): self.name = name self.age = age self.__salary = salary @property # getter # 用于访问私有属性的值 也能够访问普通属性 def salary(self): return self.__salary @salary.setter # 用来设置私有属性的值 也能够设置普通属性 def salary(self,new_salary): self.__salary = new_salary @salary.deleter # 用来设置私有属性的值 也能够删除普通属性 def salary(self): # print("can not delete salary!") del self.__dict__["_Teacher__salary"] # del self.__salary #一般property 用于操做私有的属性 t = Teacher("egon",38,100000) # # print(t.get_salary()) # # t.set_salary(5000) # # print(t.get_salary()) # print(t.name) # 被封装的属性在访问时 须要调用方法 而普通属性直接点就ok 这样一来对于对象的使用者而言 # 必须知道要访问的属性 是私有的仍是公开 而后调用对于的方法 用起来麻烦 # 此时 咱们的目标是 让访问私有属性 和访问普通属性的方式一直 # property 装饰器 就是用来将一个方法假装成属性 # print(t.salary) # t.salary = 500 # print(t.salary) # 删除对象属性 # del t.name # # print(t.name) # del t.salary # a = {"name":123} # # a.pop("name") # # del a["name"] # # print(a) del t.salary # # t.del_salary() # t.salary = 1 # # # # print(t.salary) # # del t.salary # t.get_salary() # t.set_salary(800) # t.delete_salary() # t.salary # t.salary = 800 # del t.salary
##property的另外一种使用场景:计算属性this
什么是计算属性 一个属性 它的值不是固定死的 而是经过计算动态产生的。 例如:BMI指数 #示例1 class Person: def __init__(self,name,height,weight): self.name = name self.height = height self.weight = weight # self.BMI = weight / (height ** 2) @property def BMI(self): return self.weight / (self.height ** 2) @BMI.setter def BMI(self,new_BMI): print("BMI 不支持自定义.....") p = Person("egon",1.7,80) # print(p.BMI) # # # p.weight = 60 # print(p.BMI) # print(p.get_BMI()) # p.weight = 60 # # print(p.get_BMI()) # # print(p.name) # print(p.get_BMI()) # # print(p.BMI) # p.weight = 60 # print(p.BMI) # p.BMI = 10
##封装能不能被继承问题spa
# 被封装的内容(私有的) 不能够被继承 # class A: # __name = "rose" # _A__name # # def __say_hi(self): # print("A say: hi") # class B(A): # def test(self): # # print(super().__name) #_B__name # print(A._A__name) # # pass # b = B() # b.test()
##多态设计
多态不是一个具体的技术 或代码 指的是 多个不一样类型对象 能够响应同一个方法 ,产生不一样结果 例如 水: 气态 固态 液态 动物: 人 猫 猪 汽车人: 汽车 飞机 人型 OOP中 标准解释: 多个不一样类型对象 能够响应同一个方法 而且产生不一样结果 多态的带来的好处: 只须要学习基类中的使用方法便可, 不须要关心具体的哪个类 以及实现的 以不变应万变 提升了灵活性 提升扩展性 若是没有多态 须要分别学习 person cat pig 的不一样使用方法 这对于使用者而言太麻烦了 如何实现多态: 鸭子类型 就是典型的多态 多种不一样类型 使用方法同样 #示例1 class Person(): def bark(self): print("Hello!") def run(self): print("两条腿跑!") def sleep(self): print("躺着睡!") 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("侧躺着睡!") # person1 = Person() # cat1 = Cat() # pig1 = Pig() # person1.sleep() # cat1.sleep() # pig1.sleep()
class Dog:
def bark(self):
print('汪汪汪')
def run(self):
print('四条腿在跑')
def sleep(self):
print('躺着睡')
class Cat:
def bark(self):
print('喵喵喵')
def run(self):
print('四条腿在跑')
def sleep(self):
print('趴着睡')
def manage_animal(animal):
print('========%s====='%animal.__class__.__name__)
animal.bark()
animal.run()
animal.sleep()
dog = Dog()
manage_animal(dog)
cat = Cat()
manage_animal(cat)
继承:是类与类之间的关系,什么是什么的关系,好处是经过继承可使用父类中的属性和方法code
封装:对外部隐藏属性和实现细节,同时提供调用的接口,目的提升数据的安全度 和隔离复杂度
多态:不一样类型的对象使用同一方法产生不一样的结果,好处是学习统一标准,提升灵活性和拓展性
##经常使用的内置函数
#__str__ 类中的__str__ 该方法在object中有定义 默认行为 返回对象类型以及地址 <__main__.Person object at 0x0000016F450C7390> 在将对象转为字符串时执行 注意:返回值必须为字符串类型 子类能够覆盖该方法来完成 对打印内容的自定义 #示例1 class Person: def __init__(self,name,age): self.name = name self.age = age # 将对象转换为字符串时执行 def __str__(self): print("str run") return "my name is %s , age is %s" % (self.name,self.age) p = Person("rose",20) # print(p) #在打印前都会现将要打印的内容转为字符串 经过调用__str__函数 str(p) #__del__ """ __del__ 当对象被删除前会自动调用 该方法 声明时候会删除对象? 1.程序运行结束 解释器退出 将自动删除全部数据 2.手动调用del 时也会删除对象 注意:该函数不是用来删除对象的 使用场景 当你的对象在建立时,开启了不属于解释器的资源 例如打开了一个文件 必须保证当对象被删除时 同时关闭额外的资源 如文件 也称之为析构函数 构造 的反义词 构造 指的是从无到有 析构 值从有到无 简单的说就对象全部数据所有删除 总结:__del__该函数 用于 在对象删除前作一些清理操做 """ #示例1 # 假设要求每个person对象都要绑定一个文件 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() # p = Person("jack") # a = 10 # f = open("test.txt") # print(f.read()) # f.close() p2 = Person("rose","本周内容") print(p2.read_data())
##反射
#英文中叫检讨 (自省) 面向对象中的检讨 指的是,一个对象必须具有,发现自身属性,以及修改自身属性的能力; 一个对象在设计初期,可能考虑不够周全后期须要删除或修改已经存在的属性, 和增长属性 反射就是经过字符串来操做对象属性 涉及到的方法: 1、hasattr 判断是否存在某个属性 2、getattr 获取某个属性的值 3、setattr 新增或修改某个属性 4、delattr 删除某个属性 #示例1 import os class Student: def __init__(self,name): self.name = name stu = Student("rose") # stu.age = 18 # # print(stu.name) # print(hasattr(stu,"name")) print(getattr(stu,"name")) # # setattr(stu,"name","jack") # print(getattr(stu,"name")) # # delattr(stu,"name") # print(stu.name) #示例2 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....!")
##动态导入模块
直接写import 称之为静态导入 创建在一个基础时 提早已经知道有这个模块 动态导入 指的是 在须要的任什么时候候 经过指定字符串类型包名称来导入须要的模块 import importlib mk = importlib.import_module(m_name) mk 即导入成功的模块 该方式经常使用在框架中 由于框架设计者不可能提早预知后续须要的模块和类
动态引入引入一个模块,name能够是相对路径和绝对路径,若是是相对路径的话,这package就是相应的包名
#示例 import importlib m_name = input("请输入要导入的模块名称:") #执行要输入模块名称:build_house.core mk = importlib.import_module(m_name) print(mk) from build_house import conf print(conf) 注解:print(mk) 和print(conf) 结果同样的
##反射在框架中的应用
#core.py文件 import importlib from 代码.build_house import conf def building(): print("毛坯房建造完成.......") # 读取用户提供配置信息 来加载用户所须要的一系列装饰品 for cls_info in conf.decorations: # print(cls_info) # 切割类名和模块路径 m_name,cls_name = cls_info.rsplit(".",1) # print(m_name,cls_name) # 导入模块 mk = importlib.import_module(m_name) # print(mk) # 从模块中获取类 if not hasattr(mk,cls_name): continue cls = getattr(mk,cls_name) obj = cls() print(obj) building() #conf.py文件 decorations = ["build_house.my_decoration.Table", "build_house.my_decoration.Bed", "build_house.my_decoration.Light", "other_decoration.Sofa"] #my_decoration.py文件 class Table: pass class Light: pass class Bed: pass