----------------------------day21---------------------------------
# 继承解决的是类与类之间的代码冗余问题,一定是一个类是另外一个类的子类
# 继承关系的查找
# 总结对象之间的相似之处得到类,总结类与类之间的相似之处就得到了类们的父类
'''
class OldboyPeople:
school='Oldboy'
class OldboyStudent(OldboyPeople):
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
self.score=0
def choose_course(self):
print('%s is choosing course' %self.name)
class OldboyTeacher(OldboyPeople):
def __init__(self,name,age,sex,level):
self.name=name
self.age=age
self.sex=sex
self.level=level
def score(self,stu,num):
stu.score=num
'''
'''
class OldboyPeople:
school='Oldboy'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
class OldboyStudent(OldboyPeople):
# def __init__(self,name,age,sex):
# self.name=name
# self.age=age
# self.sex=sex
# self.score=0
def choose_course(self):
print('%s is choosing course' %self.name)
class OldboyTeacher(OldboyPeople):
# def __init__(self,name,age,sex,level):
# self.name=name
# self.age=age
# self.sex=sex
# self.level=level
def score(self,stu,num):
stu.score=num
stu1=OldboyStudent('李特丹',18,'female') #OldboyPeople.__init__(stu1,'李特丹',18,'female')
print(stu1.__dict__)
tea1=OldboyTeacher('egon',18,'male') ##OldboyPeople.__init__(tea1,'egon',18,'male',10)
print(tea1.__dict__)
'''
# 问题???:如何在子类派生出的新方法中重用父类的功能
class OldboyPeople:
school='Oldboy'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
class OldboyStudent(OldboyPeople):
def __init__(self,name,age,sex):
self.name=name
self.age=age
self.sex=sex
self.score=0
def choose_course(self):
print('%s is choosing course' %self.name)
class OldboyTeacher(OldboyPeople):
# def __init__(self,name,age,sex,level):
# self.name=name
# self.age=age
# self.sex=sex
# self.level=level
def score(self,stu,num):
stu.score=num
stu1=OldboyStudent('李特丹',18,'female') #OldboyPeople.__init__(stu1,'李特丹',18,'female')
print(stu1.__dict__)
tea1=OldboyTeacher('egon',18,'male') ##OldboyPeople.__init__(tea1,'egon',18,'male',10)
print(tea1.__dict__)
====================================================================================
# 在子类派生出的新方法中重用父类功能的方式一:
# 指名道姓地访问某一个类的函数
# 注意:
# 1. 该方式与继承是没有关系的
# 2. 访问是某一个类的函数,没有自动传值的效果
class OldboyPeople:
school='Oldboy'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
class OldboyStudent(OldboyPeople):
# stu1,'李特丹',18,'female'
def __init__(self,name,age,sex,num=0):
OldboyPeople.__init__(self,name,age,sex) #OldboyPeople.__init__(stu1,李特丹',18,'female')
self.score=num
def choose_course(self):
print('%s is choosing course' %self.name)
class OldboyTeacher(OldboyPeople):
def __init__(self,name,age,sex,level):
OldboyPeople.__init__(self,name,age,sex)
self.level=level
def score(self,stu,num):
stu.score=num
stu1=OldboyStudent('李特丹',18,'female') #OldboyStudent.__init__(stu1,'李特丹',18,'female')
print(stu1.__dict__)
tea1=OldboyTeacher('egon',18,'male',10) ##OldboyTeacher.__init__(tea1,'egon',18,'male',10)
print(tea1.__dict__)
======================================================================================
# 单继承背景下属性查找的顺序:对象-》对象的类-》父类-》。。。
# class Foo:
# # x=333
# pass
#
# class Bar(Foo):
# # x=222
# pass
#
# obj=Bar()
# # obj.x=111
# print(obj.x)
class Foo:
def f1(self):
print('Foo.f1')
def f2(self):
print('Foo.f2')
self.f1() #obj.f1()
class Bar(Foo):
def f1(self):
print('Bar.f1')
obj=Bar()
obj.f2()
'''
Foo.f2
Bar.f1
'''
=================================================================
#coding:utf-8
# 多继承背景下属性查找的顺序:对象-》对象的类-》按照从左往右的顺序一个一个的分支找下去
#
# #第四层
# class I:
# # x='I'
# pass
#
# #第三层
#
# class E:
# # x='E'
# pass
#
# class F(I):
# # x='F'
# pass
#
# class H:
# x='H'
#
# # 第二层
# class B(E):
# # x='B'
# pass
#
# class C(F):
# # x='C'
# pass
#
# class D(H):
# # x='D'
# pass
#
# #第一层
# class A(B,C,D):
# # x='A'
# pass
#
# obj=A()
# # obj.x=111
# print(obj.x)
# 一旦出现菱形继承问题,新式类与经典类在属性查找上的区别是
# 新式类:广度优先查找,在最后一个分支查找顶级类
# 经典类:深度优先查找,在第一个分支就查找顶级类
class G(object):
# def test(self):
# print('from G')
pass
# 第三层
class E(G):
# def test(self):
# print('from E')
pass
class F(G):
def test(self):
print('from F')
pass
# 第二层
class B(E):
# def test(self):
# print('from B')
pass
class C(F):
def test(self):
print('from C')
pass
class D(G):
def test(self):
print('from D')
pass
# 第一层
class A(B,C,D):
# def test(self):
# print('from A')
pass
obj=A()
# obj.test()
# 新式类:对象-》A-》B-》E-》C-》F-》D-G
# 经典类:对象-》A-》B-》E-》G-》C-》F-》D
#在新式类中,提供了一个mro方法
# print(A.mro())
======================================
# 在子类派生出的新方法中重用父类功能的方式二:只能在子类中用
# 在python2:super(自己的类名,对象自己)
# 在python3:super()
# 调用super()会得到一个特殊的对象,该特殊的对象是专门用来引用父类中的属性的,!!!完全参照mro列表!!!
# 注意:
# 1. 该方式与继承严格依赖于继承的mro列表
# 2. 访问是绑定方法,有自动传值的效果
class OldboyPeople:
school='Oldboy'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
class OldboyStudent(OldboyPeople):
# stu1,'李特丹',18,'female'
def __init__(self,name,age,sex,num=0):
# OldboyPeople.__init__(self,name,age,sex) #OldboyPeople.__init__(stu1,李特丹',18,'female')
super(OldboyStudent,self).__init__(name,age,sex)
self.score=num
def choose_course(self):
print('%s is choosing course' %self.name)
class OldboyTeacher(OldboyPeople):
def __init__(self,name,age,sex,level):
super().__init__(name,age,sex)
self.level=level
def score(self,stu,num):
stu.score=num
# stu1=OldboyStudent('李特丹',18,'female') #OldboyStudent.__init__(stu1,'李特丹',18,'female')
# print(stu1.__dict__)
#
# tea1=OldboyTeacher('egon',18,'male',10) ##OldboyTeacher.__init__(tea1,'egon',18,'male',10)
# print(tea1.__dict__)
#例子
class A:
def test(self):
print('A.test()')
super().test()
class B:
def test(self):
print('from B')
class C(A,B):
pass
obj=C()
print(C.mro())
#[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
obj.test()
'''
A.test()
from B
'''
==================================================
'''
1、什么是组合
组合指的是一个对象拥有某一个属性,该属性的值是另外一个类的对象
obj=Foo()
obj.attr1=Bar1()
obj.attr2=Bar2()
obj.attr3=Bar3()
2、为何用组合
为了减少类与类之间代码冗余
3、如何用
'''
class OldboyPeople:
school='Oldboy'
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
class OldboyStudent(OldboyPeople):
def __init__(self,name,age,sex,):
super().__init__(name,age,sex)
self.score=0
self.courses=[]
def choose_course(self):
print('%s is choosing course' %self.name)
def tell_all_course(self):
for course_obj in self.courses:
course_obj.tell_info()
class OldboyTeacher(OldboyPeople):
def __init__(self,name,age,sex,level):
super().__init__(name,age,sex)
self.level=level
def score(self,stu,num):
stu.score=num
class Course:
def __init__(self,c_name,c_price,c_period):
self.c_name = c_name
self.c_price = c_price
self.c_period = c_period
def tell_info(self):
print('<课程名:%s 价钱:%s 周期:%s>' %(self.c_name,self.c_price,self.c_period))
# 创建课程
python_obj=Course('Python全栈开发',19800,'5mons')
linux_obj=Course('Linux架构师',10000,'3mons')
stu1=OldboyStudent('李特丹',18,'female')
stu2=OldboyStudent('张全蛋',38,'male')
stu3=OldboyStudent('刘二蛋',48,'male')
'''
# 一个学生只选修一门课程
stu1.course=python_obj
stu2.course=python_obj
stu3.course=python_obj
# print(stu1.course.c_name,stu1.course.c_price,stu1.course.c_period)
# print(stu2.course.c_name,stu2.course.c_price,stu2.course.c_period)
# print(stu3.course.c_name,stu3.course.c_price,stu3.course.c_period)
stu1.course.tell_info()
stu2.course.tell_info()
stu3.course.tell_info()
'''
# 一个学生可以选修多门课程
stu1.courses.append(python_obj)
stu1.courses.append(linux_obj)
stu2.courses.append(python_obj)
stu2.courses.append(linux_obj)
stu1.tell_all_course()
stu2.tell_all_course()
# tea1=OldboyTeacher('egon',18,'male') ##OldboyPeople.__init__(tea1,'egon',18,'male',10)
# print(tea1.__dict__)
========================================================
'''
1 多态
多态指的是同一种事物的多种形态
2 多态性:
可以在不用考虑对象具体类型的情况下而直接使用对象
优点:
归一化,简化对象的使用
'''
# import abc
#
# class Animal(metaclass=abc.ABCMeta):
# @abc.abstractmethod
# def speak(self):
# pass
#
# @abc.abstractmethod
# def run(self):
# pass
#抽象基类:是用来指定规范,但凡继承该类的子都必须实现speak和run,而名字必须叫speak和run
#注意:不能实例化抽象基类
# Animal()
# class People(Animal):
# def speak(self):
# print('say hello')
#
# def run(self):
# pass
#
# class Dog(Animal):
# def speak(self):
# print('汪汪汪')
#
# def run(self):
# pass
#
# class Pig(Animal):
# def speak(self):
# print('哼哼哼哼哼')
# #
# def run(self):
# pass
# #
# obj1=People()
# obj2=Dog()
# obj3=Pig()
#
#obj1,obj2,obj3都是动物
# obj1.speak()
# obj2.speak()
# obj3.speak()
#
# def speak(animal):
# animal.speak()
#
#
# speak(obj1)
# speak(obj2)
# speak(obj3)
# obj1=[1,2,3]
# obj2='hello'
# obj3={'x':1}
#
# print(obj1.__len__())
# print(obj2.__len__())
# print(obj3.__len__())
#
#
# print(len(obj1))
# print(len(obj2))
# print(len(obj3))
# python崇尚鸭子类型
class Txt:
def read(self):
print('txt read')
def write(self):
print('txt write')
class Process:
def read(self):
print('Process read')
def write(self):
print('Process write')
class Disk:
def read(self):
print('Disk read')
def write(self):
print('Disk write')
obj1=Txt()
obj2=Process()
obj3=Disk()
obj1.read()
obj1.write()
obj2.read()
obj2.write()
obj3.read()
obj3.write()
===============================================================
'''
1 什么是封装
装就是将数据属性或者函数属性存放到一个名称空间里
封指的是隐藏,该隐藏是为了明确地区分内外,即该隐藏是对外不对内(在类外部无法直接访问隐藏的属性,而在类内部是可以访问)
2 为何要封装
1. 封数据属性:???
2. 封函数属性:???
3 如何封装???
在类内定义的属性前加__开头
'''
# class People:
# __country='China' #_People__country='China'
# __n=111 #_People__n=111
#
# def __init__(self,name):
# self.__name=name #self._People__name=name
#
# def run(self):
# print('%s is running' %self.__name) #self._People__name
# print(People.__country)
# obj=People('egon')
# print(obj.__name)
# print(obj.run)
# obj.run()
# print(People.__dict__)
# print(People._People__country)
# print(obj.__dict__)
# print(obj._People__name)
# 总结这种隐藏需要注意的问题:
# 1. 这种隐藏只是一种语法上的变形,并没有真的限制访问
# 2. 这种变形只在类定义阶段检测语法时变形一次,类定义阶段之后新增的__开头的属性不会发生变形
# People.__x=1
# obj.__y=2
# print(People.__dict__)
# print(obj.__dict__)
# 3. 在继承中,父类如果不想让子类覆盖自己的方法,可以在该方法前加__开头
# class Parent1:
# def __func(self): #_Parent1__func
# print('parent1.func')
#
#
# class Sub1(Parent1):
# def __func(self): #_Sub1__func
# print('sub1.func')
# class Foo:
# def __f1(self): #_Foo__f1
# print('Foo.f1')
#
# def f2(self):
# print('Foo.f2')
# self.__f1() #self._Foo__f1()
#
# class Bar(Foo):
# def __f1(self): #_Bar__f1
# print('Bar.f1')
#
#
# obj=Bar()
# obj.f2()
# 封装的真实意图:把数据属性或函数属性装起来就是为了以后使用的,封起来即藏起来是为不让外部直接使用
# 1.封数据属性:把数据属性藏起来,是为了不让外部直接操作隐藏的属性,而通过类内开辟的接口来间接地操作属性,
# 我们可以在接口之上附加任意的控制逻辑来严格控制使用者对属性的操作
'''
class People:
def __init__(self, name, age):
self.__name = name
self.__age = age
def tell_info(self):
print('<name:%s age:%s>' % (self.__name, self.__age))
def set_info(self, name, age):
if type(name) is not str:
print('名字必须是str类型')
return
if type(age) is not int:
print('年龄必须是int类型')
return
self.__name = name
self.__age = age
obj = People('egon', 18)
# obj.tell_info()
# obj.set_info('EGON',19)
# obj.set_info(123,19)
obj.set_info('EGOn','19')
obj.tell_info()
'''
#2. 封函数属性: 隔离复杂度
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()
a=ATM()
a.withdraw()
==============================================
'''
成人的BMI数值:
过轻:低于18.5
正常:18.5-23.9
过重:24-27
肥胖:28-32
非常肥胖, 高于32
体质指数(BMI)=体重(kg)÷身高^2(m)
EX:70kg÷(1.75×1.75)=22.86
'''
# property装饰器就是将一个函数属性伪装成一个数据属性
# class People:
# 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)
#
#
# obj=People('egon',80,1.83)
# # print(obj.bmi())
#
# print(obj.bmi)
# 了解
# class People:
# def __init__(self,name):
# self.__name=name
#
# @property
# def name(self):
# return self.__name
#
# @name.setter
# def name(self,obj):
# if type(obj) is not str:
# print('名字必须是str类型')
# return
# self.__name=obj
#
# @name.deleter
# def name(self):
# # print('不让删')
# del self.__name
#
# obj=People('egon')
# # print(obj.name)
#
# # obj.name='EGON'
# # obj.name=123
# # print(obj.name)
#
# del obj.name
# print(obj.name)
class People:
def __init__(self,name):
self.__name=name
def get_name(self):
return self.__name
def set_name(self,obj):
if type(obj) is not str:
print('名字必须是str类型')
return
self.__name=obj
def del_name(self):
# print('不让删')
del self.__name
name=property(get_name,set_name,del_name)
obj=People('egon')
print(obj.name)
# obj.name='EGON'
# obj.name=123
# print(obj.name)
# del obj.name
# print(obj.name)