派生方法实战演练

import json
import datetime d = {
't1': datetime.date.today(),
't2': datetime.datetime.today(),
't3': 'jason'
}
# res = json.dumps(d)
# print(res)
"""
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type date is not JSON serializable
"""
"""
能够被序列化的数据是有限的>>>:里里外外都必须是下列左边的类型
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
| str | string |
+-------------------+---------------+
| int, float | number |
+-------------------+---------------+
| True | true |
+-------------------+---------------+
| False | false |
+-------------------+---------------+
| None | null |
+-------------------+---------------+
"""
# 1.转换方式1:手动转类型(简单粗暴)
d = {
't1': str(datetime.date.today()),
't2': str(datetime.datetime.today()),
't3': 'jason'
} # res = json.dumps(d)
# print(res) # {"t1": "2022-11-07", "t2": "2022-11-07 14:56:35.147647", "t3": "jason"}
# 2.转换方法2:派生方法(高端儒雅)
"""
查看dumps源码 注意cls参数 默认传 JSONEncoder
查看该类的源码 发现default方法是报错的发起者
编写类继承JSONEncoder并重写default方法 之后调用dumps
手动传cls= 我们自己写的类
""" class MyJsonEncoder(json.JSONEncoder):
def default(self, o):
"""
:param o: 接收无法被序列化的数据
:return: 返回可以被序列化的数据
"""
if isinstance(o,datetime.datetime): # 判断是否是datetime类型 如果是则处理成可以被序列化的类型
return o.strftime('%Y-%m-%d %X')
elif isinstance(o,datetime.date):
return o.strftime('%Y-%m-%d')
return super().default(o) # 最后还是调用原来的方法 防止有一些额外操作没有做 res = json.dumps(d,cls=MyJsonEncoder)
print(res) # {"t1": "2022-11-07", "t2": "2022-11-07 15:08:45.403976", "t3": "jason"} 总结:
1.继承某个类
2.重写被继承类里面的某个方法
3.在方法内添加一些额外的操作
4.最后利用super重新调用被继承类里面的方法
"""
super:子类调用父类的方法 一定要注意和对象查找名字的顺序区分开
"""

面向对象三大特性之封装

封装:就是将数据和功能'封装'起来
隐藏:将数据和功能隐藏起来不让用户直接调用 而是开发一些接口间接调用从而可以在接口内添加额外的操作(2.在类的定义阶段名字前面使用两个下划线开头表示隐藏)
伪装:将类里面的方法在调用时伪装成类里面的数据不用加括号
class C:
def func(self):pass
obj = C()
obj.func()
'''经过伪装'''
obj.func # class MyClass:
# shool_name = '老男孩大学'
# _ = '嘿嘿嘿'
# _name = 'tony'
# '''类在定义阶段 名字前面有两个下划线 那么该名字会被隐藏起来 无法直接访问'''
# __age = 18
# """ 在python中其实没有真正意义上的隐藏 仅仅是换个名字而已 _类名__名字"""
# def __choice_course(self):
# print('老北鼻正在选课!!!') # print(MyClass.shool_name) # 老男孩大学
# obj = MyClass
# print(obj.shool_name) # 老男孩大学
# print(MyClass._) # 嘿嘿嘿
# print(MyClass._name) # tony
# MyClass.__hobby = 'JDB' # 定义阶段之外的 无法隐藏
# print(MyClass.__hobby)
# obj = MyClass()
# obj.__addr = '派出所'
# print(obj.__addr)
# print(MyClass.__dict__)
# print(MyClass._MyClass__age) # 18 class Person:
def __init__(self,name,age,hobby):
self.name__name = name # 对象也可以拥有隐藏的属性
self.__age = age
self.__hobby = hobby def get_info(self):
# 类体代码中 是可以直接使用隐藏的名字
print(f"""
姓名:{self.__name}
年龄:{self.__age}
爱好:{self.__hobby}
""")
# 隐藏的属性开发修改的接口 可以自定义很多功能
def set_name(self,new_name):
if len(new_name) == 0:
raise ValueError('你好歹写点东西')
if new_name.isdigit():
raise ValueError('名字不能是数字')
self.__name = new_name obj = Person('json',18,'read')
obj.get_info()
# obj.set_name('tony老师')
# obj.get_info()
obj.set_name('') """
以后我们在编写面向对象代码类的定义时 也会看到很多但下划线开头的名字
表达的意思通常也是不要直接访问 而是查找一下下面可能定义的接口
"""
class ATM:
def __card(self): # 插卡
print('插卡') def __auth(self): # 身份认证
print('用户认证') def __input(self): # 输入金额
print('输入取款金额') def __print_bill(self): # 打印小票
print('打印账单') def __take_money(self): # 取钱
print('取款') def withdraw(self): # 取款功能
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money() obj = ATM()
obj.withdraw() """输出信息为隐藏信息"""

