===========================重点强调===========================
类:解决对象之间的冗余问题
相似的东西放到类中,为多个对象共享
继承:解决类之间的冗余问题
为多个类共享
分析对象所具有的属性时,
要站在一定的角度上,围绕着项目中用的上的属性进行总结
否则,属性是无边无际的
---------------
购物车项目中,原来的tank方式,还是存在循环导入的问题(虽然程序还能跑起来,但是其是存在问题的,故需要进行修改)
避免循环导入的问题的措施:
①登录功能写到 login_auth 里
②使用os.envieron
------------------
代码规范格式要求:在 执行所有核心逻辑之前,
1、先导入内置的模块
import 写一行
2、导入第三方的模块
from ... import ... # 写在一起
3、导入自己的模块
from .. import ...
4、放全局变量
在下面写内容代码
============================继承================================
1 什么是继承
继承是一种新建类的方式,新建的类称之为子类,被继承的类称之为
父类、基类、超类
python支持多继承
2 为何要继承
子类会遗传父类的属性,所以继承是用来解决类与类之间代码冗余问题
3、如何实现继承
class Parent1:
pass
class Parent2:
pass
class Sub1(Parent1):
pass
class Sub2(Parent1,Parent2):
pass
print(Sub1.__bases__)
print(Sub2.__bases__)
# __bases__ 打印sub的父类
----继承案列:
class OldboyPeople:
school = "oldboy"
class Student(OldboyPeople):
def __init__(self,name,age,gender,stud_id,course):
self.name = name
self.age = age
self.gender = gender
self.stu_id = stud_id
self.course = course
def choose(self):
print('%s 正在选课' %self.name)
class Teacher(OldboyPeople):
def __init__(self,name,age,gender,salary,level):
self.name = name
self.age = age
self.gender = gender
self.salary = salary
self.level = level
def score(self,stu,num):
stu.num = num
stu1=Student("艾利克斯",73,'male',1001,"python全栈开放")
tea1=Teacher("egon",18,'male',2000,10)
print(stu1.school)
补充:
子类可以继承、使用父类的任何方法,包括__init__函数
按照查找优先级找,而不能用就近原则查找
对象 > 类 > 父类
==========在子类派生的新方法中重用父类的功能=======================
方式一:指名道姓地调用某一个类的函数
特点:不依赖于继承关系
类定义中,指明道姓的调用其他类的功能
这种方式不依赖继承
该类调用了其他类的方法,为该类中的对象,造了若干的数据属性
从而不借助继承机制,实现继承的效果
在子类派生的新方法中重用父类的功能
class OldboyPeople:
school = "oldboy"
# 空对象,"艾利克斯",73,'male'
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
def f1(self):
print('1111111')
class Student(OldboyPeople):
# 空对象,"艾利克斯",73,'male',1001,"python全栈开放"
def __init__(self,name,age,gender,stu_id,course):
OldboyPeople.__init__(self,name,age,gender) # OldboyPeople.__init__(空对象,"艾利克斯",73,'male')
self.stu_id = stu_id
self.course = course
def choose(self):
print('%s 正在选课' %self.name)
def f1(self):
OldboyPeople.f1(self)
print("22222")
class Teacher(OldboyPeople):
def score(self,stu,num):
stu.num = num
stu1=Student("艾利克斯",73,'male',1001,"python全栈开放")
# tea1=Teacher("egon",18,'male',2000,10)
stu1.f1()
补充:
class Teacher:
def __init__(self, name, age, salary, level):
People.__init__(self, name, age, None)
self.salary = salary
self.level = level
self.its_class = []
当使用这种方式模拟继承的时候:
原属性名,发生了变形,对于变形的,必须要通过变形之后的名字 才能访问这些属性
teacher1=Teacher('木木',18,'99k','低级')
teacher1.__dict__ 中的内容详细:
{'_People__name': '木木', '_People__age': 18, '_People__gender': None, 'salary': '18k', 'level': '高级', 'its_class': []}
方式2:依赖继承(不推荐)
继承 的耦合性高
继承(能少用,还是少用)
用时,切勿将继承的层级设置过多
推荐用非继承方式,实现继承效果的方式
补充:
函数 不等价于 方法
没经过classmethod等的处理 都是函数(即 函数就是不具有自动传参self的效果)
就是单纯语句的集和,没有自动传值的作用
经过了处理 叫 方法(即 方法都具有 自动传参self的效果);
方法 有自动传值的作用
实参 与 形参
定义时,叫 形参
调用时,叫 实参
============================属性查找======================================
解决覆盖的原则:只要名字不一样便可实现
1、隐藏
隐藏之后,父类、子类中的同名属性便不会产生 覆盖,因为发生了变形 底层的名字不一样
只不过 表面看起来一样
例1:
class Foo:
def f2(self):
print("Foo.f2")
def f1(self):
print('Foo.f1')
self.f2() # obj.f2()
class Bar(Foo):
def f2(self):
print("Bar.f2")
obj = Bar()
obj.f1()
"""
Foo.f1
Bar.f2
"""
例2:父类如果不想让子类覆盖自己的方法,可以在方法名前加前缀__
class Foo:
def __f2(self): # _Foo__f2
print("Foo.f2")
def f1(self):
print('Foo.f1')
self.__f2() # obj._Foo__f2()
class Bar(Foo):
def __f2(self): # _Bar__f2
print("Bar.f2")
obj = Bar()
obj.f1()
2. 直接改名字
class Foo():
def foo_f2(self):
print('我是foo的f2')
def f1(self):
print('我是foo的f1')
self.foo_f2()
class Bar(Foo):
def f2(self):
print('我是bar的f2')
obj = Bar()
obj.f1()
============================继承的实现和原理==================================
coding:utf-8
为保证兼容性:在python中手动继承objest
object不在菱形问题的讨论范围
1 补充知识:
新式类:但凡是继承了object类的子类,以该子类子子孙孙类都称之为新式类
经典类:没有继承了object类的子类,以该子类子子孙孙类都称之为经典类
python3中全都是新式类,python2中才有经典类:
在python3中没有继承任何类的类会默认继承object类
class Foo(object):
pass
print(Foo.__bases__)
2 继承的实现原理
2.1 菱形问题:一个子类继承的多条件分支最终汇聚到一个非object类,在菱形继承下
新式类与经典类关于属性查找的方式不同
新式类:广度优先
经典类:深度优先
例1:非菱形继承,经典类与新式类的属性查找顺序都一样
class E:
# def test(self):
# print('from E')
pass
class F:
def test(self):
print('from F')
class B(E):
# def test(self):
# print('from B')
pass
class C(F):
def test(self):
print('from C')
class D:
def test(self):
print('from D')
class A(B, C, D):
# def test(self):
# print('from A')
pass
obj=A()
obj.test()
例2:菱形继承
class G(object): # 在python2中,未继承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()
print(A.mro())
若无分支(只有单继承),直接一条路去找就行
确定 查找顺序,解决多继承是广度一层一层找,还是深度找
查找时,object 最后找,即现有的类 都找不到时找object
=============================> mixins机制 <=========================================
这个机制
Mixmin 的一个类,只单纯的表示某一个功能
作用单一
-------------
原本的多继承: 继承关系不清晰
多继承的规范,Mixins机制:
多个类中,只有一个类是用来表示归属的类(往右放)
其他类都是功能类(往左放)
类名加上Mixins以标识
这样做的好处:继承关系看起来更清晰 ,既符合了人的表达方式
同时凸显了多继承的好处,最大限度的减少代码的冗余
通过C3列表中的顺序进行查找