内容概要
- 继承下的派生实际应用
- 面向对象的三大特征之封装
- 面向对象的三大特征之多态
- 面向对象之反射
继承下的派生实际应用
| import datetime |
| import json |
| |
| |
| 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) |
| |
| d1 = {'t1':datetime.datetime.today(),'t2':datetime.date.today()} |
| res = json.dumps(d1,cls=MyJsonEncode) |
| print(res) |
| |
| """ |
| TypeError: Object of type 'datetime' is not JSON serializable |
| json不能序列化python所有的数据类型 只能是一些基本数据类型 |
| json.JSONEncoder |
| |
| 1.手动将不能序列化的类型先转字符串 |
| {'t1': str(datetime.datetime.today()), 't2': str(datetime.date.today())} |
| 2.研究json源码并重写序列化方法 |
| 研究源码发现报错的方法叫default |
| raise TypeError("Object of type '%s' is not JSON serializable" % o.__class__.__name__) |
| 我们可以写一个类继承JSONEncoder然后重写default方法 |
| """ |
面向对象三大特征之封装
| |
| 将类中的某些名字'隐藏'起来 不让外界直接调用 |
| 更具有保密性 |
| 隐藏的目的是为了提供专门的通道才可访问 在通道内可以添加额外的功能 |
| |
| """ |
| 如何封装名字 |
| 在变量名的前面加上两个下划线__ |
| 封装的功能只在类定义阶段才能生效!!! |
| 在类中封装其实也不是绝对的 仅仅是做了语法上的变形而已 |
| __变量名 >>> _类名__变量名 |
| 我们虽然指定了封装的内部变形语法 但是也不能直接去访问 |
| 看到了就表示这个属性需要通过特定的通道(接口)去访问 |
| """ |
| |
| class Student(object): |
| school = '北京大学' |
| __label = '学以致用' |
| |
| def __init__(self, name, age): |
| self.name = name |
| self.age = age |
| def choose_course(self): |
| print('%s正在选课'%self.name) |
| stu1 = Student('Tom', 18) |
| print(stu1.school) |
| print(stu1.name) |
| print(stu1.age) |
| |
| print(Student.__dict__) |
| print(Student._Student__label) |
| print(stu1._Student__label) |
| |
| |
| """ |
| 将数据隐藏起来就限制了类外部对数据的直接操作,然后类内应该提供相应的接口来允许类外部间接地操作数据, |
| 接口之上可以附加额外的逻辑来对数据的操作进行严格地控制 |
| |
| 目的的是为了隔离复杂度,例如ATM程序的取款功能,该功能有很多其他功能组成 |
| 比如插卡、身份认证、输入金额、打印小票、取钱等,而对使用者来说,只需要开发取款这个功能接口即可,其余功能我们都可以隐藏起来 |
| """ |
| class Student(object): |
| __school = '北京大学' |
| def __init__(self,name,son): |
| self.__name = name |
| self.__son = son |
| |
| def chenk_info(self): |
| print(""" |
| 学生姓名:%s |
| 学生学号:%s |
| """ %(self.__name,self.__son)) |
| |
| def set_info(self,name,son): |
| if len(name) == 0: |
| print('名字不能为空') |
| return |
| if not isinstance(son,int): |
| print('学号必须纯数字') |
| return |
| self.__name = name |
| self.__son = son |
| |
| stu1 = Student('jimi',4250) |
| stu1.chenk_info() |
| stu1.set_info('Tom',1024) |
| stu1.chenk_info() |
| stu1.set_info('',666) |
| |
| """ |
| 由于python崇尚的是自由、简洁、大方不完全限制程序员的行为 |
| 所以我们很多时候在类中象征性的用一个下划线开头来取名 意思也是封装的含义 |
| class MyClass: |
| _name = 'jason' |
| def _study(self): |
| pass |
| 在类中看到下划线开头的变量名等同于两个下划线开头 |
| 意思都是不想让你直接访问 |
| """ |
| 总结:封装的目的不是隐藏 而是对外提供访问隐藏数据的接口 |
| 在该接口内就可以自定义额外的功能 |
| |
property伪装
| property就是将方法伪装成数据 |
| |
| """ |
| 扩展: |
| 体质指数(BMI)=体重(kg)÷身高^2(m) |
| """ |
| |
| 有时候很多数据需要经过计算才可以获得 |
| 但是这些数据给我们的感觉应该属于数据而不是功能 |
| BMI指数>>>:应该属于人的数据而不是人的功能 |
| class Person(object): |
| def __init__(self, name, height, weight): |
| self.__name = name |
| self.height = height |
| self.weight = weight |
| @property |
| def BMI(self): |
| return '%s的BMI指数是:%s' % (self.__name, self.weight / (self.height ** 2)) |
| |
| man1 = Person('Tom',1.80,65) |
| print(man1.BMI) |
面向对象三大特征之多态
| ''' |
| 多态:一种事物的多种形态 |
| eg: |
| 水 固态 >> 液态 >> 气态 |
| 昆虫 虫卵 >> 幼虫 >> 成虫 |
| ''' |
| |
| """ |
| 面向对象的多态性其实在很早之前就已经接触过了 |
| len方法也符合多态 |
| s1 = 'hello world' |
| s2 = 'how are you' |
| print(len(s1)) |
| print(len(s2)) |
| """ |
| |
| '''多态的使用 子类在调用时都会调用同一相同的方法 更便于管理''' |
| |
| class Animal(object): |
| def speak(self): |
| pass |
| |
| class Cat(Animal): |
| def speak(self): |
| print('喵喵喵') |
| |
| class Dog(Animal): |
| def speak(self): |
| print('汪汪汪') |
| |
| class Pig(Animal): |
| def speak(self): |
| print('哼哼哼') |
| |
| c1 = Cat() |
| c1.speak() |
| d1 = Dog() |
| d1.speak() |
| p1 = Pig() |
| p1.speak() |
| """ |
| 上述场景下 虽然体现了事物的多态性 但是并没有完整的体现出来 |
| 因为现在不同的形态去叫 需要调用不同的方法 不够一致 |
| |
| 只要你是动物 那么你想要说话 就应该调用一个相同的方法 这样便于管理 |
| """ |
| |
| """ |
| 多态性的好处在于增强了程序的灵活性和可扩展性,比如通过继承Animal类创建了一个新的类,实例化得到的对象obj,可以使用相同的方式使用obj.speak() |
| |
| 面向对象的多态性也需要python程序员自己去遵守 |
| 虽然python推崇的是自由 但是也提供了强制性的措施来实现多态性 |
| 不推荐使用 |
| """ |
| |
| |
| import abc |
| |
| class Animal(metaclass=abc.ABCMeta): |
| @abc.abstractmethod |
| def talk(self): |
| pass |
| class Person(Animal): |
| def talk(self): |
| print('啊啊啊!!!') |
| |
| p1=Person() |
| p1.talk() |
| |
| """ |
| 由多态性衍生出一个鸭子类型理论 |
| 只要你看着像鸭子 走路像鸭子 说话像鸭子 那么你就是鸭子!!! |
| """ |
| |
| """ |
| 在linux系统中有一句话>>>:一切皆文件!!! |
| 内存可以存取数据 |
| 硬盘可以存取数据 |
| ... |
| 那么多有人都是文件 |
| """ |
| class Memory(object): |
| def read(self): |
| pass |
| def write(self): |
| pass |
| class Disk(object): |
| def read(self): |
| pass |
| def write(self): |
| pass |
| |
面向对象之反射
| |
| 专业解释:指程序可以访问、检测和修改本身状态或者行为的一种能力 |
| 大白话:其实就是通过字符串来操作对象的数据和功能 |
| |
| |
| hasattr():判断对象是否含有字符串对应的数据或者功能 |
| getattr():根据字符串获取对应的变量名或者函数名 |
| setattr():根据字符串给对象设置键值对(名称空间中的名字) |
| delattr():根据字符串删除对象对应的键值对(名称空间中的名字) |
| |
| |
| class Student(object): |
| school = '清华大学' |
| def get(self): |
| pass |
| |
| '''字符串的school 跟 变量名school差距大不大? 本质区别''' |
| ''' |
| 用户输入之后的是字符串 |
| 将字符串 >>> 变量名 |
| 如不用不使用反射不太容易实现 |
| ''' |
| print(hasattr(Student, 'school')) |
| print(hasattr(Student, 'get')) |
| print(hasattr(Student, 'post')) |
| |
| guess_name = input('请输入你想要查找的名字>>>:').strip() |
| if hasattr(Student, guess_name): |
| target_name = getattr(Student, guess_name) |
| if callable(target_name): |
| print('类中有一个功能名字是%s'%guess_name,target_name) |
| else: |
| print('类中有一个数据名字是%s'%guess_name,target_name) |
| else: |
| print('类中没有该名字') |
| |
| setattr(Student,'level','贵族学校') |
| print(Student.__dict__) |
| |
| def index(): |
| hobby='啪啪啪' |
| return hobby |
| |
| stu1 = Student() |
| setattr(stu1, '智商', 10000) |
| setattr(stu1, '爱好', index()) |
| print(stu1.__dict__) |
| delattr(stu1, '爱好') |
| print(stu1.__dict__) |
| """ |
| 什么时候使用反射 可以记固定的口诀 |
| 以后只要在业务中看到关键字 |
| 对象 和 字符串(用户输入、自定义、指定) 那么肯定用反射 |
| """ |
| |
反射的实际案例
| |
| """一切皆对象 文件也是对象""" |
| |
| |
| NAME = 'NAME' |
| |
| |
| import setting |
| |
| print(dir(setting)) |
| print(getattr(setting, 'NAME')) |
| |
| |
| class FtpServer: |
| def serve_forever(self): |
| while True: |
| inp = input('input your cmd>>: ').strip() |
| cmd, file = inp.split() |
| if hasattr(self, cmd): |
| func = getattr(self, cmd) |
| func(file) |
| |
| def get(self, file): |
| print('Downloading %s...' % file) |
| |
| def put(self, file): |
| print('Uploading %s...' % file) |
| |
| |
| obj = FtpServer() |
| obj.serve_forever() |

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)