一、继承【重点掌握】
1.概念
如果两个或者两个以上的类具有相同的属性和方法,我们可以抽取一个类出来,在抽取出来的类中声明各个类公共的部分
被抽取出来的类——父类【father class】 超类【super class】 基类【base class】
两个或两个以上的类——子类 派生类
他们之间的关系——子类 继承自 父类 或者 父类 派生了 子类
# 父类【Father】、超类【Super】、基类【Base】
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def eat(self):
print("eating")
# 子类、派生类
class Student(Person):
def __init__(self,name,age,type):
self.type = type
def study(self):
print("studying")
class Worker(Person):
def __init__(self,name,age,kind):
self.kind = kind
def work(self):
print("working")
class Doctor(Person):
pass
class Teacher(Person):
def teach(self):
print("teaching")
"""
总结:
1.如果要实现继承,则定义子类的时候,class 子类类名(父类类名)
2.object是所有类的根类
3.使用继承之后,可以简化代码
4.子类除了可以继承父类中的内容之外,还可以有自己特有的属性和方法,达到了易于扩展的特点
"""
2.单继承
2.1基本使用
简单来说,一个子类只有一个父类,被称为单继承
语法:
class 子类类名(父类类名):
类体
注意:object是Python中所有类的根类
默认情况下,如果一个类没有指明继承的父类,则默认继承自object
# 父类【Father】、超类【Super】、基类【Base】
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def eat(self):
print("eating")
# 子类、派生类
class Doctor(Person):
pass
# 1.注意1:如果子类中未定义构造函数,创建子类对象,默认调用父类中的构造函数,所以需要和父类中的__init__注意参数的匹配
d = Doctor("张医生",30)
d.eat()
print(d.name,d.age)
# 注意2:子类可以继承父类中未被私有化的属性和函数
# 2.
class Teacher(Person):
def teach(self):
print("teaching")
t = Teacher("王老师",40)
t.eat()
t.teach()
# 3.注意3:如果子类中定义了构造函数,则创建子类对象的时候,调用的是子类中的构造函数
class Student(Person):
def __init__(self,type):
self.type = type
def study(self):
print("studying")
s = Student("中学生")
print(s.type)
s.eat()
s.study()
# 4.在实际应用中,常用的情况【重点掌握】
# 注意4:如果子类中定义了构造函数,其中需要继承父类中的属性,并定义了特有的属性,
# 需要在子类的构造函数中调用父类中的构造函数
class Worker(Person):
def __init__(self,name,age,kind):
# 方式一:super(当前类,self).__init__(属性列表)
# super(Worker, self).__init__(name,age)
# 方式二:super().__init__(属性列表)
# super().__init__(name,age)
# 方式三:父类类名.__init__(self,属性列表)
Person.__init__(self,name,age)
self.kind = kind
def work(self):
print("working")
w = Worker('工人',25,"电器")
print(w.kind)
print(w.name,w.age)
w.eat()
w.work()
2.2继承中的slots
class Person(object):
__slots__ = ("name","age")
def __init__(self,name,age):
self.name = name
self.age = age
p = Person('aaa',10)
# p.hobby = "唱歌"
class Student(Person):
pass
s = Student("bbb",20)
print(s.name,s.age)
s.hobby = "跳舞"
print(s.hobby)
# 结论:在父类中定义的属性的限制绑定【__slots__】,不会被子类继承,如果同样需要,则需要手动设置
2.3继承中的类属性
# 1
class Person():
place = "地球"
class Student(Person):
pass
# 注意1:子类可以继承父类中未被私有化的类属性,使用和实例属性相同
print(Person.place)
print(Student.place)
# 注意2:如果通过父类修改类属性,子类中访问到的类属性会随着修改
Person.place = "火星"
print(Person.place)
print(Student.place)
# 注意3:如果通过子类修改类属性【来自于父类】,对父类中访问的类属性没有影响
Student.place = "太空"
print(Person.place)
print(Student.place)
# 2.【面试题】
class A():
x = 1
class B(A):
pass
class C(A):
pass
print(A.x,B.x,C.x) # 1 1 1
A.x = 2
print(A.x,B.x,C.x) # 2 2 2
B.x = 3
print(A.x,B.x,C.x) # 2 3 2
3.多继承
顾名思义,多继承就是一个子类可以有多个父类,比如:一个孩子有一个父亲,一个母亲
语法:
class 子类(父类1, 父类2, 父类3。。。。):
类体
注意:object是所有类的根类
# 1.
class Runnale(object):
def run(self):
print("running")
class Flyable(object):
def fly(self):
print("flying")
# 单继承
class Dog(Runnale):
pass
# 多继承
class Bird(Runnale,Flyable):
pass
# 2.
class Father(object):
def __init__(self,money):
self.money = money
def play(self):
print("playing")
def show(self):
print("father~~~~show")
class Mother(object):
def __init__(self,face_value):
self.face_value = face_value
def eat(self):
print("eating")
def show(self):
print("mother~~~~show")
# a.
class Child1(Mother,Father):
pass
# 注意1:子类中未定义构造函数,创建子类对象的时候,默认调用父类列表中第一个父类中的构造函数
# c1 = Child1(10)
# print(c1.face_value)
# b.
class Child2(Mother,Father):
def __init__(self,money,face_value,hobby):
# 注意2:和单继承的使用相同,如果在子类中需要使用父类中的实例属性,则在子类的构造函数中调用父类中的构造函数
# 注意3:在子类的构造函数中调用父类中的构造函数,使用super()都只能调用父类列表中第一个父类中的构造函数
# 如果所有父类的构造函数都需要调用,只能使用 父类类名.__init__(self,属性列表)
Father.__init__(self, money)
Mother.__init__(self, face_value)
self.hobby = hobby
def study(self):
print("studying")
# 扩展性
def show(self):
# super().show() # 只会调用的是父类列表中第一个父类中的函数
Father.show(self)
Mother.show(self)
print("child~~~~~show")
c2 = Child2(13,45,'跑步')
c2.play()
c2.eat()
c2.study()
print(c2.money,c2.face_value,c2.hobby)
# 注意4:如果多个父类中出现了重名的函数,子类对象在调用的时候,默认调用的是父类列表中第一个父类中的函数
c2.show()
4.多继承的特点
二、函数重写【重点掌握】
"""
函数重写:override
前提:在继承的情况下
使用:如果在子类中重新实现了父类中的函数,这个过程被称为函数的重写
判断标准:只要子类中出现和父类中重名的函数,换句话说,子类中某个函数的声明和父类中某个函数的声明完全相同,就是重写,
"""
# 1.自定义函数的重写
# a
class Person():
def func(self):
print("父类~~~~func")
class Child(Person):
pass
c = Child()
c.func()
# b
class Person():
def func(self):
print("父类~~~~func")
class Child(Person):
def func(self):
print("子类~~~~func")
c = Child()
c.func()
# c.注意:当一个父类有多个子类的时候,父类中实现的函数满足大多数子类的使用,只有少数子类中无法使用,
# 则可以在子类中重新实现父类中的指定函数
class Animal():
def walk(self):
print("地面行走")
class Dog(Animal):
pass
class Cat(Animal):
pass
class Bird(Animal):
def walk(self):
print("天空中飞行")
class Elephant(Animal):
pass
# 2.系统函数的重写
# a.
class Person1(object):
def __init__(self,name,age):
self.name = name
self.age = age
# 默认情况下,打印对象的时候,会调用object中的__str__(),该函数默认返回一个表示当前对象地址的字符串
p1 = Person1('张三',10)
print(p1)
print(p1.__str__())
# b.
class Person2(object):
def __init__(self,name,age):
self.name = name
self.age = age
# 如果希望打印对象的时候,获取的结果是当前对象的属性信息,则需要在子类中重写__str__,
# 该函数只能返回一个字符串,所以建议将对象的属性信息格式化成一个字符串返回
def __str__(self):
return f"姓名:{self.name},年龄:{self.age}"
# def __repr__(self):
# return f"姓名:{self.name},年龄:{self.age}"
__repr__ = __str__
p2 = Person2('张三',10)
print(p2)
# print(p2.__str__())
# 如果对象以元素的形式存在于列表等可迭代对象中,直接打印可迭代对象,默认情况下,该对象还是以地址的形式出现
# 如果列表中也需要显示属性信息,则需要重写__repr__
list1 = [p2]
print(list1)