内容概要
- 派生方法实战
- 面向对象三大特性之封装
- 三大特性之多态
- 面向对象之反射
- 反射实战案例
- 练习题
派生方法实战
派生方法实战案例:
import json
import datetime
# time_dict = {'t1': datetime.datetime.today(),
# 't2': datetime.date.today()}
#
# res = json.dumps(time_dict) # 序列化字典
# print(res) # 结果报错,是因为字典内的日期类型不支持序列化
# '''raise TypeError(f'Object of type {o.__class__.__name__} '
# TypeError: Object of type datetime is not JSON serializable'''
# 我们就可以通过派生方法将上述字典转换成序列化,我们先看一下简单的
# time_dict = {'t1': str(datetime.datetime.today()),
# 't2': str(datetime.date.today())} # 我们可以通过将日期类型转换为 字符串
# res = json.dumps(time_dict) # 序列化字典
# print(res) # 这样就可以得到最后序列化日期类型的结果
# # {"t1": "2022-11-07 14:47:27.634664", "t2": "2022-11-07"}
# 我们在看一下派生方法是怎么做到的
class My_JSONEncoder(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')
else:
return super().default(o)
time_dict = {'t1': datetime.datetime.today(),
't2': datetime.date.today()}
res = json.dumps(time_dict, cls=My_JSONEncoder)
print(res)
# {"t1": "2022-11-07 14:55:46", "t2": "2022-11-07"} 也成功的序列化了这个日期类型
# 我们使用这个派生方法就相当于改写了 json.JSONEcoder 里面的 default 方法
# 所以我们就可以通过改写方法来让我们序列化的字典不报错
面向对象之封装
封装:
将数据与功能封装起来
class MyClass:
school_name = '清华大学'
_ = 'a'
_name = 'Nicki_Minaj'
__hobby = 'study'
'''类在定义阶段 名字前面有两个下划线,那么它就会被隐藏起来,我们不能通过对象.的方式访问此数据值'''
def __choice_num(self):
pass
obj = MyClass()
print(obj.school_name) # 清华大学
# print(obj.__hobby) # 'MyClass' object has no attribute '__hobby'
# 虽然我们使用__hobby 不可以通过对象.的方式访问
# 我们看一下对象的名称空间
print(MyClass.__dict__) # '_MyClass__hobby': 'study'
# 还是有__hobby 这个名字的
# 所以我们想访问的话就可以通过点的方式
print(MyClass._MyClass__hobby) # study
# 但是我们这样虽然访问到了这个隐藏的属性,但是就失去了我们使用封装特性的目的了
隐藏:
将数据和功能隐藏起来不让用户直接调用 而是开发一些接口间接调用,从而可以在接口内添加额外的操作
class Person:
def __init__(self,name,gender):
self.__name = name
self.__gender = gender
def walk(self):
print(f'{self.__name} 会走路')
def set_person(self,new_name):
if len(new_name) == 0:
raise ValueError('用户名长度不能为0')
if new_name == '1':
raise ValueError('用户名中不能些数字')
self.__name = new_name
'''我们封装是可以在类的定义阶段使用的'''
'''但是我们在类外就不可以进行对封装的属性修改或增加的操作了'''
# 隐藏的属性开放修改的接口 我们可以自定义很多功能
# 所以隐藏属性后,我们可以暴露给用户一些接口,让用户校验后才可以对属性进行修改
伪装:
将类里面的方法伪装成类利的数据 @property
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) # 利用装饰器伪装成数据
面向对象之多态
多态就代表着事物的多种形态
比如 水 :
有固态 气态 液态
# 面向对象中多态意思是 一种事物可以有多种形态但是针对相同的功能应该定义相同的方法
# 这样无论我们拿到的是哪个具体的事物 都可以通过相同的方法调用功能
鸭子类型
# 鸭子类型:只要你看上去像鸭子 走路像鸭子 说话像鸭子 那么你就是鸭子
'''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,无法实例化
面向对象之反射
反射:
在 python中 反射就是利用字符串去操纵对象的数据和方法
hasattr() # 判断对象中是否含有某个字符串对应的属性名或方法名 返回布尔值
getattr() # 根据字符串获取对象中的属性名或方法名,如果没有就会报错
所以 getattr 方法一般 搭配 hasattr() 方法一起使用
setattr() # 根据字符串给对象设置或修改数据
delattr() # 根据字符串删除对象里面的名字
class F1:
def __init__(self,name,age):
self.name = name
self.name = name
def talk(self):
print(f'{self.name} 正在说话~')
obj = F1('kevin',123)
while True:
func = input('请输入您想要执行的功能>>>:')
if hasattr(obj,func):
res = getattr(obj,func)
res()
break
else:
print('没这个功能')
# 我们再来看看反射的实战案例
class WinCmd:
def tasklist(self):
print('''
tasklist功能正在运行
''')
def ipconfig(self):
print('''
ip地址正在打印
''')
def server_run(self):
print('欢迎进入简易版本cmd终端')
while True:
target_cmd = input('请输入您的指令>>>:')
res = target_cmd
if len(res) <= 1:
if hasattr(self, res[0]):
getattr(self, res[0])()
else:
print(f'{res[0]}不是内部或者外部命令')
else:
print('没有这个功能~')
obj = WinCmd()
obj.server_run()
一切皆对象
# 利用反射保留某个py文件中所有的大写变量名及对应的数据值
import settings # 导入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('该模块文件中没有该名字')
标签:__,封装,name,self,多态,datetime,面向对象,print,def
From: https://www.cnblogs.com/ddsuifeng/p/16866985.html