# 1 封装 # 什么是封装 :对外部隐藏属性和方法 给外部提供使用的接口 # 目的:限制外部对内部数据的访问 因为有些数据是机密的 不方便对外透露 # 如何封装: __开头的语法 分为封装属性 和 封装方法 # 封装的好处: 封装属性--提高安全性 封装方法:提高便利性 # 封装属性 ''' class Student: def __init__(self,name,age,id_card): self.name = name self.age = age self.__id_card = id_card # 外部就无法通过.id_card 和 .__id_card def show_id_card(self): print(self.__id_card) stu = Student('tom',18,'xxxxxxxx') print(stu.name) # tom print(stu.age) # 18 # print(stu.__id_card) 是没有这个的 stu.show_id_card() # xxxxxxxx ''' # 对私有属性的访问以及修改 ''' class Student: def __init__(self,name,age,id_card): self.name = name self.age = age self.__id_card = id_card # 外部就无法通过.id_card 和 .__id_card def get_id_card(self,pwd): # 访问被封装的属性 称之为访问器 可以为访问添加条件 if pwd == '123': return self.__id_card else: print('密码错误') def set_id_card(self,new_id_card): # 修改被封装的属性称之为设置器 # 身份证必须是字符 且 是18位 if isinstance(new_id_card,str) and len(new_id_card) == 18: self.__id_card = new_id_card else: print('新身份证不符合规定') stu = Student('tom',18,'123456789012345678') stu.get_id_card('wsx') # 密码错误 stu.set_id_card('123456789123456789') # 无结果 ''' # 给方法封装 说明这方法可以被内部访问 不应该被外界访问 """ class ATM: def withdraw(self): self.__user_auth() self.__input_money() self.__save_record() # 输入账号和密码 # 显示余额 # 输入取款金额 # 保存记录 def __user_auth(self): print('输入用户名和密码') def __input_money(self): print('余额为1000000,输入取款金额!') def __save_record(self): print('记录流水......') atm = ATM() atm.withdraw() # 提现只需要调用withdraw就可以了 不需要一步一步去操作其他三个步骤 简化了外部操作 """ # 2:property装饰器 的 用途1 # 作用:将方法伪装成普通属性 # 为什么要用property 希望将私有属性的访问方式和普通属性一致 普通属性 点语法 # 与property相关的 两个装饰器 # setter # 用点语法 给属性赋值时触发 # # deleter # 用点语法删除属性时触发 # 案例 ''' class Teacher: def __init__(self,name,age,salary): self.name = name self.age = age self.__salary = salary # s实质是在名称空间里换名字为 _Teacher__salary @property def salary(self): # getter # 用于访问私有属性的值 也可以访问普通属性 return self.__salary @salary.setter # 用来设置私有属性的值 也可以设置普通属性 def salary(self,new_salary): self.__salary = new_salary @salary.deleter def salary(self): del self.__dict__['_Teacher__salary'] # 删除老师薪水部分 a = Teacher('jeck',18,50) # 这是访问私有属性 print(a.salary) # 50 a.salary=10 # 赋值时运用 setter print(a.salary) # 10 del a.salary # 已删除salary部分 # print(a.salary) 这时打印会报错的 ''' # property装饰器 的 用途2 :计算属性 # 有些属性不是固定的 是需要计算出来的 这是也可以用到property # 例如计算BMI 体质指数(BMI)=体重(kg)÷身高^2(m) ''' 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) @BMI.setter def BMI(self,new_bmi): print('bmi不支持自定义') p = People('egon',80,1.7) print(p.BMI) # 27.68166089965398 p.BMI = 10 # 运行这步 不会更改值 bmi不支持自定义 print(p.BMI) # 27.68166089965398 结果还是这个不会变的 计算属性时 setter 不受用
# 多态 # 定义:多个不同类型对象可以响应同一个产生不同的结果 ***** # 好处: 只需要学习基类中的使用方法即可, 不需要关心具体的哪一个类 以及实现的 以不变应万变 提高了灵活性 提高扩展性 # 如果没有多态 需要分别学习 person cat pig 的不同使用方法 这对于使用者而言太麻烦了 # 人 和 猫 和猪都有一些相同的技能 会说话 会跑 会睡觉 但是这三种技能动物都拥有 那么可以运用多态建立一个动物三种函数 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('侧躺着睡') def management_animal(animal): print("==================正在溜%s=============" % animal.__class__.__name__) animal.bark() animal.run() animal.sleep() # 来了一堆动物 person1 = Person() cat1 = Cat() pig1 = Pig() management_animal(person1) management_animal(cat1) management_animal(pig1)
# 类中的 内置函数 __str__ """ 类中的__str__ 该方法在object中有定义 默认行为 返回对象类型以及地址 <__main__.Person object at 0x0000016F450C7390> 在将对象转为字符串时执行 注意:返回值必须为字符串类型 子类可以覆盖该方法来完成 对打印内容的自定义 """ 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) # str run # 类中__del__ """ __del__ 当对象被删除前会自动调用 该方法 声明时候会删除对象? 1.程序运行结束 解释器退出 将自动删除所有数据 2.手动调用del 时也会删除对象 注意:该函数不是用来删除对象的 使用场景 当你的对象在创建时,开启了不属于解释器的资源 例如打开了一个文件 必须保证当对象被删除时 同时关闭额外的资源 如文件 也称之为析构函数 构造 的反义词 构造 指的是从无到有 析构 值从有到无 简单的说就对象所有数据全部删除 总结:__del__该函数 用于 在对象删除前做一些清理操作 """ # 假设要求每一个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()) # 具体看运行结果 ''' # 反射 面向对象中指的就是 对象必须具备发现自己属性以及修改自己属性的能力 # 因为在创建初期的属性可能不符合后期要求 则需要删除或增加或修改属性 # 四个方法 # hasattr 判断是否存在这个属性 # getattr 取得这个属性的值 # setattr 增加或修改某属性的 # delattr 删除某个属性 # 案例 """ import os 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('不存在这个方法') # 可输入 dir 和 ipconfig 两个方法 """ # 动态导入 # import 是静态导入 是提前知道有这个模块 # 动态导入:在需要的时候 通过指定字符串形式来导入需要的模块 # 语法 import importlib mk = importlib.import_module(m_name) # m_name 指的就是模块名 print(mk) # mk 就是导入的模块