面向对象2:类空间,类关系

类空间问题

何处可以添加对象属性

class Human:
mind = "有思想"
def __init__(self,name):
self.name = name
def rework(self,work):
self.work = work

man = Human("tom")
man.age = 18   #类外部可以
man.rework("IT") #类内部方法可以
print(man.__dict__)
# {'name': 'tom', 'age': 18, 'work': 'IT'}

对象的属性不仅可以在__init__里面添加,还可以在类的其他方法或者类的外面添加

添加类的静态属性

class Human:
    mind = "有思想"
    def __init__(self,name):
        self.name = name
    def rework(self,work):
        self.work = work
    def sethair(self):
        Human.hair = "头发"
    def setfood(self):
        Human.food = "杂食"

Human.eyes = "眼睛"
Human.sethair("anyone")  #类调用类的方法给类添加静态属性

man = Human("Jarry")
man.setfood()  #对象调用类中的方法给类添加静态属性

print(Human.__dict__)  

对象是找到类的属性

 

对象查找属性的顺序:先从对象空间找 >>类空间找 >>父类空间 >>...

类名查找属性的顺序:先从本类空间找 >>父类空间 >>...

类与类之间的关系

 类与类之间的关系

依赖关系:将一个类的对象或者类名传到另一个类的方法中

class Door:
    def __init__(self,quality):
        self.quality = quality
    def opened(self):
        print("%s门被打开"%self.quality)
class Human:
    def __init__(self,name):
        self.name = name
    def open(self):
        print("%s喊芝麻开门"%self.name)
        door_1.opened()

door_1 = Door("石头")
human_1 = Human("阿凡提")
human_1.open()

# 阿凡提喊芝麻开门
# 石头门被打开

关联关系:将一个类的对象或者类名封装到另一个类的对象的属性中

  聚合关系:关联关系的一种特例,

  组合关系:关联关系的一种特例,将一个类的对象或者类名封装到另一个类的对象的属性中

实现关系:

继承关系:

继承

  继承(英语:inheritance)是面向对象软件技术当中的一个概念。如果一个类别A“继承自”另一个类别B,就把这个A称为“B的子类别”,而把B称为“A的父类别”也可以称“B是A的超类”。继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。 一般静态的面向对象编程语言,继承属于静态的,意即在子类别的行为在编译期就已经决定,无法在执行期扩充

class Animal:
    def __init__(self,sex,age):
        self.sex = sex
        self.age = age
    def eat(self):
        print("进食能力")

class Cat(Animal):  #Cat类继承了Animal的属性
    eyes = "夜视"    #Cat类添加自己的属性
    def eat(self):
        print("爱吃鱼")

class Dog(Animal):
    pass

c1 = Cat("",1)
d1 = Dog("",2)

print(c1.age)
print(c1.eyes)
c1.eat()
d1.eat()

# 1
# 夜视
# 爱吃鱼
# 进食能力

继承的优点:

1,增加了类的耦合性(耦合性不宜多,宜精)。

2,减少了重复代码。

3,使得代码更加规范化,合理化

继承的分类

就上面的例子:

Animal叫做:父类,基类,超类。

Cat Dog叫做:子类,派生类。

python2中有两种类:

  经典类:Python2.2之前一直使用的是经典类,经典类在基类的根如果什么都不写,没有父类

  新式类:python2.2之后出现了新式类,新式类基类的根是object,既所有类都继承了object类

单继承

 类名,对象执行父类方法和执行顺序

class Animal:
hair = "有毛"
def __init__(self,sex,age):
self.sex = sex
self.age = age
def eat(self):
print("填饱肚子")
def sleep(self):
print("日落而息")

class Cat(Animal):
def sleep(self): #先执行本类中的eat方法,如果没有才执行父类中的
print("昼伏夜出")

print(Animal.hair) #子类调用父类属性
Animal.eat("anyone") #子类调用父类方法
Animal.sleep("111") #子类调用父类方法
c1 = Cat("母",1,)
print(c1.hair) #对象调用本类的父类属性
c1.eat() #对象调用本类的父类方法
c1.sleep() #对象调用本类的父类方法,如果本类有,就执行本类的,不再执行父类方法

