zoukankan      html  css  js  c++  java
  • 类与类的关系

    从类空间与对象空间的角度研究类

    给对象封装属性:

    1.在__init__中

    2.在类的外部

    3.在类的其他方法中

    给一个类添加属性:

    1.类的外部

    2.类的内部

    class A:
        def __init__(self,name,age):
            self.name = name
            self.age = age
        def func(self,sex):
            self.sex = sex
        def func1(self):
            A.country = '中国'
    
    #给对象添加属性:
    obj = A('barry',18)           #在__init__中添加属性
    obj.height = 176              #在类的外面添加属性
    obj.func('')                #在类的方法中添加属性
    print(obj.__dict__)
    
    #给类添加属性:
    A.count = 666                  #在类的外部
    obj.func1()                    #在类的内部

    类对象指针(对象空间):

    对象找属性顺序:对象空间--类空间--父类空间

    类指针(累空间):

    类找属性顺序:类空间--父类空间

    以上顺序单向不可逆

    类与类的关系

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

    class Elephant:                                     #大象类
        def __init__(self,name):
            self.name = name
        def open(self,ref):
            print('%s打开冰箱门'%(self.name))
            ref.beopen_door()
        def close(self,foo):
            print('%s关闭冰箱门'%(self.name))
            foo.beclosed_door()
    
    class Refrigerator:                                 #冰箱类
        def __init__(self,name):
            self.name = name
        def beopen_door(self):
            print('%s冰箱门被打开了'%(self.name))
        def beclosed_door(self):
            print('%s冰箱门被关闭了'%(self.name))
       
    ele = Elephant('猛犸')                          #实例化大象对象
    
    haier = Refrigerator('海尔')                    #实例化冰箱对象
    ele.open(haier)                                 #将冰箱对象传入大象类的方法中
    ele.close(haier)
    
    # gree = Refrigerator('格力')
    # ele.open(gree)
    # ele.close(gree)

    #大象是主体,可以选择冰箱,冰箱依赖于大象

    2.组合(关联,聚合)关系 : 将一个类的对象或者类名封装到另一个类的对象的属性中

    class Boy:
        def __init__(self,name,girlfriend=None):
            self.name = name
            self.girlfriend = girlfriend
        def dinner(self,ref):
            if self.girlfriend:
                print('%s和女朋友%s共进晚餐'%(self.name,ref.name))
            else:
                print('今晚吃鸡,大吉大利')
    
    class Girl:
        def __init__(self,name,boyfriend=None):
            self.name = name
            self.boyfriend = boyfriend
        def shopping(self,ref):
            if self.boyfriend:
                print('%s和男朋友%s一起逛街'%(self.name,ref.name))
            else:
                print('宅在家')
    
    # alex = Boy('alex')          #girlfiend 默认为None
    # alex.dinner()
    
    结果:
    今晚吃鸡,大吉大利                #执行else条件下语句
    
    # ruhua = Girl('如花')
    # alex.girlfriend = ruhua        #将ruhua这个对象传给girlfriend
    # alex.dinner()
    
    结果:
    alex和女朋友如花共进晚餐
    
    # jinlian = Girl('金莲')
    # wuda = Boy('武大',jinlian)       #将jinlian这个对象在一开始就传给girlfriend
    # wuda.dinner()
    
    结果:
    武大和女朋友金莲共进晚餐
    
    # wuda.girlfriend = None
    # wuda.dinner()                    #解除绑定
    
    结果:
    今晚吃鸡,大吉大利
    
    
    # alex = Boy('alex')
    # ruhua = Girl('如花')
    # ruhua.boyfriend = alex      #将alex这个对象传给boyfriend
    # ruhua.shopping()
    
    结果:
    如花和男朋友alex一起逛街

    3.继承(实现)关系 : 有父类和子类,子类可以继承调用父类的内容

    继承的好处:

    1.减少代码重复率

    2.让类与类产生关系,增强耦合性

    3.使代码更加规范化,清晰化

    在python3中,所有的类都默认继承父类 object

    单继承

    class Animal:
        live = '活着'
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
        def eat(self):
            print('动物都会吃')
    
    class Person(Animal):           #子类名(父类名)
        live = '无所谓'
    
    
    对象:
    p1 = Person('alex','',20)      #子类中没有,执行父类中的__init__
    p1.eat()                              #子类中没有,执行父类中的eat方法
    print(p1.live)                       #子类和父类中具有相同的属性,先调用自己类中的属性
    
    结果:
    无所谓
    
    
    #子类执行父类的属性和方法,也会将自己的地址传给self
    
    类名:
    Person.live      #自己类中有,调用自己类中的属性
    
    结果:
    无所谓

    对象既要执行子类的方法,又要执行父类的方法:

    1.在子类中写入 父类名.方法名(self,参数) 

    class Animal:
        live = '活着'
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
        def eat(self):
            print('动物都会吃')
    
    class Person(Animal):
        live = '无所谓'
        def eat(self):
            Animal.eat(self)            #父类名.方法名(self),手动将p1对象传给self
            print('人类都需要吃饭')

    2.在子类的方法中,写入 super().方法名(参数)  自动将子类的对象传入父类方法的self

    class Animal:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
        def eat(self):
            print('动物都会吃')
    
    class Person(Animal):
        def eat(self):
            super().eat()            #调用父类的eat方法,将p1对象自动传给父类eat方法中的self
            print('人类都需要吃饭')
    
    p1 = Person('alex','',20)  #自动调用父类的__init__方法进行传参
    p1.eat()
    
    结果:
    动物都会吃
    人类都需要吃饭

    在子类中封装另外的属性

    1.使用类名   不依赖继承

    class Animal:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = age
    
    class Person(Animal):
        def __init__(self,n,s,a,mind):
            # Animal.__init__(self,n,s,a)    #方法一:不依赖继承  类名后可以不加Animal
            self.mind = mind
    
    p1 = Person('邓哥','',18,'思想')

    2.super()    依赖继承

    class Animal:
        def __init__(self,name,sex,age):
            self.name = name
            self.sex = sex
            self.age = ageclass Cat(Animal):
        def __init__(self,n,s,a,climb):
            super().__init__(n,s,a)          #方法二:依赖继承
            self.climb = climb
    
    c1 = Cat('大橘','',4,'爬树')

     多继承

    多继承的顺序:从左到右

    类的分类:

    python2x版本:(python2.2之前,只有经典类,python2.2之后出现了新式类)

    经典类: 不继承object,多继承遵循深度优先

       深度优先:从左到右一条路走到底,没有再继续返回走下一条

    新式类 : 继承object的类,多继承遵循c3算法 mro方法查询继承顺序

    python3x版本:所有类都默认继承object  只有新式类

    mro序列

    表头和表尾:

    [A,B,C]   表头:A    表尾:B,C

    [A]         表头:A     表尾:空

    [A] +[B] = [A,B]

    merge里面的计算顺序(面试题):

    merge([A,O], [C,E,F,O],[C])               #将第一个列表的第一个元素A提取出来,判断这个元素在其他表尾中存不存在,不重复,就单独提取出来
    = [A] + merge([O], [C,E,F,O],[C])         #继续提取第一个元素O,跟第二个列表的表尾重复,不进行操作,继续找下一个列表的首个元素C进行判断
    = [A,C] + merge([O], [E,F,O])           
    = [A,C,E] + merge([O], [F,O])
    = [A,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
    
    obj = A()
    #按照merge的顺序,可以一步一步推算
    mro(A(B,C)) = [A] + merge(mro(B),mro(C),[B,C])                 #A继承B,C   计算A的继承顺序的固定格式 
    
    mro(B) = mro(B(D,E)) = [B] + merge(mro(D),mro(E),[D,E])        #B继承D,E
    mro(D(O)) = [D,O]                                              #D继承O
    mro(E(O)) = [E,O]                                              #E继承O
    
    mro(B(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继承E,F
    mro(C) = mro(C(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] 
                           
    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] + merge([O],[O])
                 = [A,B,D,C,E,F,O] 

    在python方法中,也可以直接输出打印:

    print(A.mro())    
    
    结果:[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.D'>, <class '__main__.C'>, <class '__main__.E'>, <class '__main__.F'>, <class '__main__.O'>, <class 'object'>]    

    #和上边计算的结果一样
  • 相关阅读:
    C#中关于@的用法
    c++ 中__declspec 的用法
    #pragma详细解释(一)
    memmove 和 memcpy的区别
    【niubi-job——一个分布式的任务调度框架】----安装教程
    [异能程序员]第一章 酒后事发(第一更)
    博客园的最后一篇博文,还是要离开了(附带个人博客源码分享)
    五一假期——技术之路上的坎儿
    deerlet-redis-client添加集群支持,邀请各路大神和菜鸟加入。
    从日常开发说起,浅谈HTTP协议是做什么的。
  • 原文地址:https://www.cnblogs.com/sandy-123/p/10320315.html
Copyright © 2011-2022 走看看