面向对象之继承
面向对象的三大特性: 封装,继承,多态.
什么是继承?
专业角度: B 继承 A类, B就叫做A的子类,派生类, A叫做B的父类,基类,超类. B类以及B类的对象使用A类的所有的属性以及方法.
字面意思: 继承就是继承父母所有的资产.
单继承,多继承.
继承的优点.
-
节省代码.
-
增强的耦合性.
-
代码规范化.
继承分为单继承与多继承.
- Person Dog Cat : 子类,派生类
- Animal: 父类, 基类, 超类
- 单继承: 使用.
- 多继承:有区别.
- 单继承.
class Person:
def init(self,name,sex,age):
self.name = name
self.age = age
self.sex = sex
class Cat:
def init(self,name,sex,age):
self.name = name
self.age = age
self.sex = sex
class Dog:
def init(self,name,sex,age):
self.name = name
self.age = age
self.sex = sex
class Animal:
def init(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
class A:
pass
class Person(Animal):
pass
class Dog(Animal):
pass
class Cat(Animal):
pass
继承的优点:
继承分为单继承与多继承.
Person Dog Cat : 子类,派生类
Animal: 父类, 基类, 超类
单继承: 使用.
多继承:有区别.
class Animal(object):
live = '有生命的'
def init(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def eat(self):
print(f'self----> {self}')
print('动物都需要进食')
class Person(Animal):
pass
# 1.从类名执行父类的属性.
# print(Person.dict)
# print(Person.live)
# Person.eat(55)
# 2. 从对象执行父类的一切.
# 实例化对象一定一定会执行三件事. 一定会执行__init__
# p1 = Person('dsb', 21, 'laddy_boy')
# # print(p1.dict)
# print(p1.live)
# p1.eat()
# print(f'p1--->{p1}')
Person.live = 'xxx'
print(Person.live)
注意: 子类以及子类对象只能调用父类的属性以及方法,不能操作(增删改).
class Animal(object):
live = '有生命的'
def init(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def eat(self):
print(f'self----> {self}')
print('动物都需要进食')
class Person(Animal):
def eat(self):
print('人类需要进食')
p1 = Person('dsb', 21, 'laddy_boy')
# 子类将父类的方法覆盖了,(重写父类的方法)
p1.eat = '李业'
p1.eat() # 对象查找顺序先从对象空间找名字, 子类找名字, 父类找名字.
如何既要执行父类方法又要执行子类方法
两种解决方式:
class Animal:
live = '有生命的'
def init(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def eat(self):
print(f'self----> {self}')
print('动物都需要进食')
class Person(Animal):
def init(self,name, age, sex, hobby):
'''
self : p1
:param name: 怼怼哥
:param age: 23
:param sex: 不详
:param hobby: 吹牛逼
'''
# 方法一:
Animal.init(self, name, age, sex)
# 方法二:
# super(Person, self).init(name, age, sex)
# super().init(name, age, sex)
self.hobby = hobby
def eat(self):
print('人类需要进食')
super().eat()
p1 = Person('怼怼哥', 23, '不详','吹牛逼')
# print(p1.dict)
p1.eat()
class Base:
def init(self, num):
self.num = num
def func1(self):
print(self.num)
class Foo(Base):
pass
obj = Foo(123)
obj.func1()
class Base:
def init(self, num):
self.num = num
def func1(self):
print(self.num)
class Foo(Base):
def func1(self):
print("Foo. func1", self.num)
obj = Foo(123)
obj.func1()
class Base:
def init(self, num): # 2
self.num = num
def func1(self): # 4
print(self.num) # 123
self.func2() # self ---> obj # 对象查询顺序:
def func2(self):
print("Base.func2")
class Foo(Base):
def func2(self):
print("Foo.func2")
obj = Foo(123) # 1
obj.func1() # 3
class Base:
def init(self, num):
self.num = num
def func1(self):
print(self.num)
self.func2()
def func2(self):
print(111, self.num)
class Foo(Base):
def func2(self):
print(222, self.num)
lst = [Base(1), Base(2), Foo(3)]
for obj in lst:
obj.func2()
class Base:
def init(self, num):
self.num = num
def func1(self):
print(self.num)
self.func2()
def func2(self):
print(111, self.num)
class Foo(Base):
def func2(self):
print(222, self.num)
lst = [Base(1), Base(2), Foo(3)]
for obj in lst:
obj.func1()
子类以及对象可以调用父类的属性方法.
多继承.
class God:
# def init(self,name):
# self.name = name
def fly(self):
print('会飞')
def climb(self):
print('神仙累了也需要爬树')
class Monkey:
# def init(self,sex):
# self.sex = sex
def climb(self):
print('爬树')
class MonkeySun(God, Monkey):
pass
# 多继承的难点就是继承顺序的问题
sun = MonkeySun()
sun.climb()
python2x
class A: # 经典类
pass
class B(object): # 新式类
pass
python3x:(默认继承object)
class C: # 新式类
pass
class A:
pass
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
class E:
pass
class F(D, E):
pass
class G(F, D):
pass
class H:
pass
class Foo(H, G):
pass
print(Foo.mro())
mro算法 面试中有可能会遇到
mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )
mro(Foo(H,G)) = [Foo] + merge(mro(H), mro(G),[H,G])
表头:
列表的第一个元素
表尾:
列表中表头以外的元素集合(可以为空)
表头,表尾
[A,B,C] : 表头: A 表尾: [B,C]
[A] : 表头: A 表尾: []
'''
class O:
pass
class D(O):
pass
class E(O):
pass
class F(O):
pass
class B(D,E):
pass
class C(E,F):
pass
class A(B,C):
pass
a = A()
a.func()
'''
'''
mro(A) = mro(A(B,C))
= [A] + merge(mro(B), mro(C), [B,C])
mro(B) = mro(B(D,E))
= [B] + merge(mro(D), mro(E), [D,E])
= [B] + merge([D,O], [E,O], [D,E])
= [B,D] + merge([O], [E,O], [E])
= [B,D,E,O]
mro(C) = mro(C(E,F))
= [C] + merge(mro(E), mro(F),[E,F])
= [C] + merge([E,O],[F,O],[E,F])
= [C,E] + merge([O],[F,O],[F])
= [C,E,F,O]
mro(A) = mro(A(B,C))
= [A] + merge([B,D,E,O], [C,E,F,O], [B,C])
= [A,B] + merge([D,E,O], [C,E,F,O], [C])
= [A,B,D] + merge([E,O], [C,E,F,O], [C])
= [A,B,D,C] + merge([E,O], [E,F,O])
= [A,B,D,C,E] + merge([O], [F,O])
= [A,B,D,C,E,F,O]
'''
class O:
pass
class D(O):
pass
class E(O):
pass
class F(O):
pass
class B(D,E):
pass
class C(E,F):
pass
class A(B,C):
pass
工作中用mro()方法研究新式类的继承顺序
print(A.mro())
面向对象:
-
python2.2之前:都是经典类,
-
python2.2直至python2.7之间存在两种类型: 经典类,新式类.
-
经典类: 基类不继承object,查询规则 依靠:深度优先的原则.
-
新式类: 基类必须继承object,查询规则: mro算法.
-
python3x 只有新式类.