继承的一点补充
继承json模块中的jsonencoder 并派生出新的功能
import json
from datetime import date,datetime
dict1 = {
'time1':datetime.now() #'time1':str(datetime.now())
} #这样的字符串类型才可以使用
res = json.dumps(dict1)
print(res)
>>>>>>>>>>>>>
报错
###改用以下的方法操作###
class MyJson(json.JSONEncoder):#这个地方的是继承父类
def default(self,o):###这个是一个判断o代表的是是不是一个序列化对象,会把字典res的每一个值都放进去代表o
if isinstance(o,datetime):#判断一个对象是否有一个类的实例,把字典里面每一个值都做一下判断,是不是datetime的对象,
return datetime.strftime(o,'%Y-%m-%d %X') 是的 就返回一个时间的字符串,datetime.now()就是一个datetime对象
else:
return super().default(self,o) ###如果不是的就返回default处理
dict1 = {
'time1':datetime.now(),
'name':'tank'
}
#指定自定义的一个MyJson 派生类
res = json.dumps(dict1,cls = MyJson)##cls= 自定义的类 cls = MyJson是一个必须要有的东西
print(res)
>>>>>>>>>>>>>>>>
{"time1": "2019-11-27 14:53:20", "name": "tank"}
组合
1.夺命三问
1.什么是组合?
-组合指的是一个对象中,包含另一个或者多个对象。
2.为什么要用组合?
-减少代码的冗余
3.如何使用组合?
耦合度:
耦--->莲藕:藕断丝连
-耦合度越高,程序的可扩展性越低
-耦合度越低,程序的可扩展性越高
-跟继承相比,组合的耦合度低,程序的可扩展性高
2.总结
-继承:
继承是类与类的关系,子类继承父类哦的属性/方法,子类和父类是一种从属关系
-组合:
组合是对象与对象的关系,一个对象拥有另一个对象中的属性和方法,是一种什么有什么的关系
#父类
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',17,'male',2002,6,6)
stu1 = Student('Hcy',109,'female',1910,11,11)
print(tea1.name,tea1.age,tea1.sex)
tea1.tell_birth()
stu1.tell_birth()
>>>>>>>>>>>>>>>>>>>>>
tank 17 male
年:2002
月:6
日:6
年:1910
月:11
日: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):
People.__init__(self,name,age,sex)
#学生类
class Student(People):
def __init__(self,name,age,sex):
People.__init__(self,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}
''')
stu1 = Student('Hcy',109,'female')
print(stu1.name,stu1.age,stu1.sex)
date_obj = Date(1090,11,11)
stu1.date_obj = date_obj ######组合这个的意思把= 右边的date_obj看作一个属性值赋值给对象stu1的属性date_obj,也可以这么表示,stu1.new_date = date_obj,相当于obj.name = 'david',这个样就把2个对象组合到一起了。
print(stu1.date_obj.year,stu1.date_obj.month,stu1.date_obj.day)
stu1.date_obj.tell_birth() 调用对象中的函数
>>>>>>>>>>>>>>>
Hcy 109 female
1090 11 11
年:1090
月:11
日:11
组合的使用
'''
练习需求:
选课系统:
1.有学生、老师类,学生和老师都有属性,“名字,性别,年龄,课程
2.方法,老师和学生可以添加课程,打印学生/教授课程
组合的实现
'''
# #父类
class People:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
#打印出日期方法
def tell_birth(self):
print(f'''
年:{self.date_obj.year}
月:{self.date_obj.month}
日:{self.date_obj.day}
''')
#添加课程
def add_course(self,course_obj):
self.course_list.append(course_obj)
def tell_all_course_info(self):
for course_obj in self.course_list:
course_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("Hcy",2000,'female')
date_obj = Date('公元19','11','11')
print(date_obj.year)
stu1.date_obj = date_obj#####
stu1.tell_birth()
#创建课程对象
python_obj = Course('python',77777,6)
go_obj = Course('go',88888,4)
#当前学生的添加了课程对象
#添加了python课程
stu1.add_course(python_obj)####对象.函数+()调用类中间的函数立即执行的
#添加go的课程
stu1.add_course(go_obj)####对象.函数+()调用类中间的函数立即执行的
#当前打印所有的课程信息
stu1.tell_all_course_info() ####对象.函数+()调用类中间的函数立即执行的
>>>>>>>>>>>>>>>>>
公元19
年:公元19
月:11
日:11
======课程信息如下=====
课程名称:python
课程价格:77777
课程周期:6
======课程信息如下=====
课程名称:go
课程价格:88888
课程周期:4
3.封装
1.夺命三问?
1.什么是封装?
-封:比如一个袋子,封起来。
-装:比如一堆小猫小狗,装在袋子里。
-对象相当于一个袋子
封装指的是可以将一堆属性和方法,封装在对象中。
PS:对象就好比一个“袋子/容器”,可以存放一对属性和方法;
PS:存不是目的,目的是为了取,可以通过“对象''方式获取属性或方法。
2.为什么要封装?
-可以通过”对象“的方式,”存放/获取“属性或方法
-对象有”.“的机制
-方便数据的存取
3.如何封装?
class User:
x = 10
def func(self):
print('world')
obj = User()
obj.y = 20
print(obj.x,obj.y)######这个例子就是封装,把数据封装在对象里面
obj.func()
>>>>>>>>>>>>>
10 20
world
4.访问限制机制
1.夺命三问
1.什么是访问限制机制?
-凡是在类内部定义的属性或方法
-以--开头的属性或者方法名,都会被限制,外部不能"直接访问",该属性原型
PS:看着是将该属性或方法隐藏起来
python特有的:
注意:凡是在类内部定义--开头的属性或者方法,都将变形为-类名--属性/方法
2.为什么有访问机制?
-比如将一些隐私的数据,隐藏起来,不让外部轻易的获取
-接口:
可以将一对数据封装成一个接口,可以让用户调用接口
并且通过相应的逻辑,最后将数据返回给用户
3.如何实现?
class User:
#__开头的属性
__name = 'tank'#,__name 变形为 _类名__name
def __run(self):
print('tank is running...')
obj = User()
print(obj.__name)####报错
print(obj._User__name)
obj._User__run()
>>>>>>>>>>>>>>
tank
tank is running...
class User:
__name = 'tank'
__age = 17
__sex = 'male'
__ID = '123'
__bal = '10000000'
# def __init__(self,name,age,sex):
# self.__name = name
# self.__age = age
# self.__sex = sex
def parse_user(self,username,password):
if username == 'tank' and password =='123':
print(f'''
通过验证,获取用户信息:
用户名:{self.__name}
用户年龄:{self.__age}
用户性别:{self.__sex}
身份ID:{self.__ID}
用户资产:{self.__bal}
''')
else:
print('校验失败,无法查询到用户')
obj = User()
obj.parse_user('tank','123') ####正常的方法 不能获取里面的——变量的 可以用这个方式 操作
>>>>>>>>>>>>>
通过验证,获取用户信息:
用户名:tank
用户年龄:17
用户性别:male
身份ID:123
用户资产:10000000
#模拟取钱的操作
class ATM:
def __insert_card(self):
print('开始插卡...')
def __input_pwd(self):
print('输入密码...')
def __input_money(self):
print('开始吐钱')
def __print_flow(self):
print('打印流水账单...')
#取款的规范接口
def withdraw(self):#######这个操作是self.方式调用上面的函数
self.__insert_card()
self.__input_pwd()
self.__input_money()
self.__print_flow()
obj = ATM()
obj.withdraw()
>>>>>>>>>>>>>>>>>>>>>>
开始插卡...
输入密码...
开始吐钱
打印流水账单...
5.property
1.夺命三问
1.什么是property?
-是一个python的内置方法,可以装饰在”类内部的方法上“。
就可以将该方法调用方式----》对象.方法() 变成-----》对象.方法
2.为什么用property?
PS:在某些场景下 调用的方法只是用来获取计算后的某个值;
PS:必须通过,对象.方法()方式调用,让该方法看起来像动词
-目的为了迷惑调用者,调用的方法误以为是属性 而不是方法
3.如何用?
#需求:计算人体的bmi指数
#体重/身高的平方
#value = weight /(height**2)
class User:
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)
user_obj = User('Huyan',100,2)
print(user_obj.bmi)####调用bmi的函数的时候,就没有带括号,因为加了@property 给人感觉是
属性而实际是方法
>>>>>>>>>>>>>>>>>
25.0
修改名字
class User:
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)
@property #######这个原来的 也要写在上面的
def name(self):
return self.__name
@name.setter######需要注意的是修改方法名字 要与property装饰器后的方法是一样的
要用setter来表示
def name(self,value):
self.__name = value
user_obj = User('Huyan',100,2)
# print(user_obj.bmi)
user_obj.name = 'david'
print(user_obj.name)
>>>>>>>>>>>>>>>>>
david
删除名字
class User:
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)
@property
def name(self):
return self.__name
@name.deleter ####把这个名字删除掉
def name(self):
del self.__name
user_obj = User('Huyan',100,2)
# print(user_obj.bmi)
del user_obj.name
print(user_obj.name)
>>>>>>>>>>>
AttributeError: 'User' object has no attribute '_User__name'