Python基础---面向对象2

事物之间都会存在一些相对应的关系,在面向对象中,类与类之间存在着以下关系:

  依赖关系

  关联,组合,聚合关系,

  实现关系,继承关系

01.依赖关系:

  将一个类的类名或对象传入到另一个类的方法中

例1. 设计一个场景:把大象装进冰箱,这个场景中存在两个事物,一个是大象,另一个是冰箱

class Elephant:
    def __init__(self,name):
        self.name = name
    def open(self,obj):
        print('%s说:开门'%(self.name))
     obj.be_opened()  
def close(self,obj): print('%s说:关门'%(self.name))
     obj.be_closed()
class Refrigerator: def __init__(self,name): self.name = name def be_opened(self): print('%s被打开了'%(self.name)) def be_closed(self): print('%s被关闭了'%(self.name)) ele_obj = Elephant('猛犸') haier = Refrigerator('海尔') xinfei = Refrigerator('新飞')
                        # 将冰箱类的实例化对象,传到大象类的方法中
ele_obj.open(haier)
ele_obj.close(haier)

02.组合关系:

  组合:将一个类的对象或类名,封装到另一个类的对象的属性中

例2. 设计一个场景,男女朋友

class Boy:
    def __init__(self,name,gf = None):
        self.name = name
        self.gf = gf
    def have_dinner(self):
        if self.gf:
            print('%s和女朋友%s一起共度晚餐'%(self.name,self.gf.name))
        else:
            print('%s自己一个玩'%(self.name))
class Girl:
    def __init__(self,name):
        self.name = name


allen = Boy('allen')
ruhua = Girl('如花')
allen.gf = ruhua              # self.gf 拿到的是一个内存地址
allen.have_dinner()            # allen和女朋友如花一起共进晚餐

例3. 游戏人物相互攻击

class GameRole:
    def __init__(self,name,ad,hp):
        self.name = name
        self.ad = ad
        self.hp = hp
    def equipment(self,wea):
        self.wea = wea        # 给人物对象封装一个属性,这个属性是武器类的实例化对象
class Weapon:
    def __init__(self,name,ad):
        self.name = name
        self.ad = ad
    def wea_attack(self,p1,p2):
        p2.hp -= p1.ad+self.ad
        print('%s用%s攻击了%s,%s掉了%s血,还有%s血'%
              (p1.name, self.name, p2.name, p2.name,p1.ad+self.ad, p2.hp ))
# 实例化人物对象
yasuo
= GameRole('亚索',20,200) mumu = GameRole('木木',10,200) # 实例化武器对象 sword = Weapon('太刀',10) hammer = Weapon('锤子',10) # 给人物封装武器属性 yasuo.wea = sword mumu.wea = hammer yasuo.wea.wea_attack(yasuo,mumu) mumu.wea.wea_attack(mumu.attack)

03.继承关系:

 3.1.单继承

  3.1.1通过类名或对象执行父类方法:

class Animal:
    type_name = '动物类'    
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def eat(self):
        print('in Animal eat')
class Person(Animal):
    pass
1.执行父类方法
# 类名调用:
print(Person.eat(123))
print(Person.type_name)
# 对象调用:
obj = Person('小一',18,'')
obj.eat()                # in Animal eat
obj.type_name = '123'
print(obj.__dict__)                # {'name':'小一','age':18,'sex':男,'type_name':'123'}

执行步骤:

  (1)实例化对象obj,执行__init__方法,子类空间没有,就去父类空间找,父类空间如果没有,就继续往上找(python3中的父类默认为object)

  (2)obj.eat(),先执行子类空间中的eat方法,没有就去父类空间中找

  3.1.2同时执行子类和父类的方法:

class Animal:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def func(self):
        print('in Animal func')
class Person(Animal):
    def func():
        Animal.func(self)        # 类名.方法名时,必须要传参
        super().func()           # super方法,func()中不用传参数
        print('in Person func') 
p1 = Person('小一',18)
p1.func()                in Animal func  in Person func

  3.1.3同时执行子类和父类的__init__方法:

class Animal:
    def __init__(self,name,age):
        self.name = name
        self.age = age
