py 学习之另外两大特性封装和多态以及反射的内容 day 28
2022/4/8 23:25:28
本文主要是介绍py 学习之另外两大特性封装和多态以及反射的内容 day 28,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
今日学习内容
- 继承下的派生实际应用
- 面向对象三大特性之封装
- 面向对象三大特性之多态
- 反射
- 双下方法
继承下的派生实际应用
在学习的时候讲到这样的一个例子,还用到了之前学的时间模块内容 import datetime import json class MyJsonEncoder(json.JSONEncoder): def default(self, o): # 这个形参o是即将要被序列化的数据对象 '将o处理成json可以序列化的类型' if isinstance(o.datetime.datetime): return o.strftime('%Y-%m-%d %X') elif isinstance(o, datetime.date): return o.strftime('%Y-%m-%d') return super().default(o) # 这里就是调用父类的default d1 = {'t1': datetime.datetime.today(), 't2': datetime.date.today()} res = json.dumps(d1, cls = MyJsonEncoder) print(res) # {"t1": "2022-04-08 21:12:00", "t2": "2022-04-08"} 上述操作重写了default ''' 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 = '清华大学' def __init__(self, name, age): self.__name = name self.__age = age # 专门开设一个访问学生数据的通道(接口) def check_info(self): print(""" 学生姓名:%s 学生年龄:%s """ % (self.__name, self.__age)) # 专门开设一个修改学生数据的通道(接口) def set_info(self,name,age): if len(name) == 0: print('用户名不能为空') return if not isinstance(age,int): print('年龄必须是数字') return self.__name = name self.__age = age stu1 = Student('jason', 18) stu1.check_info() stu1.set_info('jasonNB',28) stu1.check_info() stu1.set_info('','haha')
特性(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): # print('%s的BMI指数是:%s' % (self.name, self.weight / (self.height ** 2))) return '%s的BMI指数是:%s' % (self.__name, self.weight / (self.height ** 2)) # p1 = Person('jason', 1.83, 77) # # p1.BMI() # 22.9 # # print(p1.BMI) # p2 = Person('eason',1.90,85) # # p2.BMI() # 23.5 # # print(p2.BMI) # p3 = Person('xd',1.85,100) # # p3.BMI() # 29.2 # print(p3.BMI) # p4 = Person('xd',1.5,34) # # p4.BMI() # 15.1 # print(p4.BMI)
多态
# 概念 多态:指事物的多种形态 计算机中多态:一个抽象类有多个子类,进行不同的实现,多态依赖于继承 简意:不同的对象调用相同的方法,产生不同的行为 # 例子 s1 = 'abc' w1 = [1, 2, 3, 4, 5] s1.__len__() w1.__len__() len(s1) len(w1) print(len(s1)) # 3 print(len(w1)) # 5 s1是字符串类型,w1是列表,两个完全不同的对象,他们都可以调用len方法,而得出的结果不同
如何使用多态
多态在python中,即子类对象调用父类相同的方法时,产生各自的结果 多态依赖于继承,可以用接口继承或者重写父类来实现 # 例子 class H20: def __init__(self,name,temerature): self.name = name self.temerature = temerature def turn_ice(self): if self.temerature < 0: print("[%s]温度太低结冰了"%self.name) elif self.temerature > 0 and self.temerature < 100: print("[%s]液化成水" % self.name) elif self.temerature > 100: print("[%s]温度太高变成水蒸气" % self.name) class Water(H20): pass class Ice(H20): pass class Steam(H20): pass w1 = Water("水",25) i1 = Ice("冰",-20) s1 = Steam("水蒸气",3000) #执行过程中不同的对象调用相同的方法 w1.turn_ice() # [水]液化成水 i1.turn_ice() # [冰]温度太低结冰了 s1.turn_ice() # [水蒸气]温度太高变成水蒸气 #或者定义一个接口来执行上面的调用 def func(obj): obj.turn_ice() func(w1) # [水]液化成水 func(i1) # [冰]温度太低结冰了 func(s1) # [水蒸气]温度太高变成水蒸气 '接口类Animal' import abc # 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化 class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法 def talk(self): # 抽象方法中无需实现具体的功能 pass class Person(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准 def talk(self): pass p1 = Person() # 若子类中没有一个名为talk的方法则会抛出异常TypeError,无法实例化
反射
# 什么是反射 概念:指程序可以访问、检测和修改本身状态或者行为的一种能力 大白话:其实就是通过字符串来操作对象的数据和功能 # 需掌握的四个方法 hasattr():判断对象是否含有字符串对应的数据或者功能 getattr():根据字符串获取对应的变量名或者函数名 setattr():根据字符串给对象设置键值对(名称空间中的名字) delattr():根据字符串删除对象对应的键值对(名称空间中的名字) # 就是以上四种方法在例子中的使用 class Student(object): school = '清华大学' def get(self): print('得到了一个篮球') # 编写一个小程序 判断Student名称空间中是否含有用户指定的名字 如果有则取出展示 print(Student.__dict__) guess_name = input('请输入你想要查找的名字>>>:').strip() # 不使用反射不太容易实现 print(hasattr(Student, 'school')) # True print(hasattr(Student, 'get')) # True print(hasattr(Student, 'post')) # False # print(getattr(Student, 'school')) # 清华大学 print(getattr(Student, 'get')) # <function Student.get at 0x10527a8c8> while True: 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(): pass obj = Student() setattr(obj, '血量', 10000) setattr(obj, '功能', index) print(obj.__dict__) delattr(obj, '功能') print(obj.__dict__) '就是看到关键词对象和字符串(用户输入、自定义、指定)就是用反射'
反射实例
# 利用反射获取配置文件中的配置信息 """一切皆对象 文件也是对象""" import settings dir(settings) # 获取对象中所有可以使用的名字 getattr(settings, 'NAME') class FtpServer: def serve_forever(self): while True: inp=input('input your cmd>>: ').strip() cmd,file=inp.split() if hasattr(self,cmd): # 根据用户输入的cmd,判断对象self有无对应的方法属性 func=getattr(self,cmd) # 根据字符串cmd,获取对象self对应的方法属性 func(file) def get(self,file): print('Downloading %s...' %file) def put(self,file): print('Uploading %s...' %file) obj = FtpServer() obj.serve_forever()
今天的学习内容到此结束,接下来去复习前面的知识点了
这篇关于py 学习之另外两大特性封装和多态以及反射的内容 day 28的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-20测试人员都是画画大神,让我看看谁还不会用代码图?
- 2024-05-20年薪百万的程序员都在用的摸鱼方式……
- 2024-05-19永别了,微服务架构!
- 2024-05-15鸿蒙生态设备数量超8亿台
- 2024-05-13TiDB + ES:转转业财系统亿级数据存储优化实践
- 2024-05-09“2024鸿蒙零基础快速实战-仿抖音App开发(ArkTS版)”实战课程已上线
- 2024-05-09聊聊如何通过arthas-tunnel-server来远程管理所有需要arthas监控的应用
- 2024-05-09log4j2这么配就对了
- 2024-05-09nginx修改Content-Type
- 2024-05-09Redis多数据源,看这篇就够了