依赖
依赖关系:将一个类名或对象名传给另一个类的方法中
class A:
def __init__(self,name,age):
self.name = name
self.age= age
def func(self,objb): #objb = b
print(self)
print(objb)
objb.func() #可以调用B类中的属性
class B:
def __init__(self,name,age):
self.name = name
self.age = age
def func(self):
print(self)
#实例化两个对象
a = A('小明',23)
b = B('小红',21)
a.func(b) #把b这个对象传给A类的func方法
组合
组合关系:将一个类的对象封装给另一个类的对象的属性
class A:
def __init__(self,name):
self.name = name
def func(self,obj):
self.obj = obj #给一个类封装一个属性,该属性是另一个类的对象b
#print(self.obj.name)
class B:
def __init__(self,name):
self.name = name
a = A('xm')
b = B('xh')
a.func(b)
print(a.__dict__)
继承
继承:子类可以具有父类的属性以及方法。
继承分为单继承和多继承:
单继承
:
class Animal:
live = '活着不好吗'
#就算父类这里不指定__init__,Animal也默认是继承了object(python中的新式类,在python2.2-2.7之间存在经典类(父类默认不继承object)和新式类),2.2之前都是经典类),
#所以,当实例化对象之后也会自动执行__init__
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
def eat(self):
print('吃饭了吗?')
class Persion(Animal): #继承
def eat(self): #当子类又写一个跟父类同名的方法时,
#先从对象空间找再从子类空间找(名字),最后从父类空间找
#找到只执行一次就不往上执行了
print('吃面条')
p1 = Persion('小猪',2,'公') #虽然Persion没有__init__但是必须传参数,因为继承了父类(也叫基类或超类)
print(p1.__dict__) #{'name': '小猪', 'age': 2, 'gender': '公'} #子类获得了父类的属性
# p1.eat() #打印:吃饭了吗?#1.当子类没有eat方法时去执行父类的eat方法,如果在子类写一个与父类同名的eat方法叫:子类重写父类的方法
#3.再执行一下
p1.eat() #打印:吃面条
当子类和父类都存在同名的方法时,默认只执行一次,打印了吃面条
之后就不打印吃饭了吗?
了,要想执行了子类的方法之后又执行父类的方法:
class Animal:
def __init__(self,name,age,gender):
self.name = name
self.age = age
self.gender = gender
def eat(self):
print('动物吃东西')
class Persion(Animal):
def __init__(self,name,age,gender,hoby):
#方法一:直接调用,简单粗暴
Animal.__init__(self,name,age,gender) #直接调用父类的方法,通过对象p1传参
#方法二:python内置的super
# super(Persion, self).__init__()#传Animal中init所需参数
super().__init__('小猪',2,'不详')
self.hoby = hoby
def eat(self):
print('人类吃东西')
#同时也执行父类的eat方法
super().eat()
p1 = Persion('小明',23, '男','篮球') #
# print(p1.__dict__)
p1.eat()
#人类吃东西
#动物吃东西
多继承
:
class O:
pass
class D(O):
pass
class E(O):
pass
class F(O):
pass
class B(D,E):
# pass
def eat(self):
print('吃饭')
class C(E,F):
pass
class A(B,C):
# pass
def eat(self):
print('吃饭了吗')
ls = A()
ls.eat()
print(A.mro()) #查看执行顺序
#吃饭了吗
在多继承中,如果两个父类中出现两个同名的方法,那么子类是如何查找父类的方法的?即MRO(Method Resolution Order)问题。
mro计算公式:
mro(Child(Base1,Base2)) = [ Child ] + merge( mro(Base1), mro(Base2), [ Base1, Base2] )
(其中Child继承自Base1, Base2)
以上代码中,查找eat方法的顺序计算方法如下:
mro(A) = mro(A,(B,C))
= [A] + merge(mro(B),mro(C),[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])#E在其它列表的表尾中,忽略此列表,进行下一个列表计算;C不在在其它列表的表尾中,拿出C放到merge外面,并移除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] + merge([O],[O])
= [A,B,D,C.E,F,O] #最终查找顺序
mro(B) = mro(B,(D,E))
= [B] + merge(mro(D),mro(E),[D,E])
= [B] + merge([D,O],[E,O],[D,E]) #表头D不在其他列表的表尾的集合中,拿出D放到merge外面,并移除D
= [B,D] + merge([O],[E,O],[E])
= [B,D,E] + merge([O],[O])
= [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] +merge([O],[O])
= [C,E,F,O]
python虽然支持多继承,但是并不推荐使用。