您的位置:首页 > 其它

20201222-1 类的继承2

2021-04-16 23:41 74 查看
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 = agedef 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 即可
还有一种其他的方法可以调用父类,另一种方式,叫做 superclass People:def __init__(self,name,age):
        self.name = name    # 等号两边的 name 变量名可以不一致,比如 self.NAme = name; name 是(self,name,age)中的参数名,NAme 是赋的变量名self.age = agedef 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 = agedef 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 = agedef 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",因为传的只是一个字符串,并没有真的关联# 真正要传的是 w1def 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 = agedef 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 = agedef 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 = agedef 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 n2class People(object):  # 新式类def __init__(self,name,age):
        self.name = name    
        self.age = agedef 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 是字符串

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: