面向对象三大特性之封装
一、继承json模块,并派生出新的功能
- 继承json模块中的JSONEncoder,并派生出新的功能
import json
from datetime import date, datetime
#在原来json模块中可序列化的数据型优先
# print(type(datetime.now()))
#<class 'datetime.datetime'>
#json不可以变化集合,类
# dict1 = {
# # 'time1': str(datetime.now())
# 'time1': datetime.now()
# }
# res = json.dumps(dict1)
# print(res) #Object of type datetime is not JSON serializable
#现在想要自定义一个可以被json化的类
class MyJson(json.JSONEncoder):
#datetime.now() ---->o
def default(self, o):
#isinstance:判断一个对象是否是一个类的实例
if isinstance(o, datetime): #True
return datetime.strftime(o, '&Y-%m-%d %X')
else:
return super().default(self, o)
dict1 = {
'time1': datetime.now(),
'name': 'yafeng'
}
#指定自定义的一个MyJson 派生类
#cls= 自定义的类
res = json.dumps(dict1, cls=MyJson)
print(res)
#{"time1": "&Y-11-27 14:32:22", "name": "yafeng"}
二、组合
'''
夺命三问:
1、什么是组合?
组合指的是一个对象中,包含另一个或多个对象
2、为什么要用组合?
减少代码的冗余
3、如何使用组合?
耦合度:
藕:莲藕---> 藕断丝连
- 耦合度越高:程序的可扩展性越低
- 耦合度越低:程序的可扩展性越高
总结:
- 继承:
继承是类与类之间的关系,子类继承父类的属性与方法,子类与父类是一种'从属'关系
- 组合:
组合是对象与对象的关系,一个对象拥有另一个中的属性/方法,是一种什么有什么的关系
'''
# #继承
# #父类
# class People:
# def __init__(self, name, age, sex, year, month, day):
# self.name = name
# self.age = age
# self.sex = sex
# self.year = year
# self.month = month
# self.day = day
#
# def tell_birth(self):
# print(f'''
# =====出生年月日=====
# 年:{self.year}
# 月:{self.month}
# 日:{self.day}
#
# ''')
#
#
# #老师类
# class Teacher(People):
# def __init__(self, name, age, sex, year, month, day):
# super().__init__(name, age, sex, year, month, day)
#
# #学生类
# class Student(People):
# def __init__(self, name, age, sex, year, month, day):
# super().__init__(name, age, sex, year, month, day)
#
#
# tea1 = Teacher('tank', 18, 'male', 2001, 1, 11)
# stu1 = Student('yafeng', 16, 'male', 2003, 12, 11)
#
# print(tea1.name, tea1.age, tea1.sex, tea1.year, tea1.month, tea1.day)
# tea1.tell_birth()
#
# '''
# tank 18 male 2001 1 11
#
# =====出生年月日=====
# 年:2001
# 月:1
# 日:11
# '''
# print(stu1.name, stu1.age, stu1.sex, stu1.year, stu1.month, stu1.day)
# stu1.tell_birth()
# '''
# yafeng 16 male 2003 12 11
#
# =====出生年月日=====
# 年:2003
# 月:12
# 日:11
#
# '''
#用组合去实现
class People:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
#老师类
class Teacher(People):
def __init__(self, name, age, sex):
super().__init__(name, age, sex)
#学生类
class Student(People):
def __init__(self, name, age, sex):
super().__init__(name, age, sex)
#日期类
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
def tell_birth(self):
print(f'''
=====出生年月日=====
年:{self.year}
月:{self.month}
日:{self.day}
''')
tea1 = Teacher('tank', 25, 'female')
date_obj = Date('1994', 1, 11)
#老师对象中包含一个自定义的日期对象
tea1.date_obj = date_obj
tea1.date_obj.tell_birth()
'''
=====出生年月日=====
年:1994
月:1
日:11
'''
stu1 = Student('yafeng', 18, 'male')
date_obj = Date('1196', 1, 30)
stu1.date_obj = date_obj
stu1.date_obj.tell_birth()
'''
=====出生年月日=====
年:1196
月:1
日:30
'''
'''
练习需求:
选课系统:
1、有学生类,老师类,学生与老师有属性'名字,年龄,性别,课程'
2、有方法,老师与学生可以添加课程,打印学习/教授的课程
#用组合实现
'''
# 父类
class People:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
# 打印出生日期
def tell_birth(self):
# pass
print(f'''
年:{self.date_obj.year}#在后面stu1.date_obj= date_obj
月:{self.date_obj.month}
日:{self.date_obj.day}
''')
# 添加课程
def add_course(self, course_obj):
self.course_list.append(course_obj)
# pass
# 打印当前课表内的所有课程信息
def tell_all_course(self):
# 从当前对象课程列表中取出所有的课程对象
for couser_obj in self.course_list:
couser_obj.tell_course_info()
class Student(People):
def __init__(self, name, age, sex):
super().__init__(name, age, sex)
# 学生自己的课程列表
self.course_list = []
class Teacher(People):
def __init__(self, name, age, sex):
super().__init__(name, age, sex)
# 老师自己的教授的课程列表
self.course_list = []
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
# 定义一个课程类:课程有:课程名称,课程价格,课程周期
class Course:
def __init__(self, course_name, course_price, course_time):
self.course_name = course_name
self.course_price = course_price
self.course_time = course_time
# 定义打印课程方法: 只打印一个课程信息
def tell_course_info(self):
print(f'''
=====课程信息如下=====
课程名称:{self.course_name}
课程价格:{self.course_price}
课程时间:{self.course_time}
''')
# 创建学生对象
stu1 = Student('yafeng', 18, 'male')
date_obj = Date(2001, 1, 30)
stu1.date_obj = date_obj
# 创建课程对象
python_obj = Course('python', 66666, 6)
go_obj = Course('go', 29998, 5)
# 给当前学生对象添加课程对象
# 添加python课程
stu1.add_course(python_obj)
# 添加go课程
stu1.add_course(go_obj)
# 当前学生打印所有课程的信息
stu1.tell_all_course()
三、封装
'''
夺命三问
1、什么是封装?
封:比如一个袋子,封起来
装:比如将一堆小猫,小狗装在袋子里
#对象---->相当于一个袋子
封装指的是可将一堆属性和方法。封装到对象中
ps: 对象就好比一个‘袋子/容器’, 可以存放一堆属性和方法
ps: 存不是目的,目的是为了取,可以通过‘对象.’的方式获取属性或方法
2、为什么要封装?
可以通过‘对象.’的方式‘存放/获取’属性或方法
对象拥有‘.’的机制
方便数据的存取
3、如何封装?
class user:
x = 10
def func():
pass
obj = user()
obj.y = 20
obj ---->x,func,y
'''
四、访问限制机制
'''
夺命三问:
1、什么是访问限制机制?
凡是在类内部定义的属性或方法,
以__开头的属性或方法名,都会被限制,外部不能'直接访问'该属性的原型
ps: 看起来像是将该属性或方法隐藏起来了
#python特有的
注意:凡是在类内部定义__开头的属性或方法,都会变形为_类名__属性/方法。
2、为什么要有访问限制?
比如:将一些隐私的数据,隐藏起来,不让外部轻易获取
-接口:
可以将数据封装成一个接口,可以让用户调用接口,
并且通过相应的逻辑,最后再将数据返回给用户
3、如何实现?
'''
# # demo1
# class User:
#
# #__开头的属性
# __name = 'yafeng' #__name变形为---> _类名__name
#
# #__开头的方法
# def __run(self):
# print('yafeng is running')
#
#
# # print(User.__name) #AttributeError: type object 'User' has no attribute '__name'
# #不能直接访问
#
# obj = User()
# print(obj._User__name) #yafeng
# #demo2
# class User:
# #__开头的属性
# __name = 'yafeng'
# __age = 18
# __sex = 'male'
# __ID = '12345678966'
# __bal = 12345678910
#
# def __init__(self, name, age, sex):
# self.__naem = name
# self.__age = age
# self.__sex = sex
#
#
# #校验接口,获取用户信息
# def parse_user(self, username, password):
# if username == 'yafeng_handsome' and password == '666':
# print(f'''
# 通过验证,获取用户信息
# 用户名:{self.__naem}
# 用户年龄:{self.__age}
# 用户性别:{self.__sex}
# 用户ID:{self.__ID}
# 用户资产:{self.__bal}
# ''')
# else:
# print('校验失败,无法查询用户信息!')
#
# #__开头的方法
# def __run(self):
# print('yafeng is running...')
#
# obj = User('yafeng', 18, 'male')
# obj.parse_user('yafeng_handsome', '666')
# '''
# 通过验证,获取用户信息
# 用户名:yafeng
# 用户年龄:18
# 用户性别:male
# 用户ID:12345678966
# 用户资产:12345678910
# '''
#
#demo3
class ATM:
#取钱功能
#1、插入银行卡
def __insert_card(self):
print('开始插卡...')
pass
#2、输入密码
def __input_pwd(self):
print('输入密码...')
pass
#3、输入取款金额
def __input_bal(self):
print('输入取款金额...')
pass
#4、出钱
def __output_money(self):
print('开始吐钱...')
pass
#5、打印流水账单
def __print_flow(self):
print('打印流水账单...')
pass
#取款顺序接口
def withdraw(self):
#1、插入银行卡
self.__insert_card()
#2、输入密码
self.__input_pwd()
#3、输入取款金额
self.__input_bal()
#4、出钱
self.__output_money()
#5、打印流水账单
self.__print_flow()
atm_obj = ATM()
atm_obj.withdraw()
五、propetry
'''
夺命三问:
1、什么是property?
是一个python内置的装饰器,可以装饰在'类内部的方法'上。
可以将该方法调用方式有由---->对象.方法()----> 对象.方法
2、为什么用property?
ps:在某些场景下,调用的方法只是用来获取计算后的某个值
ps:必须通过 对象.方法() 方式调用,让该方法看起来像动词
让名词的方法,调用时更为合理
目的是为了,迷惑调用者,调用的方法误以为是 属性
3、如何用?
'''
#需求:计算人体BMI指数
#公式:BMI=体重/身高的平方
#value = weight/(height*height)
class User:
def __init__(self, name, height, weight):
self.__name = name
self.weight = weight
self.height = height
#获取BMI指数的方法
@property
def BMI(self):
return self.weight/(self.height**2)
@property
def name(self):
return self.__name
@name.setter
def name(self, value):
self.__name = value
@name.deleter
def name(self): #删除属性
del self.__name
user_obj = User('yafaneg', 1.77, 64)
# user_obj.BMI()
# print(user_obj.BMI())
#20.428357113217785
#@property以后
print(user_obj.BMI)
#20.428357113217785
#注意此时不能在BMI后面加(),否则会报错
# print(user_obj.BMI())
#TypeError: 'float' object is not callable
# print(user_obj.name) #yafaneg
#
#
# #修改属性
# user_obj.name = '亚峰'
# print(user_obj.name) #亚峰
#删除属性
del user_obj.name
print(user_obj.name) #AttributeError: 'User' object has no attribute '_User__name'