派生方法,面向对象三大特征,封装,伪装,多态
- 派生方法的实战(非非菲菲菲菲常重要)
- 什么是派生
- 派生方法的使用
- 面向对象三大特征之封装
- 封装是什么
- 封装的实现
- property伪装属性
- 实战BMI
- 面向对象三大特征之多态
- 面向对象之反射
1.派生方法的实战(非非菲菲菲菲常重要)
在学派生实战之前我们再来回顾一下什么是派生
1.1什么是派生:
指的是子类继承父类的属性方法,并且派生出自己独有的属性与方法
通过super来指向父类的属性(super()是一个特殊的类,调用super得到一个对象,该对象指向父类的名称空间)
ok,下面我们来看一串代码:
d = {
't1': datetime.datetime.today(),
't2': datetime.date.today()
}
res = json.dumps(d)
print(res)
我的目的是想将这个字典用json的方式序列化,但是执行后发现不可行,会报错:
| raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type datetime is not JSON serializable |
所以这个时候我们来查看一下报错的源码(json.JSONEncoder):
在报错的源码中有一个关于default的描述:
class JSONEncoder(object):
"""Extensible JSON <http://json.org> encoder for Python data structures.
Supports the following objects and types by default:
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
| str | string |
+-------------------+---------------+
| int, float | number |
+-------------------+---------------+
| True | true |
+-------------------+---------------+
| False | false |
+-------------------+---------------+
| None | null |
+-------------------+---------------+ # 就是说即将要被序列化的数据要在这些数据类型中,其他的乱七八糟的就会报错
可以看出我们datetime模块得出的字符不属于左边这一列的数据类型,同样的json也无法接受,那咋整?这个时候我们就要用到我们的派生方法(你可看好楼)
2 派生方法的使用
我们新建一个MyJsonEncode类,然后将json.JSONEncoder作为他的父类,然后继承他,然后对内部的default进行重新定义(错误就是出现在这里的嘛),用isinstance内置函数进行判断我们输入的数据类型即可!

派生方法序列化代码
d = {
't1': datetime.datetime.today(),
't2': datetime.date.today()
}
# res = json.dumps(d)
"""
class JSONEncoder:
pass
dumps(obj,cls=None):
if cls == None:
cls = JSONEncoder
return cls(...) # JSONEncoder()
查看JSONEncoder源码发现序列化报错是有default方法触发的
raise TypeError(f'Object of type {o.__class__.__name__} '
f'is not JSON serializable')
我们如果想要避免报错 那么肯定需要对default方法做修改(派生)
"""
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)
json.dumps(d, cls=MyJsonEncode)
isinstance()是Python中的一个内建函数。是用来判断一个对象的变量类型
strftime()函数可以把YYYY-MM-DD HH:MM:SS格式的日期字符串转换成其它形式的字符串
2.面向对象三大特征之封装
1.封装是什么
|
1.在类定义阶段使用双下划线开头命名的属性将会被隐藏 形式:__变量名,,,(函数,变量,数据都可以被隐藏,只要是在类体内的所有可以被定义的都可以被隐藏) |
封装的代码
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
"""
3.property伪装属性
可以简单的理解为 将方法伪装成数据
简单理解就是在类体中,我们调用数据的时候是可以直接点名字的obj.name,而调用方法的时候是要加括号的obj.func(),伪装就是调用方法的时候也可以不用括号obj.func。
使用方法 @property
@property
def BMI(self):
return self.weight / (self.height ** 2)
这样之后我们在调用BMI时候就不用加括号了
扩展了解
体质指数(BMI)=体重(kg)÷身高^2(m)
BMI指数
# 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)
# p1 = Person('jason', 78, 1.83)
# res = p1.BMI()
# print(res)
# p2 = Person('悍匪', 72, 1.73)
# res = p2.BMI()
# print(res)
"""BMI虽然需要计算获得 但是更像是人的数据"""
# p1 = Person('jason', 78, 1.83)
# print(p1.BMI)
# print(p1.name)
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
面向对象三大特征之多态

浙公网安备 33010602011771号