一、继承
继承: 子类可以把父类的相关的方法和属性复制一份
# 继承就是在类的后面写上(父类) # 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()
五、例题-搬家具
需求
将小于房子剩余面积的家具摆放到房子中
步骤分析
需求涉及两个事物:房子 和 家具,故被案例涉及两个类:房子类 和 家具类。
1class 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)