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 是字符串
  • 相关阅读:
    HTML DOM教程 14HTML DOM Document 对象
    HTML DOM教程 19HTML DOM Button 对象
    HTML DOM教程 22HTML DOM Form 对象
    HTML DOM教程 16HTML DOM Area 对象
    ubuntu 11.04 问题 小结
    VC6.0的 错误解决办法 小结
    boot.img的解包与打包
    shell里 截取字符串
    从零 使用vc
    Imagemagick 对图片 大小 和 格式的 调整
  • 原文地址:https://www.cnblogs.com/azxsdcv/p/14174816.html
Copyright © 2011-2022 走看看