面向对象之派生方法、封装、伪装、三大特性、反射
1|0面向对象之派生方法、封装、伪装、三大特性、反射
1|1派生方法实战演练
1|0什么是派生方法?
- 子类中的定义方法和父类定义方法一模一样的方法,并且扩展了新功能(子类和父类一样,但是子类可以修改父类自定义新功能)
import json import datetime d = { 't1': datetime.date.taday(), 't2': datetime.datetime.today(), 't3': 'jason' } # 导入datetime、json模块直接打印 res=json.dumps(d) print(res) """ 出现报错,AttributeError: type object 'datetime.date' has no attribute 'taday' 查看源码发现datetime模块不能直接序列化(必须是要图片里面显示的类型) """ """ 能够被序列化的数据是有限的>>>:里里外外都必须是下列左边的类型 +-------------------+---------------+ | Python | JSON | +===================+===============+ | dict | object | +-------------------+---------------+ | list, tuple | array | +-------------------+---------------+ | str | string | +-------------------+---------------+ | int, float | number | +-------------------+---------------+ | True | true | +-------------------+---------------+ | False | false | +-------------------+---------------+ | None | null | +-------------------+---------------+ """ #解决方法:手动将不符合数据类型转成符合要求的数据类型 like={ 't1':str(datetime.datetime.today()), 't2':str(datetime.date.today()) } res=json.dumps(like) print(res) """ 输出结果:{"t1": "2022-11-07 15:18:39.654295", "t2": "2022-11-07"} """ # 利用派生方法 like={ 't1':datetime.datetime.today(), 't2':datetime.date.today() } res=json.dumps(like) """ 出现报错:TypeError: Object of type datetime is not JSON serializable 查看JSONEncoder源码发现序列化报错是由default方法触发的 raise TypeError(f'Object of type{o._class_._name_}'f'is not JSONli serializable') 我们如果想要避免报错,那么肯定需要对default方法做修改(派生) """ Like = { 't1': datetime.datetime.today().__str__(), 't2': datetime.date.today().__str__(), } class MyJsonEncode(json.JSONEncoder): def default(self, o): # o就是json即将要序列化的数据 if isinstance(o, datetime.datetime): return o.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(o, datetime.date): return o.strftime('%Y-%m-%d') # 如果是可以序列化的类型 那么不做任何处理 直接让它序列化即可 return super().default(o) '''让python的不走自己的default走我们自定义的default再放他回去走它的''' res = json.dumps(Like, cls=MyJsonEncode) print(res) json.dumps(Like, cls=MyJsonEncode) """ 输出结果: {"t1": "2022-11-07 16:31:04.973732", "t2": "2022-11-07"} """
1|2面向对象三大特性之封装
1|0什么是封装?
- 封装就是把数据或者功能隐藏起来、包起来
- 隐藏的目的不是让用户无法使用,而是给这些隐藏的数据开设定的接口
1|0什么是伪装?
- 将类里面的方法伪装成类里面的数据
class Student(object): _school = '清华大学' def _init_(self, name, age): self._name = name self._age = age 1.在类的定义阶段使用双下划线开头的名字都是隐藏的属性(后续类和对象都不可以直接获取 会报错) 2.在python中不会真正的限制任何代码,隐藏的属性如果真的需要访问也可以,只不过需要做变形处理 eg: __隐藏的变量名,实际在名称空间里面_类名__变量名 ps:既然是隐藏,就不应该使用变形之后的名字去访问,那样就没有隐藏的意义了 class Person: def __init__(self, name, age, hobby): self.__name = name # 对象也可以拥有隐藏的属性 self.__age = age self.__hobby = hobby def get_info(self): # 类体代码中 是可以直接使用隐藏的名字 print(f""" 姓名:{self.__name} 年龄:{self.__age} 爱好:{self.__hobby} """) # 隐藏的属性开放修改的接口 可以自定义很多功能 def set_name(self, new_name): if len(new_name) == 0: raise ValueError('你好歹写点东西') if new_name.isdigit(): raise ValueError('名字不能是数字') self.__name = new_name obj = Person('jason', 18, 'read') obj.get_info() # obj.set_name('tony老师') # obj.get_info() obj.set_name('') """ 以后我们在编写面向对象代码类的定义时 也会看到很多单下划线开头的名字 表达的意思通常特使不要直接访问 而是查找一下下面可能定义的接口 """
1|0伪装
BMI指数:衡量一个人的体重与身高对健康影响的一个指标 体质指数(BMI)=体重(kg)÷身高^2(m) EX:70kg÷(1.75×1.75)=22.86 class Person(object): def __init__(self, name, height, weight): self.name = name self.height = height self.weight = weight @property def BMI(self): return self.weight / (self.height ** 2) p1 = Person('jason', 1.83, 78) # p1.BMI() # BMI应该作为人的基本数据而不是方法 # print(p1.BMI) # 利用装饰器伪装成数据 class Foo: def __init__(self, val): self.__NAME = val # 将属性隐藏起来 @property def name(self): return self.__NAME @name.setter def name(self, value): if not isinstance(value, str): # 在设定值之前进行类型检查 raise TypeError('%s must be str' % value) self.__NAME = value # 通过类型检查后,将值value存放到真实的位置self.__NAME @name.deleter def name(self): raise PermissionError('Can not delete') f = Foo('jason') print(f.name) f.name = 'jason123' print(f.name) del f.name # f.name = 'jason' # 触发name.setter装饰器对应的函数name(f,’jason') # f.name = 123 # 触发name.setter对应的的函数name(f,123),抛出异常TypeError # del f.name # 触发name.deleter对应的函数name(f),抛出异常PermissionError
1|3面向对象三大特性之多态
多态:一种事物的多种形态 水:液态 固态 气态 动物:人 猪 猫 狗 # class Animal: # def spark(self): # '''叫的方法''' # pass # # # class Cat(Animal): # # def miao(self): # # print('喵喵喵') # def spark(self): # print('喵喵喵') # # # class Dog(Animal): # # def wang(self): # # print('汪汪汪') # def spark(self): # print('汪汪汪') # # # class Pig(Animal): # # def heng(self): # # print('哼哼哼') # def spark(self): # print('哼哼哼') """ 面向对象中多态意思是 一种事物可以有多种形态但是针对相同的功能应该定义相同的方法 这样无论我们拿到的是哪个具体的事物 都可以通过相同的方法调用功能 """ # s1 = 'hello world' # l1 = [11, 22, 33, 44] # d = {'name': 'jason', 'pwd': 123} # print(s1.__len__()) # print(l1.__len__()) # print(d.__len__()) """ 鸭子类型:只要你看上去像鸭子 走路像鸭子 说话像鸭子 那么你就是鸭子 """ # linux系统 """ 文件 能够读取数据也能够保存数据 内存 能够读取数据也能够保存数据 硬盘 能够读取数据也能够保存数据 ...... 一切皆文件 """ # class File: # def read(self): pass # # def write(self): pass # # # class Memory: # def read(self): pass # # def write(self): pass # # # class Disk: # def read(self): pass # # def write(self): pass '''python永远提倡自由简介大方 不约束程序员行为 但是多态提供了约束的方法''' import abc # 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化 class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法 def talk(self): # 抽象方法中无需实现具体的功能 pass class Cat(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准 def talk(self): pass cat = Cat() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化
1|4面向对象之反射
利用字符串操作对象的数据和方法 1.hasattr() 重点 判断对象是否含有某个字符串对应的属性名或方法名 2.getattr() 重点 根据字符串获取对象对应的属性名(值)或方法名(函数体代码) 3.setattr() 根据字符串给对象设置或者修改数据 4.delattr() 根据字符串删除对象里面的名字 # class C1: # school_name = '小姐姐学院' # # def choice_course(self): # print('大宝贝们正在选课') # # obj = C1() '''判断某个名字对象是否可以使用(存在)''' # 推导思路 # try: # obj.xxx # except AttributeError: # print('你木有这个名字') '''判断用户随意指定的名字对象是否可以使用(存在)''' # target_name = input('请输入对象可能使用的名字>>>:').strip() # try: # obj.target_name # except AttributeError: # print('你木有这个名字') """ 字符串的名字跟变量名区别大不大 'school_name' school_name 非常大 完全不一样 """ # 反射:利用字符串操作对象的数据和方法 # print(hasattr(obj, 'school_name')) # True # print(getattr(obj, 'school_name')) # 小姐姐学院 # print(getattr(obj, 'choice_course')) # <bound method C1.choice_course of <__main__.C1 object at 0x00000248C0B65A30>> class C1: school_name = '小姐姐学院' def choice_course(self): print('大宝贝们正在选课') obj = C1() while True: target_name = input('请输入您想要操作的名字>>>:') if hasattr(obj, target_name): print('恭喜您 系统中有该名字') # 获取该名字对应的数据(值 函数) data_or_func = getattr(obj, target_name) if callable(data_or_func): print('您本次使用的是系统中的某个方法') data_or_func() else: print('您本次使用的是系统中的某个数据') print(data_or_func) else: print('很抱歉 系统中没有该名字')
1|5反射实战案例
1.什么时候应该考虑使用反射 只要需求中出现了关键字 对象....字符串.... 2.实战案例 1.模拟cmd终端 class WinCmd: def tasklist(self): print(""" 1.学习编程 2.学习python 3.学习英语 """) def ipconfig(self): print(""" 地址:127.0.0.1 地址:上海浦东新区 """) def get(self, target_file): print('获取指定文件',target_file) def put(self, target_file): print('上传指定文件',target_file) def server_run(self): print('欢迎进入简易版本cmd终端') while True: target_cmd = input('请输入您的指令>>>:') res = target_cmd.split(' ') if len(res) == 1: if hasattr(self, res[0]): getattr(self, res[0])() else: print(f'{res[0]}不是内部或者外部命令') elif len(res) == 2: if hasattr(self, res[0]): getattr(self, res[0])(res[1]) else: print(f'{res[0]}不是内部或者外部命令') obj = WinCmd() obj.server_run() 2.一切皆对象 # 利用反射保留某个py文件中所有的大写变量名及对应的数据值 import settings print(dir(settings)) # dir列举对象可以使用的名字 useful_dict = {} for name in dir(settings): if name.isupper(): useful_dict[name] = getattr(settings, name) print(useful_dict) # while True: # target_name = input('请输入某个名字') # if hasattr(settings, target_name): # print(getattr(settings, target_name)) # else: # print('该模块文件中没有该名字')
__EOF__

本文作者:知了了了了
本文链接:https://www.cnblogs.com/zhiliaowang/p/16866627.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/zhiliaowang/p/16866627.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现