zoukankan      html  css  js  c++  java
  • 20201222-1 类的继承2

    1-1-1
    Man 在初始化时 可以多传入一个属性吗?
    可以在类 Man 下进行重构
    
    class People:
    
        def __init__(self,name,age):
            self.name = name    
            # 等号两边的 name 变量名可以不一致,比如 self.NAme = name; name 是(self,name,age)中的参数名,NAme 是赋的变量名
            self.age = age
    
        def eat(self):
            print("%s is eating..."%self.name)
        def talk(self):
            print("%s is talking..."%self.name)
        def sleep(self):
            print("%s is sleeping..."%self.name)
        
    class Man(People):
        # def __init__ 这个动作相当于完全重构,会覆盖
        # 这样用户实例化时,不会调用父类,将直接调用这里的 def __init__
        # 这样需要重新写一遍参数
        def __init__(self,name,age,money):
            People.__init__(self,name,age) # self.name 和 age 在父类中实现
            self.money = money             # 新增功能 money 在子类中实现
            print("%s 一出生就有%s money"%(self.name,self.money))
    
        def piao(self):
            print("%s is piaoing.....20s......done."%self.name)
        def sleep(self):
            People.sleep(self)      
            print("man is sleeping")
    
    class Woman(People):
        def get_birth(self):
            print("%s is born a baby...."%self.name)
            
    m1 = Man("NiuHanYang",222,10)       # 这样就需要 传入 money   
    m1.eat()
    m1.piao()
    m1.sleep()
    
    w1 = Woman("ChenRonghua",26)
    w1.get_birth()
    --->
    NiuHanYang 一出生就有 10 money
    NiuHanYang is eating...
    NiuHanYang is piaoing.....20s......done.
    NiuHanYang is sleeping...
    man is sleeping
    ChenRonghua is born a baby....
    
    这就是对 构造函数 进行重构
    父类的参数都要写一遍,因为用户调用时,不是调用父类,是在调用初始化构造函数
    写完后,加入新增的属性,这时候就与父类无关了
    注:没有高级方法,只可以这样写
    1-1-2
    父类通常不会有很多参数,不固定的加 *args 即可
    还有一种其他的方法可以调用父类,另一种方式,叫做 super
    class People:
    
        def __init__(self,name,age):
            self.name = name    
            # 等号两边的 name 变量名可以不一致,比如 self.NAme = name; name 是(self,name,age)中的参数名,NAme 是赋的变量名
            self.age = age
    
        def eat(self):
            print("%s is eating..."%self.name)
        def talk(self):
            print("%s is talking..."%self.name)
        def sleep(self):
            print("%s is sleeping..."%self.name)
        
    class Man(People):
        def __init__(self,name,age,money):
            # People.__init__(self,name,age) # self.name 和 age 在父类中实现
            super(Man,self).__init__(name,age)
            # super(Man,self).__init__(name,age) 这种写法与 People.__init__(self,name,age) 是完全一样的 
            # super 的作用就是 继承父类的 构造函数      
            self.money = money         
            print("%s 一出生就有%s money"%(self.name,self.money))
    
        def piao(self):
            print("%s is piaoing.....20s......done."%self.name)
        def sleep(self):
            People.sleep(self)      
            print("man is sleeping")
    
    class Woman(People):
        def get_birth(self):
            print("%s is born a baby...."%self.name)
            
    m1 = Man("NiuHanYang",222,10)       # 这样就需要 传入 money   
    m1.eat()
    m1.piao()
    m1.sleep()
    
    w1 = Woman("ChenRonghua",26)
    w1.get_birth()
    --->
    NiuHanYang 一出生就有10 money
    NiuHanYang is eating...
    NiuHanYang is piaoing.....20s......done.
    NiuHanYang is sleeping...
    man is sleeping
    ChenRonghua is born a baby....
    1-1-3
    既然 super(Man,self).__init__(name,age) 这种写法与 People.__init__(self,name,age) 是完全一样的
    为什么还会有 super 呢?
    super 没有写 People,这样以后修改父类名称时,super 无需修改
    如果有多个子类,无需修改多个子类中的 "People" 
    
    类可以进行多继承,比如:
    class Man(People,Animal):
        def __init__(self,name,age,money):
            People.__init__(self,name,age)
            Animal.__init__(self,name,age)
            # 如果用 super 就会变得方便,直接多继承了
            super(Man,self).__init__(name,age)
    1-1-4 
    其实还有一个地方可以改进,其实标准的写法如下:
    # 好比 python 2.7 和 3.0; 新式类中多了一些升级
    # class People: 经典类
    class People(object):  # 新式类
        def __init__(self,name,age):
            self.name = name    
            # 等号两边的 name 变量名可以不一致,比如 self.NAme = name; name 是(self,name,age)中的参数名,NAme 是赋的变量名
            self.age = age
    
        def eat(self):
            print("%s is eating..."%self.name)
        def talk(self):
            print("%s is talking..."%self.name)
        def sleep(self):
            print("%s is sleeping..."%self.name)
        
    class Man(People):
        def __init__(self,name,age,money):
            # People.__init__(self,name,age) # self.name 和 age 在父类中实现
            super(Man,self).__init__(name,age)
            # super(Man,self).__init__(name,age) 这种写法与 People.__init__(self,name,age) 是完全一样的 
            # super 的作用就是 继承父类的 构造函数      
            self.money = money         
            print("%s 一出生就有%s money"%(self.name,self.money))
    
        def piao(self):
            print("%s is piaoing.....20s......done."%self.name)
        def sleep(self):
            People.sleep(self)      
            print("man is sleeping")
    
    class Woman(People):
        def get_birth(self):
            print("%s is born a baby...."%self.name)
            
    m1 = Man("NiuHanYang",222,10)       # 这样就需要 传入 money   
    m1.eat()
    m1.piao()
    m1.sleep()
    
    w1 = Woman("ChenRonghua",26)
    w1.get_birth()
    
    我们只需要关心,新式类多继承的方式变了
    在继承上,新式类和经典类是有明显不同的
    super(Man,self).__init__(name,age) 是新式类的写法
    People.__init__(self,name,age) 是经典类的写法
    1-2
    经典类和新式类的变化,主要体现在继承上
    首先需要了解多继承,才可以知道区别在哪里
    不是所有语言都支持多继承,比如 java 就是不支持的
    
    # 现在有一个 People,添加一个关系类
    class People(object):  # 新式类
        def __init__(self,name,age):
            self.name = name    
            # 等号两边的 name 变量名可以不一致,比如 self.NAme = name; name 是(self,name,age)中的参数名,NAme 是赋的变量名
            self.age = age
    
        def eat(self):
            print("%s is eating..."%self.name)
        def talk(self):
            print("%s is talking..."%self.name)
        def sleep(self):
            print("%s is sleeping..."%self.name)
    
    class Relation(object):
        # 结果生成两个人,调用的是 m1 的 friends;得有交朋友的对象,所以obj就是w1
        # 为什么这地方写的是 obj 而不是 "chenronghua",因为传的只是一个字符串,并没有真的关联
        # 真正要传的是 w1
        def make_friends(self,obj):
            print("%s is making friends with %s"%(self.name,obj.name))
    
    # 在男人这里直接继承 Relation    
    class Man(People,Relation):
        def __init__(self,name,age,money):
            # People.__init__(self,name,age) # self.name 和 age 在父类中实现
            super(Man,self).__init__(name,age)
            # super(Man,self).__init__(name,age) 这种写法与 People.__init__(self,name,age) 是完全一样的 
            # super 的作用就是 继承父类的 构造函数      
            self.money = money         
            print("%s 一出生就有%s money"%(self.name,self.money))
    
        def piao(self):
            print("%s is piaoing.....20s......done."%self.name)
        def sleep(self):
            People.sleep(self)      
            print("man is sleeping")
    # 在Woman这里也继承 Relation;多写一个就是多继承一个
    class Woman(People,Relation):
        def get_birth(self):
            print("%s is born a baby...."%self.name)
            
    m1 = Man("NiuHanYang",222,10)       # 这样就需要 传入 money   
    # 既然继承了,就代表可以用 Relation 里的方法
    w1 = Woman("ChenRonghua",26)
    m1.make_friends(w1)
    --->
    NiuHanYang 一出生就有10 money
    NiuHanYang is making friends with ChenRonghua
    
    这样就可以多继承了
    这个 Relation 并没有写构造函数,也没有传参数,为什么就可以直接 .name了呢?
    在继承父类时,name就已经传进去了,名字已经有了,所以不需要在继承一遍
    只需要把额外的需要继承的功能填进去就可以了
    自己已经有一些功能了,在添加一些新功能还是给自己添加,所以Relation中,可以 self.name,因为已经有名字了
    1-2-1
    这是因为 People 类中,已经先有名字了吗?
    如果调用 People 和 Relation 的顺序呢?
    class People(object):  # 新式类
        def __init__(self,name,age):
            self.name = name    
            # 等号两边的 name 变量名可以不一致,比如 self.NAme = name; name 是(self,name,age)中的参数名,NAme 是赋的变量名
            self.age = age
    
        def eat(self):
            print("%s is eating..."%self.name)
        def talk(self):
            print("%s is talking..."%self.name)
        def sleep(self):
            print("%s is sleeping..."%self.name)
    
    class Relation(object):
        def make_friends(self,obj):
            print("%s is making friends with %s"%(self.name,obj.name))
    
    # 在男人这里直接继承 Relation    
    class Man(Relation,People):
        def __init__(self,name,age,money):
            # People.__init__(self,name,age) # self.name 和 age 在父类中实现
            super(Man,self).__init__(name,age)
            # super(Man,self).__init__(name,age) 这种写法与 People.__init__(self,name,age) 是完全一样的 
            # super 的作用就是 继承父类的 构造函数      
            self.money = money         
            print("%s 一出生就有%s money"%(self.name,self.money))
    
        def piao(self):
            print("%s is piaoing.....20s......done."%self.name)
        def sleep(self):
            People.sleep(self)      
            print("man is sleeping")
    # 在Woman这里也继承 Relation;多写一个就是多继承一个
    class Woman(People,Relation):
        def get_birth(self):
            print("%s is born a baby...."%self.name)
            
    m1 = Man("NiuHanYang",222,10)       # 这样就需要 传入 money   
    # 既然继承了,就代表可以用 Relation 里的方法
    w1 = Woman("ChenRonghua",26)
    m1.make_friends(w1)
    --->
    NiuHanYang 一出生就有10 money
    NiuHanYang is making friends with ChenRonghua
    
    # 结果依然是成立的
    # 不过,class Man(Relation,People), Relation 和 People 的放置顺序,其实是有关系的
    # 真正生成名字,不是在People里生成的,是在 Man 中构造时 生成的
    # 本来要继承父类的 __init__ ;但是 Man 自己有 __init__ 了,所以就不执行父类的了,这里执行的是自己的
    # 所以是先执行了自己的 __init__ 之后,由执行了父类的方法
    # 所以,name就已经有了
    1-2-2
    如果Man没有自己的构造方法呢?这时就需要寻找父类的构造方法
    类Man 先 Relation,后 People 能否找到呢?
    class People(object):  # 新式类
        def __init__(self,name,age):
            self.name = name    
            self.age = age
        def eat(self):
            print("%s is eating..."%self.name)
        def talk(self):
            print("%s is talking..."%self.name)
        def sleep(self):
            print("%s is sleeping..."%self.name)
    
    class Relation(object):
        def make_friends(self,obj):
            print("%s is making friends with %s"%(self.name,obj.name))
     
    class Man(Relation,People):
        def piao(self):
            print("%s is piaoing.....20s......done."%self.name)
        def sleep(self):
            People.sleep(self)      
            print("man is sleeping")
    
    class Woman(People,Relation):
        def get_birth(self):
            print("%s is born a baby...."%self.name)
            
    m1 = Man("NiuHanYang",222)       
    w1 = Woman("ChenRonghua",26)
    m1.make_friends(w1)
    --->
    NiuHanYang is making friends with ChenRonghua
    
    结果依然没有报错,为什么?
    因为 Man 没有构造方法,实例化时会找父类,先找到了 Relation,Relation中没有构造方法,为什么没有报错?
    因为 Relation 中的 make_friends 方法还没有执行,没执行所以没问题
    1-2-3
    可以进行验证
    class People(object):  # 新式类
        def __init__(self,name,age):
            self.name = name    
            self.age = age
        def eat(self):
            print("%s is eating..."%self.name)
        def talk(self):
            print("%s is talking..."%self.name)
        def sleep(self):
            print("%s is sleeping..."%self.name)
    
    class Relation(object):
        def __init__(self):
            print(self.name)
        # 验证,是不是按照从左到右的顺序执行的,如果是从左到右执行的,是会报错的
        def make_friends(self,obj):
            print("%s is making friends with %s"%(self.name,obj.name))
     
    class Man(Relation,People):
        def piao(self):
            print("%s is piaoing.....20s......done."%self.name)
        def sleep(self):
            People.sleep(self)      
            print("man is sleeping")
    
    class Woman(People,Relation):
        def get_birth(self):
            print("%s is born a baby...."%self.name)
            
    m1 = Man("NiuHanYang",222)       
    w1 = Woman("ChenRonghua",26)
    m1.make_friends(w1)
    --->
    TypeError: __init__() takes 1 positional argument but 3 were given
    报错中说,传了三个参数,虽然继承了父类,但是子类需要传参数
    class Relation(object):
        def __init__(self):
            print(self.name)
    里面必须接收参数
    1-2-4
    所以传入两个参数 n1 n2
    class People(object):  # 新式类
        def __init__(self,name,age):
            self.name = name    
            self.age = age
        def eat(self):
            print("%s is eating..."%self.name)
        def talk(self):
            print("%s is talking..."%self.name)
        def sleep(self):
            print("%s is sleeping..."%self.name)
    
    class Relation(object):
        def __init__(self,n1,n2):
            print(self.name)
        # 验证,是不是按照从左到右的顺序执行的,如果是从左到右执行的,是会报错的
        def make_friends(self,obj):
            print("%s is making friends with %s"%(self.name,obj.name))
     
    class Man(Relation,People):
        def piao(self):
            print("%s is piaoing.....20s......done."%self.name)
        def sleep(self):
            People.sleep(self)      
            print("man is sleeping")
    
    class Woman(People,Relation):
        def get_birth(self):
            print("%s is born a baby...."%self.name)
            
    m1 = Man("NiuHanYang",222)       
    w1 = Woman("ChenRonghua",26)
    m1.make_friends(w1)
    --->
    AttributeError: 'Man' object has no attribute 'name'
    这个时候报错说里面没有 name 
    所以,默认的执行顺序是 从左到右;这时左边还没有这个 name,所以就没有 name 
    1-3
    # class People: 经典类
    class People(object):  # 新式类
        def __init__(self,name,age):
            self.name = name    
            self.age = age
            self.friends = []   # 默认的朋友列表
    
        def eat(self):
            print("%s is eating..."%self.name)
        def talk(self):
            print("%s is talking..."%self.name)
        def sleep(self):
            print("%s is sleeping..."%self.name)
    
    class Relation(object):
        def make_friends(self,obj):
            print("%s is making friends with %s"%(self.name,obj.name))
            self.friends.append(obj)
    # 现在 Relation 和 People 没关系,通过子类继承才有关系
    # 这样加上 obj 两个人就真正联系起来了
    
    class Man(Relation,People):
        def __init__(self,name,age,money):
            # People.__init__(self,name,age) # self.name 和 age 在父类中实现
            super(Man,self).__init__(name,age)
            # super(Man,self).__init__(name,age) 这种写法与 People.__init__(self,name,age) 是完全一样的 
            # super 的作用就是 继承父类的 构造函数      
            self.money = money         
            print("%s 一出生就有%s money"%(self.name,self.money))
    
        def piao(self):
            print("%s is piaoing.....20s......done."%self.name)
        def sleep(self):
            People.sleep(self)      
            print("man is sleeping")
    
    class Woman(Relation,People):
        def get_birth(self):
            print("%s is born a baby...."%self.name)
            
    m1 = Man("NiuHanYang",222,10)       # 这样就需要 传入 money   
    w1 = Woman("ChenRonghua",26)
    
    m1.make_friends(w1)
    print(m1.friends)
    --->
    NiuHanYang 一出生就有10 money
    NiuHanYang is making friends with ChenRonghua
    [<__main__.Woman object at 0x0000021283609C08>]
    
    # obj.name 是字符串
  • 相关阅读:
    洛谷 P1213 时钟 &&IOI 1994 The Clocks
    P1457 城堡 The Castle
    [USACO08OCT]牧场散步Pasture Walking
    洛谷 P1262 间谍网络
    [USACO09DEC]牛收费路径Cow Toll Paths
    1266: [AHOI2006]上学路线route
    1093: [ZJOI2007]最大半连通子图
    洛谷 P3797 妖梦斩木棒
    1821: [JSOI2010]Group 部落划分 Group
    2019中国产业互联网领袖峰会(上海)
  • 原文地址:https://www.cnblogs.com/azxsdcv/p/14174816.html
Copyright © 2011-2022 走看看