一、继承
继承: 子类可以把父类的相关的方法和属性复制一份
# 继承就是在类的后面写上(父类)
# 1. 继承可以把父类的所有的属性和方法获取到
class Father:
# 类属性 因为他存放在类空间中 同时所有的对象都可以使用这个属性
name = "老王"
def dance(self):
print("广场舞")
class Son(Father):
pass
son = Son()
son.dance()
print(son.name)
- 单继承:只有一个父类
# 继承就是在类的后面写上(父类)
# 1. 继承可以把父类的所有的属性和方法获取到
class Father:
def __init__(self):
self.name = "老王"
def dance(self):
print("广场舞")
class Son(Father):
pass
son = Son()
son.dance()
father = Father()
print(id(son.name))
print(id(father.name))
- 多继承:有多个父类
"""
多继承就是有多个父类
1.如果多个父类中有不同的方法和属性就会被子类全部继承
2.如果有多个父类,并且父类中方法或者属性相同,那么就会使用先继承的父类的方法和属性
"""
class Father1:
name = '老王'
def dance(self):
print('广场舞')
class Father2:
name = '老李'
def dance(self):
print('扭秧歌')
class Son(Father1, Father2):
pass
son = Son()
son.dance()
print(son.name)
多继承:
- 如果多个父类的方法和属性都不相同
- 子类会把所有的不相同的方法和属性都继承下来
- 如果多个父类的方法和属性有相同的情况
- 子类会按照继承顺序, 先继承(father1, father2) father1的相关的方法和属性
二、子类重写父类的方法和属性
使用: 我们不会单一的只为了继承父类的属性和方法而继承, 子类会进行重写, 把和父类相同的方法名和属性名进行重写
# 继承可以在父类的基础上添加新方法和属性 进而可以省略写和父类相同方法和属性
# 方法的重写: 把和父类相同的方法的名字重新在子类里定义 这个时候我们使用的子类的方法的时候用的就是重写后的方法了
class Father:
def __init__(self):
self.name = "老王"
def dance(self):
print('广场舞')
def run(self):
print("走路")
class Son(Father):
def __init__(self):
Father.__init__(self)
self.name = "小王"
def sing(self):
print("唱歌")
def dance(self):
print('街舞')
son = Son()
son.dance()
son.run()
son.sing()
print(son.name)
三、子类调用父类的方法
两种方式:
父类名.父类方法()
# 子类调用父类的方法 直接使用父类名 父类方法就可以了
class Father:
def dance(self):
print('广场舞')
def run(self):
print("走路")
class Son(Father):
def sing(self):
print("唱歌")
def dance(self):
Father.dance(self)
print('街舞')
son = Son()
son.dance()
# son.run()
# son.sing()
super().方法名()
# super当继承关系非常复杂的时候, 我们可以使用super()方法
class Father1:
def dance(self):
print('广场舞1')
class Father2:
def dance(self):
print('广场舞2')
class Son(Father1, Father2):
def dance(self):
super().dance()
print('街舞')
print(Son.__mro__)
son = Son()
son.dance()
mro顺序表
类名.mro ==> 得到一个顺序表, 通过这个顺序表就可以获取super的调用情况
class Base:
def __init__(self):
print('Base.__init__')
class A(Base):
def __init__(self):
super().__init__()
print('A.__init__')
class B(Base):
def __init__(self):
super().__init__()
print('B.__init__')
class D(Base):
def __init__(self):
super().__init__()
print('D.__init__')
class C(A, D, B):
def __init__(self):
super().__init__()
print('C.__init__')
print(C.__mro__)
c = C()
super的两种使用方式
- A对象的 super().方法() : 直接从mro顺序表里找相应的方法进行调用,并且A作为起始位置
- A对象的 super(B,self).方法(): 直接直接从mro顺序表里找相应的方法进行调用,并且B作为起始位置
class Base:
def __init__(self):
print('Base.__init__')
class A(Base):
def __init__(self):
super().__init__()
print('A.__init__')
class B(Base):
def __init__(self):
super().__init__()
print('B.__init__')
class C(A, B):
def __init__(self):
super(B, self).__init__()
print('C.__init__')
print(C.__mro__)
c = C()
使用的建议:
复杂的继承关系指的是 发生多层继承的同时又发生了多继承
- 没有复杂继承管的情况的话 使用
- 父类名.父类方法()
- 有负责继承关系使用
- super()
四、私有属性和私有方法
定义私有属性 是两个下划线开头的属性就是私有属性
私有属性的作用: 确保数据的安全性
- 子类无法继承 私有属性
- 在类的外部 无法直接获取 和 修改 私有属性
修改私有属性
- 在类的内部修改私有属性 私有属性可以在类的内部使用(我们可以通过一个def set_vlaue这样的方法对私有属性就行修改, 同时可以设置数据的验证代码 进而保证数据的符合我们的要求)
- 私有属性可以在类的内部回去 比如直接定义一个def get_value方法, 就可以获取私有属性
# 私有权限:
# 私有权限可以给属性和方法设置
# 1. 在继承的时候不会被子类获取到, 只能在父类里使用
# 2. 不能在类的外部修改和调用私有属性或者方法
# 3. 设置的方式 两个下划线就是私有权限
class Father:
def __init__(self):
self.name = "老王"
self.__age = 20
# 私有属性可以在类的内部修改 这样就可以设置相应的条件 进而保证数据的安全性
def set_value(self, value):
if 0 < value < 200:
self.__age = value
else:
print("数据不对")
# 私有权限可以在类的内部获取
def get_value(self):
print(self.__age)
father = Father()
print(father.name)
father.set_value("王汪汪")
father.get_value()
# print(father.__little_son)
# class Son(Father):
# pass
#
#
# son = Son()
# print(son.name)
# print(son.__little_son)
私有方法的使用和私有属性的使用完全一样
class Father:
def __dance(self):
print('舞蹈')
def get_value(self):
self.__dance()
class Son(Father):
pass
father = Father()
# 私有方法在类的外部无法直接调用
# father.__dance()
# 私有方法可以在类的内部进行调用
father.get_value()
# 私有方法不可以被继承
son = Son()
son.get_value()
# son.__dance()
五、例题-搬家具
需求
将小于房子剩余面积的家具摆放到房子中
步骤分析
需求涉及两个事物:房子 和 家具,故被案例涉及两个类:房子类 和 家具类。
class House:
def __init__(self, area, address):
# 家庭住址
self.house_address = address
# 房子面积
self.house_area = area
# 空闲面积
self.free_house_area = area
# 家具列表
self.item_list = []
def add_item(self, item):
# item家具对象
# 判断剩余面积是否大于家具面积
if self.free_house_area >= item.item_area:
# 如果大于则可以添加家具
self.item_list.append(item.item_name)
# 添加完毕以后 家的剩余面积就会发生变化
self.free_house_area = self.free_house_area - item.item_area
else:
# 剩余面积不大于家具面积
print("面积不足!!!")
def __str__(self):
# 描述房子的信息
return f"房子位于{self.house_address},房子的总面积:{self.house_area}," \
f"房子的剩余面积:{self.free_house_area},家具有:{self.item_list}"
class Item:
def __init__(self, name, area):
# 家具的名字
self.item_name = name
# 家具的面积
self.item_area = area
# 定义房子
house = House(100, "新郑丽园")
# 定义家具a
a = Item("红木沙发", 10)
# 定义家具a
b = Item("红木床", 89)
# 定义家具a
c = Item("红木电视机", 20)
# 把家具添加到家里
house.add_item(a)
print(house)
house.add_item(b)
print(house)
house.add_item(c)
print(house)