伪装

BMI指数:衡量一个人的体重与身高对健康影响的一个指标
体质指数(BMI) = 体重(kg)÷身高^2(m)
EX: 70kg÷(1.75×1.75)=22.86 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) # 利用装饰器伪装成数据 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') f = Foo('jason')
print(f.name)
f.name = 'jason123'
print(f.name)
del f.name
# f.name = 'jason' # 触发name.setter装饰器对应的函数name(f,’jason')
# f.name = 123 # 触发name.setter对应的的函数name(f,123),抛出异常TypeError
# del f.name # 触发name.deleter对应的函数name(f),抛出异常PermissionError

三大特性之多态

多态:一种事物的多种形态
水:液态 固态 气态
动物:人 猪 猫 狗
1.多个类如果有相似之处 那么里面针对相似的功能应该起相同的名字
# class Animal:
# def spark(self):
# '''叫的方法'''
# pass
#
#
# class Cat(Animal):
# # def miao(self):
# # print('喵喵喵')
# def spark(self):
# print('喵喵喵')
#
#
# class Dog(Animal):
# # def wang(self):
# # print('汪汪汪')
# def spark(self):
# print('汪汪汪')
#
#
# class Pig(Animal):
# # def heng(self):
# # print('哼哼哼')
# def spark(self):
# print('哼哼哼') """
面向对象中多态意思是 一种事物可以有多种形态但是针对相同的功能应该定义相同的方法
这样无论我们拿到的是哪个具体的事物 都可以通过相同的方法调用功能
""" # s1 = 'hello world'
# l1 = [11, 22, 33, 44]
# d = {'name': 'jason', 'pwd': 123}
# print(s1.__len__())
# print(l1.__len__())
# print(d.__len__()) """
鸭子类型: 只要你看上去想鸭子 走路像鸭子 说话像鸭子 那么你就是鸭子
""" # linux系统
"""
文件 能够读取数据也能够保存数据
内存 能够读取数据也能够保存数据
硬盘 能够读取数据也能够保存数据
......
一切皆文件
""" class File:
def read(self): pass def write(self): pass class Memory:
def read(self): pass def write(self): pass class Disk:
def read(self): pass def write(self): pass '''python永远提倡自由简介大方 不约束程序员行为 但是多态提供了约束的方法''' 2.强制规定子类编写父类中相同的方法(不是为了派生)
abc模块 import abc # 指定metaclass属性将类设置为抽象类,抽象类本身只是用来约束子类的,不能被实例化
class Animal(metaclass=abc.ABCMeta):
@abc.abstractmethod # 该装饰器限制子类必须定义有一个名为talk的方法
def talk(self): # 抽象方法中无需实现具体的功能
pass # class Cat(Animal): # 但凡继承Animal的子类都必须遵循Animal规定的标准
pass # cat = Cat() # 若子类中没有一个名为talk的方法则会抛出 异常TypeError,无法实例化

面向对象之反射

利用字符串操作对象的数据方法
1.hasattr() 重点
判断对象是否含有某个字符串对应得属性名或者方法名
2.getattr() 重点
根据字符串获取对象对应的属性名(值)或方法名(函数体代码)
3.setattr()
根据字符串给对象设置或者修改数据
4.delattr()
根据字符串删除对象里面的名字 # class C1:
# school_name = '小姐姐学院'
#
# def choice_course(self):
# print('小姐姐正在选课')
#
# obj = C1()
'''判断某个名字对象是否可以使用(存在)'''
# 推导思路 # try:
# obj.xxx
# except AttributeError:
# print('你没有这个名字') '''判断用户随意指定的名字对象是否可以使用(存在)'''
# target_name = input('请输入对象可能使用的名字>>>:').strip()
# try:
# obj.target_name
# except AttributeError:
# print('你没有这个名字')
"""
字符串的名字 跟变量名区别大不大
’school_name‘
school_name
非常大 完全不一样
""" # 反射:利用字符串操作对象的数据和方法
# print(hasattr(obj,'school_name')) # True
# print(getattr(obj,'school_name')) # 小姐姐学院
# print(getattr(obj,'choice_course')) # <bound method C1.choice_course of <__main__.C1 object at 0x000001AF23705B80>> class C1:
school_name = '小姐姐学院' def choice_course(self):
print('小姐姐正在选课') obj = C1()
while True:
target_name = input('请输入您想要操作的名字>>>>')
if hasattr(obj, target_name):
print('恭喜您, 系统中有该名字')
# 获取该名字对应的数据(值 函数)
data_or_func = getattr(obj, target_name)
if callable(data_or_func):
print('您本次使用的是系统中的某个方法')
data_or_func()
else:
print('您本次使用的是系统中的某个数据')
print(data_or_func)
else:
print('很抱歉 系统中没有该名字')
ps:反射从另外一个角度看 能够将面向对象的代码与用户交互起来

反射实战案例

1.什么时候应该考虑使用反射  只要需求中出现了关键字
对象....字符串....
2.实战案例 1.模拟cmd终端
class WinCmd:
def tasklist(self):
print("""
1.学习编程
2.学习python
3.学习英语
""")
def ipconfig(self):
print("""
地址:127.0.0.1
地址:上海浦东新区
""")
def get(self,target_file):
print('获取指定文件',target_file)
def put(self,target_file):
print('上传指定文件',target_file)
def server_run(self):
print('欢迎进入简易版本cmd终端')
while True:
target_cmd = input('请输入您的指令>>>:')
res = target_cmd.split(' ')
if len(res) == 1:
if hasattr(self,res[0]):
getattr(self,res[0])()
else:
print(f'{res[0]}不是内部或者外部命令')
elif len(res) == 2:
if hasattr(self,res[0]):
getattr(self,res[0])(res[1])
else:print(f'{res[0]}不是内部或者外部命令') obj = WinCmd()
obj.server_run() 2.一切皆对象 # 利用反射保留某个py文件中所有的大写变量名及对应的数据值
import 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('该模块文件中没有该名字')

python之路25 面向对象 封装(隐藏、伪装)、多态、反射的更多相关文章

  1. (转)Python之路,Day6 - 面向对象学习

    本节内容:   面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法.     引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战> ...

  2. python基础(25):面向对象三大特性二(多态、封装)

    1. 多态 1.1 什么是多态 多态指的是一类事物有多种形态. 动物有多种形态:人,狗,猪. import abc class Animal(metaclass=abc.ABCMeta): #同一类事 ...

  3. python之路——25

    复习 1.继承 表示什么是什么的关系 1.单继承 1.先抽象,再继承 2.子类没有的名字,调用父类 3.类中使用self,看清楚self指向谁 2.多继承 1.新式类和经典类 1.新式类:广度优先 经 ...

  4. Python之路,Day6 - 面向对象学习

    本节内容:   面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法. 引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战>的游戏 ...

  5. 转:Python之路,Day6 - 面向对象学习

    这篇文章写的不错,转来收了 转自:http://www.cnblogs.com/alex3714/articles/5188179.html   本节内容:   面向对象编程介绍 为什么要用面向对象进 ...

  6. 十一Python之路,Day6 - 面向对象学习

      本节内容:   面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法.     引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战& ...

  7. Python之路: 面向对象

    Python是一门面向对象的语言,所以在Python中创建一个类和对象是很容易的.接下来了解一下面像对象的一些基本特征. 面向对象技术简介 类(class):描述具有相同的属性和方法的对象的集合.定义 ...

  8. python之路--初识面向对象

    一 . 初识面向对象 面向过程: 一切以事务的发展流程为中心. 面向对象: 一切以对象为中心. 一切皆为对象. 具体的某一个事务就是对象 打比方: 大象进冰箱 步骤: 第一步, 开门, 第二步, 装大 ...

  9. python之路----初识面向对象(二)

    类命名空间与对象.实例的命名空间 创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性 而类有两种属性:静态属性和动态属性 静态属性就是直接在类中定义的变量 动态属性就 ...

  10. Python之路:面向对象及相关

    其他相关 一.isinstance(obj, cls) 检查是否obj是否是类 cls 的对象 class Foo(object):     pass   obj = Foo()   isinstan ...

随机推荐

  1. day47-JDBC和连接池03

    JDBC和连接池03 8.事务 8.1事务介绍 基本介绍 JDBC程序中当一个Connection对象创建时,默认情况下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而 ...

  2. Application保存作用域

    Application保存作用域,作用范围:一次应用程序范围有效.Application属性范围值,只要设置一次,则所有的网页窗口都可以取得数据. ServletContext在服务器启动时创建,在服 ...

  3. Laravel-Easy-Admin 快速搭建数据后台 web管理后台

    基于PHP + Laravel + element-admin-ui 搭建的快速数据后台,只在解决系列后台增删改查等日常操作.快速搭建,在生成业务的同时可以花更多的时间关注技术本身,提高程序员自身进阶 ...

  4. 小程序返回上一级页面背景音乐报错 setBackgroundAudioState:fail title is nil!;

    小程序初始化在onLoad的时候加载了一次背景音乐. 如果此时报错是title必传.如果没有 会报错一次 setBackgroundAudioState:fail title is nil!; 这个都 ...

  5. C语言------选择结构

    仅供借鉴.仅供借鉴.仅供借鉴(整理了一下大一C语言每个章节的练习题.没得题目.只有程序了) 文章目录 1 .实训名称 2 .实训目的及要求 3 .源代码及运行截图 4.小结 1 .实训名称 实训4:选 ...

  6. 十八、Service的应用

    Service 的应用 ClusterIP ​clusterIP 主要在每个 node 节点使用 ipvs,将发向 clusterIP 对应端口的数据,转发到 kube-proxy 中.然后 kube ...

  7. 二叉搜索树 - C++ 实现

    二叉搜索树 - C++ 实现 概述 Overview 二叉查找树(英语:Binary Search Tree, 后文中简称 BST), 也称为二叉搜索树.有序二叉树(ordered binary tr ...

  8. elasticsearch聚合之bucket terms聚合

    目录 1. 背景 2. 前置条件 2.1 创建索引 2.2 准备数据 3. 各种聚合 3.1 统计人数最多的2个省 3.1.1 dsl 3.1.2 运行结果 3.2 统计人数最少的2个省 3.2.1 ...

  9. C#使用最小二乘法对多个离散点进行圆拟合

    /// <summary> /// 最小二乘法拟合圆,计算拟合圆半径和拟合圆圆心 /// </summary> /// <param name="points& ...

  10. nacos集群搭建和反向代理

    搭建环境 安装ngin https://www.linuxprobe.com/linux-install-nginx.html 配置jdk1.8 https://blog.csdn.net/qq_42 ...