# 有毛
# 填饱肚子
# 日落而息
# 有毛
# 填饱肚子
# 昼伏夜出

 同时执行本类与父类的方法

 父类.方法()
class Animal:
    def __init__(self,sex,age):
        print("Animal类中")
        self.sex = sex
        self.age = age

class Cat(Animal):
    def __init__(self,sex,age,hair):
        print("Cat类中")
        self.hair = hair
        Animal.__init__(self,sex,age)  #不能省略self

c1 = Cat("",2,"短毛")

# Cat类中
# Animal类中
 super().func()跳过本类(默认)查找func方法并执行
class Animal:
    def __init__(self,sex,age):
        print("Animal类中")
        self.sex = sex
        self.age = age

class Cat(Animal):
    def __init__(self,sex,age,hair):
        print("Cat类中")
        self.hair = hair
        super().__init__(sex,age)  #不写self

c1 = Cat("",2,"短毛")

# Cat类中
# Animal类中

多继承 

class ShenXian:     # 神仙
    def fly(self):
        print("神仙都会飞")
class Monkey:       # 猴
    def chitao(self):
        print("猴⼦喜欢吃桃⼦")
class ShenHou(ShenXian, Monkey): # 孙悟空是神仙,也是只猴
    pass
sxz = ShenHou()    # 孙悟空
sxz.chitao()        # 会吃桃⼦
sxz.fly()           # 会飞

当两个父类中出现了重名方法的时候,调用哪一个父类的方法?

既如何查找父类方法?即MRO(method resolution order“方法分辨顺序”) 问题。

在python中这是一个很复杂的问题.。因为在不同的python版本中使用的是不同的算法来完成MRO的.

经典类的多继承

经典类中采用的是深度优先

 

按照123456的顺序即为深度优先

按照142356的顺序则为广度优先

新式类的多继承mro()

mro序列

MRO是一个有序列表L,在类被创建时就计算出来。

通用计算公式为

Child继承于Base1和Base2
mro(Child(Base1,Base2)) = [Child] + merge(mro(Base1),mro(Base2),[Base1,Base2])

 如果继承于1个基类:

Child继承于Base
mro(Child) = mro(Child(Base))
       = [Child] + merge(mro(Base),[Base])
       = [Child] + merge([Base] + [Base])
       = [B,A]

 如果继承于多个基类:

Child继承于Base1,Base2,Base3,...
mro[Child]
= [Child] + merge(mro(Base1), mro(Base2), mro(Base3), ...,[Base1, Base2, Base3,...])

计算结果为一个列表,列表中至少有一个元素类,即本类Child。

merge是C3算法的核心。

merge操作:

表头:列表的第一个元素

表尾:列表表头以外的元素集合(可为空)

如计算merge( [E,O], [C,E,F,O], [C] )
有三个列表 :  ①     ②         ③

1 merge不为空,取出列表①的表头E,判断
(E是否在这些表尾的集合中,在>>跳过,不在>>取出并从所有表头中删除) 各个列表的表尾分别是[O], [E,F,O],[],E在这些表尾的集合中,因而跳过当前列表
2 取出列表②的表头C,进行判断 C不在各个列表表尾的集合中,因而将C拿出到merge外,并从所有表头删除 merge( [E,O], [C,E,F,O], [C]) = [C] + merge( [E,O], [E,F,O] ) 3 进行下一次新的merge操作 ......

示例:

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] )  # 单继承mro(D(O))=[D,O]
         = [B,D] + merge( [O] , [E,O]  ,  [E] )  # 拿出并删除D
         = [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] )  # 跳过O,拿出并删除
         = [C,E,F] + merge([O] ,  [O])
         = [C,E,F,O]

原式= [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
    = [A,B,D,C] + merge([E,O],  [E,F,O])
    = [A,B,D,C,E] + merge([O],    [F,O])  # 跳过O
    = [A,B,D,C,E,F] + merge([O],    [O])
    = [A,B,D,C,E,F,O]
---------------------
View Code

 

 

 

 

 

 

 

 

 

 

 

 

面向对象

posted on 2019-02-16 13:26  六月_海动  阅读(89)  评论(0)    收藏  举报