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 是字符串