面向对象3
2022/7/28 23:28:33
本文主要是介绍面向对象3,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一、派生方法实战演练(重要)
import datetime import json d = { 't1': datetime.datetime.today(), 't2': datetime.date.today() } res = json.dumps(d) print(res)
上述代码报错,无法正常序列化,这是因为json序列化python数据类型是有限制的,不是所有类型都可以
即将被序列化的数据,内外都必须是一下类型才可以
python | json |
---|---|
dict | object |
list,tuple | arrary |
str | string |
int,float | number |
bool | True/False |
None | null |
1.解决方式一:手动将不符合数据类型要求的数据转成符合要求的
import datetime import json d = { 't1': str(datetime.datetime.today()), 't2': str(datetime.date.today()) } res = json.dumps(d) print(res) # {"t1": "2022-07-28 15:00:15.153789", "t2": "2022-07-28"}
2.解决方式二:派生方法
class JSONEncoder: pass dumps(obj,cls=None): if cls == None: cls = JSONEncoder return cls(...) # JSONEncoder()
查看JSONEncoder源码发现序列化报错是由default方法触发的
我们如果想要避免报错 那么肯定需要对default方法做修改(派生)
import datetime import json d = { 't1': datetime.datetime.today(), 't2': datetime.date.today() # {"t1": "2022-07-28 15:10:25", "t2": "2022-07-28"} } 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) res = json.dumps(d, cls=MyJsonEncode) print(res) # {"t1": "2022-07-28 15:10:25", "t2": "2022-07-28"}
二、面向对象的三大特性之封装
1.简介
封装:将数据或者功能隐藏起来(包起来,装起来)
隐藏的目的:给这些隐藏的数据开设特定的接口,让用户使用接口才可以去使用,我们在接口中添加一些额外的操作
在类定义阶段使用双下划线开头的名字都是隐藏的属性,后续类和对象都无法直接获取
在python中不会真正的限制任何代码,隐藏的属性如果真的需要访问也可以,只不过需要做变形处理
2.代码示例
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.set_info('','我很大')
我编写python很多时候都是大家墨守成规的东西,不需要真正的限制
class A: _school = '清华大学' def _choice_course(self): pass
三、property伪装属性
1.简介
property伪装属性:将方法伪装成数据,伪装之后可以将func方法伪装成数据(obj.func)
obj.name # 数据只需要点名字 obj.func() # 方法还要加括号
2.代码示例
BMI指数是用来衡量一个人的体重与身高对健康影响的一个指标,计算公式为
体质指数(BMI)=体重(kg)÷身高^2(m)
身高或体重是不断变化的,因而每次想查看BMI值都需要通过计算才能得到,但很明显BMI听起来更像是一个特征而非功能,为此Python专门提供了一个装饰器property,可以将类中的函数“伪装成”对象的数据属性,对象在访问该特殊属性时会触发功能的执行,然后将返回值作为本次访问的结果,例如
class Person: 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) p = Person('jason', 78, 1.83) res = p.BMI() print(res)
使用property有效地保证了属性访问的一致性。另外property还提供设置和删除属性的功能,如下
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') obj = Foo('jason') # print(obj.name) # obj.name = 666 # print(obj.name) del obj.name
四、面向对象三大特性之多态
1.简介
多态:一种事物的多种形态
- 水:液态、气态、固态
- 动物:猫、狗、猪
2.代码示例
一种事物有多种形态,但是相同的功能应该有相同的名字,以后我无论拿到哪个具体的动物,都不需要管到底是谁,直接调用相同的功能即可
class Animal: # 同一类事物: 动物 def talk(self): pass class Cat(Animal): # 动物的形态之一: 猫 def talk(self): print('喵喵喵') class Dog(Animal): # 动物的形态之二: 狗 def talk(self): print('汪汪汪') class Pig(Animal): # 动物的形态之三: 猪 def talk(self): print('哼哼哼') # 实例化得到三个对象 cat = Cat() dog = Dog() pig = Pig() cat.talk() # 喵喵喵 dog.talk() # 汪汪汪 pig.talk() # 哼哼哼 def Talk(animal): animal.talk() Talk(cat) # 喵喵喵 Talk(dog) # 汪汪汪 Talk(pig) # 哼哼哼
python也提供了一种强制性的操作(了解即可),应该是自觉遵守
import abc # 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化 class Animal(metaclass=abc.ABCMeta): @abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法 def talk(self): # 抽象方法中无需实现具体的功能 pass class Person(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准 def talk(self): pass def run(self): pass obj = Person()
五、面向对象之反射(重要)
1.简介
反射:通过字符串来操作对象的数据方法
2.反射的四个主要方法
方法 | 描述 |
---|---|
hasattr() | 判断对象是否含有某个字符串对应的属性 |
getattr() | 获取对象字符串对应的属性 |
setattr() | 根据字符串给对象设置属性 |
delattr() | 根据字符串给对象删除属性 |
class Teacher: def __init__(self,full_name): self.full_name =full_name t=Teacher('jason Lin') # hasattr(object,'name') hasattr(t,'full_name') # 按字符串'full_name'判断有无属性t.full_name # getattr(object, 'name', default=None) getattr(t,'full_name',None) # 等同于t.full_name,不存在该属性则返回默认值None # setattr(x, 'y', v) setattr(t,'age',18) # 等同于t.age=18 # delattr(x, 'y') delattr(t,'age') # 等同于del t.age
3.代码示例
需求:判断用户提供的名字在不在对象可以使用的范围内
class Student: school = '清华大学' def choice_course(self): print('选课') stu = Student()
3.1.方式1:异常处理(过于繁琐)
try: if stu.school: print(f"True{stu.school}") except Exception: print("没有属性")
变量名school(stu.school)与字符串school(stu.‘school’)区别:两者虽然只差了引号,但是本质是完全是不一样的
3.2.方式2:获取用户输入的名字,判断改名字有没有对象
异常处理不好实现,我们需要使用反射
while True: target_name = input('请输入您想要核查的名字>>>:').strip() '''上面的异常更加不好实现 需要用反射''' # print(hasattr(stu, target_name)) # print(getattr(stu, target_name)) if hasattr(stu, target_name): # print(getattr(stu, target_name)) res = getattr(stu, target_name) if callable(res): print('拿到的名字是一个函数', res()) else: print('拿到的名字是一个数据', res) else: print('不好意思 您想要查找的名字 对象没有') print(stu.__dict__) stu.name = 'jason' stu.age = 18 print(stu.__dict__) setattr(stu, 'gender', 'male') setattr(stu, 'hobby', 'read') print(stu.__dict__) del stu.name print(stu.__dict__) delattr(stu, 'age') print(stu.__dict__)
3.3.总结
以后只要在需求中看到了关键字....对象....字符串,那么肯定需要使用反射
4.反射实战演练
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)
操作系统
Linux系统
linux系统:一切皆文件(只要能读数据,能写数据,那么就是文件)
class Txt: # Txt类有两个与文件类型同名的方法,即read和write def read(self): pass def write(self): pass class Disk: # Disk类也有两个与文件类型同名的方法:read和write def read(self): pass def write(self): pass class Memory: # Memory类也有两个与文件类型同名的方法:read和write def read(self): pass def write(self): pass
Python
python:一切皆对象(只要有数据,有功能,那么就是对象)
- 文件名→文件对象
- 模块名→模块对象
这篇关于面向对象3的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-03Springboot企业级开发资料入门教程
- 2025-01-03SpringBoot企业级开发资料入门教程
- 2025-01-03Springboot微服务资料入门教程
- 2025-01-03Springboot项目开发资料:新手入门教程
- 2025-01-03Springboot项目开发资料:新手入门指南
- 2025-01-03SpringCloud Alibaba资料入门教程
- 2025-01-03SpringCloud Alibaba资料详解与入门教程
- 2025-01-03SpringCloud微服务资料入门教程
- 2025-01-03单元化架构最佳实践指南!
- 2025-01-03SpringCloud项目开发资料入门教程