面向对象
继承下派生的使用
import json
import datetime
class MyJsonEncode(json.JSONEncoder):
def default(self, o):
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)
a = {'b': datetime.datetime.now()}
res = json.dumps(a, cls=MyJsonEncode)
print(res)
'''
TypeError: Object of type 'datetime' is not JSON serializable
json 不能序列化python中所有的数据类型 只能试一下基本数据类型 例如 datetime.datetime类型的数据
解决方法:
1.手动将不能序列化的类型先转换称字符串
str(datetime.datetime.now())
2.研究json源码并重写序列化方法
研究源码发现报错的方法叫default
raise TypeError("Object of type '%s' is not JSON serializable" % o.__class__.__name__)
我们可以重写一个类继承JSONEncoder然后重写default方法
'''
面向对象三大特性之封装
# 封装的含义
将类中某些名字隐藏起来,不让外界直接调用
隐藏的目的是为了提供专门的通道去访问 在通道内可以额外添加功能
# 代码实操
class Student:
def __init__(self, name, age):
self.__name = name
self.__age = 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
# 设置一个通道 查看学生数据
def check_info(self):
print(f"学生的姓名是{self.__name}")
print(f"学生的年龄是{self.__age}")
stu1 = Student('tom', 20)
# print(stu1.name) # AttributeError: 'Student' object has no attribute 'name'
print(stu1.__dict__) # {{'_Student__name': 'tom', '_Student__age': 20}
stu1.name = 'tom'
print(stu1.__dict__) # {'_Student__name': 'tom', '_Student__age': 20, 'name': 'tom'}
stu1.check_info() # 学生的姓名是tom 学生的年龄是20
stu1.set_info('jason',28)
stu1.check_info() # 学生的姓名是jason 学生的年龄是28
'''
将数据隐藏起来就是限制了类外部对数据的直接操作,然后类内应该提供相应的接口来运行外部间接的操作数据
接口之上可以附加额外的逻辑来对数据的操作进行严格的控制
目的是为了隔离复杂度,例如ATM程序的提款功能,应该有很多其他功能组成
比如插卡,身份认证,输入金额,打印小票,取钱等,而对使用之来说只需要开发取款这个功能接口即可,其余功能我们都可以隐藏起来
'''
property
property就是将方法伪装成数据
'''
eg:
体质指数(BMI)=体重(kg)÷身高^2(m)
'''
有时候我们很多数据需要经过计算才可以获得,但是这些数据给我们的感觉属于是数据,而不是功能
class Person:
def __init__(self, name, heiget, weight):
self.__weight = weight
self.__heiget = heiget
self.__name = name
@property
def BMI(self):
BMIis = self.__weight / self.__heiget ** 2
return BMIis
p1 = Person('jason',1.83,60)
print(p1.BMI) # 17.916330735465376
面向对象三大特征之多态
# 什么是多态
一种事物的多种形态
eg:
动物 猫、狗、猪
蔬菜 番茄、白菜、西兰花
# 多态性
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('哼哼哼')
'''只要是动物,那么就会交流,就应该调用一个相同的方法,而不是同一个功能,在不同的类里面是不同的名字。这样便于管理'''
# 面向对象的多态性,很早之前我们就接触过
s1 = 'hello world'
l1 = [1,2,3,3]
print(len(s1))
print(len(l1))
'''
多态性的好处在于增强了程序的灵活性和可扩展性,你让通过继承animal类创建一个新类,实例化得到一个对象object,可以使用形同的方法使用object.speak()
面向对象的多态性也需要python程序员自己去遵守,但是python也提供了强制性措施来是想多态性但是不推荐使用
'''
import abc
# 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
def talk(self):
pass # 抽象方法中无需实现具体的功能
class Cat(Animal): # 只要是继承了Anima的类,就必须遵循Ani规定的标准
def talk(self):
pass # 遵守Animal的规定,定义一个talk方法
c1 = Cat() # 若Cat类中没有talk方法,就会抛出异常,无法实例化
'''
由多态衍生出一个鸭子类理论
只要你看着像鸭子、说话像鸭子、走路像鸭子,那么你就是鸭子
'''
# 鸭子类型举例
'''
在Linux只给你有 一切皆文件的说法
内存可以存储数据
硬盘可以存取数据
那么就都是文件
'''
class Memory(object):
def read(self):
pass
def write(self):
pass
class Disk(object):
def read(self):
pass
def write(self):
pass
# 得到内存或者硬盘对象之后 只要想读取数据就调用read 想写入数据就调用write 不需要考虑具体的对象是谁
面向对象之反射
# 什么是反射
专业解释:指程序可以访问、检查和修改本身状态或者行为的一种能力
大白话:其实就是通过字符串来操作对象的数据和功能
# 反射需要掌握的四个方法
hasattr();判断对象是否含义字符串对应的数据或者功能
getattr():根据字符串获取对应的变量名或者函数名
setattr():根据字符串设置对应的键值对(名称空间中的名字)
delattr():根据字符串删除对象对应的键值对(名称空间中的名字)
# 反射的实际应用
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def get(self):
pass
stu1 = Student('jason',23)
print(hasattr(stu1, 'name')) # True
delattr(stu1,'name')
print(hasattr(stu1, 'name')) # False
print(hasattr(Student,'__init__')) # True
print(getattr(stu1, 'name')) # jason
print(getattr(Student,'__init__')) # <function Student.__init__ at 0x0000022F76C2EEE8>
setattr(stu1,'name','tom')
print(stu1.name) # tom
反射实际案例
# 利用反射获取配置文件中的配置信息
'''一切皆对象,文件也是对象'''
import settings
dir(settings) # 获取对象中所有可以使用的名字
choice = input('请输入您想要获取的名字:')
getattr(settings, choice)
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()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人