class Person(Animal):
    def __init__(self,name,age,sex):
        Animal.__init__(self,name,age)
        super().__init__(name,age)
        self.sex = sex
p1 = Person('小一',18,'')
print(p1.__dict__)            {'name':'小一','age':18,'sex':'男'}

  3.1.4 super( )方法:

    完全按照对象所在类的mro顺序执行,在多继承中,super(指定类名,self).方法名(),super中指定的类会被跳过,执行mro的下一个顺序的类的方法

class A:
    def func1(self):
        print('in A func1')
class B(A):
    def func1(self):
        super(B, self).func1()        跳过B,执行C
        print('in B func1')
class C(A):
    def func1(self):
       print('in C func1')
class D(B,C):
    def func1(self):
        super(D, self).func1()       跳过D,执行B
        print('in D func1')
obj = D()
obj.func1()
print(D.mro())                    继承顺序:D.B.C.A

 3.2多继承

  3.2.1 python中类的分类: 经典类,新式类

    py2x版本中: py2.2之前只有经典类,不继承object类,遵循的是深度优先原则,从左至右一条路走到黑

    py2.2之后,出现新式类,继承object类,遵循C3算法,mro顺序

    py3x版本中: 所有的类都默认继承object类

  3.2.2 经典类的多继承:

    深度优先原则,从左至右一条路走到黑

   mro顺序: Foo --> H --> G --> F --> E --> D --> B --> A --> C

  3.2.3 新式类的多继承: 当两个父类出现了重名的方法时,遵循C3算法,mro顺序

  (1)mro序列: 是一个有序的列表,在类被创建时就会计算出来

    通用公式为:mro(Child(Base1,Base2)) = [Child] + merge(mro(Base1),mro(Base2),[Base1,Base2])

  (2)继承至一个基类: classB(A)

mro(B) = mro(B(A)) = [B] + merge(mro(A),[A]) = [B] + merge([A]+[A]) = [B,A]

  (3)继承至多个基类: classB(A1,A2,A3...)

mro(B) = merge(B(A1,A2,A3...))
= [B] + merge(mro(A1),mro(A2),mro(A2)...[A1,A2,A3...]) 
= ...

  (4)表头和表尾: 

    表头: 列表的第一个元素

    表尾: 除第一个元素外其他元素

如计算merge( [E,O], [C,E,F,O], [C] )
              1        2       3
01.merge不为空,取出第一个列表列表1的表头E,进行判断                              
   各个列表的表尾分别是[O], [E,F,O],E在这些表尾的集合中,因而跳过当前当前列表
02.取出列表2的表头C,进行判断
   C不在各个列表的集合中,因而将C拿出到merge外,并从所有表头删除

merge( [E,O], [C,E,F,O], [C] ) = [C] + merge( [E,O], [E,F,O])
03.进行下一次新的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])
       = [B] + [D] + merge([O],[E,O],[E])
       = [B,D,E] + merge([O]) = [B,D,E,O]
mro(C) = mro(C(E,F)) = [C,E,F,O]
mro(A) = [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]

4.面向对象的三大特性:封装,继承,多态

  封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式。

优点:便于使用,提高复用性和安全性

  继承:可以使子类具有父类的各种属性和方法,而且不需要再次编写相同的代码,在子类继承父类的同时,可以重新定义某些属性,重写某些方法,即覆盖父类中原有的属性和方法,使子类具有不同于父类的功能,此外,给子类追加新的属性和方法也是很常见的做法.

继承的优点: 增强代码的耦合性,减少重复代码,使代码更加规范化,合理化

  多态:指一类事物有多种形态.python默认支持多态,一个变量可以是多种数据类型

   鸭子类型: 如果看起来是鸭子,那它就是鸭子,两个类虽没有任何关系,但隐形中遵循了一个标准

   优点:1.统一标准,减少了词汇量,建立了一种弱关联;2.两个类没有任何的耦合性,但是可以产生关系,A的对象会使用B类的方法

posted @ 2019-02-14 21:52  DF-包子  阅读(197)  评论(0编辑  收藏  举报