继承
通过继承创建的新类称为“子类”或“派生类”。
被继承的类称为“基类”、“父类”或“超类”。
# 父类 class A(object): def __init__(self): self.num = 10 def print_num(self): print(self.num + 10) # 子类 class B(A): pass b = B() print(b.num) b.print_num()
虽然子类没有定义__init__方法初始化属性,也没有定义实例方法,但是父类有。所以只要创建子类的对象,就默认执行了那个继承过来的__init__方法。
如果子类和父类的方法名和属性名相同,则默认使用子类的。叫 子类重写父类的同名方法和属性
1、单继承
- 子类在继承的时候,在定义类时,小括号()中为父类的名字
- 父类的属性、方法,会被继承给子类
子类继承了父类 就拥有了父类的"方法"和"属性"
子类拥有了父类的属性 是因为子类使用了父类的__init__(对属性赋值的地方)
class People: 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 taiking..."%self.name) def sleep(self): print("%s is sleeping..."%self.name) class Man(People): #直接继承 pass m1 = Man("haha",25) m1.eat()
class Man(People): def piao(self): print("%s is piaoing...20s...done"%self.name) m1 = Man("haha",25) m1.piao()
class Man(People): def sleep(self): #重写 print("man is sleeping") m1 = Man("haha",25) m1.sleep()
class Man(People): def sleep(self): #重构父类的方法 People.sleep(self) print("man is sleeping") m1 = Man("haha",25) m1.sleep()
两个子类之间不能互调
2、多继承
- 多继承可以继承多个父类,也继承了所有父类的属性和方法
- 注意:如果多个父类中有同名的 属性和方法,则默认使用第一个父类的属性和方法(根据类的魔法属性mro的顺序来查找)
- 多个父类中,不重名的属性和方法,不会有任何影响。
# 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 taiking..."%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) class Man(People,Relation): def __init__(self,name,age,money): #People.__init__(self,name,age) super(Man,self).__init__(name,age) #新式类的写法,和上面的作用一样,不用写多个People self.money = money print("%s 一出生就有%s money"%(self.name,self.money)) 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("haha",25,10) w1 = Woman("xixi",26) m1.make_friends(w1) print(m1.friends[0].name)
子类中调用父类的方法:
1、方式(单和多继承 都适用)
格式: 父类名.父类方法名(self)
2、方式 适用于新式类
格式: super(子类类名, self).父类方法名()
3、方式 (适用于新式类) 02方式的简写
格式: super().父类方法名()
super默认会调用第一个父类的方法(适用于单继承 或者只想使用第一个父类的方法)
继承顺序:
广度优先
class A: def __init__(self): print(("A")) class B(A): def __init__(self): print(("B")) class C(A): def __init__(self): print(("C")) class D(B,C): pass # D里面没有构造函数时,先走B,B没有走C,C没有走A obj = D()
python2里经典类是按深度优先来继承的(D里面没有构造函数时,先走B,B没有走A,A没有走C);新式类是按广度优先来继承的。
python3里经典类和新式类都是统一按广度优先来继承的。
继承实例:
class School(object): #object基类 def __init__(self,name,addr): self.name = name self.addr = addr self.student = [] self.staff = [] def enroll(self,stu_obj): print("为学员[%s] 办理注册手续"%(stu_obj.name)) self.student.append(stu_obj) def hire(self,staff_obj): self.staff.append(staff_obj) print("雇佣新员工%s"%(staff_obj.name)) class SchoolMember(object): def __init__(self,name,age,sex): self.name = name self.age = age self.sex = sex def tell(self): pass class Teacher(SchoolMember): def __init__(self,name,age,sex,salary,course): super(Teacher,self).__init__(name,age,sex) self.salary = salary self.course = course def tell(self): print(''' ----- info of Teacher:%s----- Name:%s Age:%s Sex:%s Salary:%s Course:%s '''%(self.name,self.name,self.age,self.sex,self.salary,self.course)) def teach(self): print("[%s] is teaching course [%s]" % (self.name,self.course)) class Student(SchoolMember): def __init__(self,name,age,sex,stu_id,grade): super(Student,self).__init__(name,age,sex) self.stu_id = stu_id self.grade = grade def tell(self): print(''' ----- info of Teacher:%s----- Name:%s Age:%s Sex:%s Stu_id:%s Grade:%s '''%(self.name,self.name,self.age,self.sex,self.stu_id,self.grade)) def pay_tuition(self,amount): print("%s has paid tution for $%s"%(self.name,amount)) school = School('老男孩IT','沙河') t1 = Teacher("Oldboy",56,"M",200000,"Linux") t2 = Teacher("Alex",28,"M",3000,"PythonDevOps") s1 = Student("haha",22,'M',10001,'PythonDevOps') s2 = Student("xixi",23,'w',10002,'Linux') t1.tell() s1.tell() school.hire(t1) school.enroll(s1) school.enroll(s2) school.staff[0].teach() for stu in school.student: stu.pay_tuition(5000)
多态
一种接口,多种实现
多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
那么,多态的作用是什么呢?我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了--代码重用。而多态则是为了实现另一个目的--接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。
python不直接支持多态,但可以间接实现
Python的多态,就是弱化类型,重点在于对象参数是否有指定的属性和方法,如果有就认定合适,而不关心对象的类型是否正确。
class Animal(object): def __init__(self,name): self.name = name def talk(self): pass @staticmethod def animal_talk(obj): obj.talk() class Cat(Animal): def talk(self): print('Meow!') class Dog(Animal): def talk(self): print('Woof!woof!') d = Dog("haha") # d.talk() c = Cat("xixi") # c.talk() Animal.animal_talk(d) # Woof!woof! Animal.animal_talk(c) # Meow!
class Person(object): def __init__(self): self.name = "小明" self.age = 20 def eat(self): print("肯德基") print("="*10) class Dog(object): def __init__(self): self.name = "旺财" self.age = 2 def eat(self): print("啃骨头") print("="*10) xiaoming = Person() # print(xiaoming.name) # print(xiaoming.age) # xiaoming.eat() xiaohong = Person() # print(xiaohong.name) # print(xiaohong.age) # xiaohong.eat() # 函数(object 为使用Person创建出来的对象服务的) def my_print(object): # python中不关心函数(方法)中参数的类型 只要这个参数有这个属性或者这个方法 就可以使用 print(object.name) print(object.age) object.eat() my_print(xiaoming) my_print(xiaohong) # 狗对象 wangcai = Dog() my_print(wangcai) # 多态的好处? # 给函数或者方法 增加的扩展性 和 提高开发效率
完