Python进阶---面向对象 继承

简介: Python进阶---面向对象 继承

一、继承

继承: 子类可以把父类的相关的方法和属性复制一份

# 继承就是在类的后面写上(父类)
# 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)
目录
相关文章
|
1月前
|
Python
Python进阶第一篇(Python的面向对象)
Python进阶第一篇(Python的面向对象)
|
9天前
|
存储 算法 搜索推荐
算法进阶之路:Python 归并排序深度剖析,让数据排序变得艺术起来!
【7月更文挑战第12天】归并排序是高效稳定的排序算法,采用分治策略。Python 实现包括递归地分割数组及合并已排序部分。示例代码展示了如何将 `[12, 11, 13, 5, 6]` 分割并归并成有序数组 `[5, 6, 11, 12, 13]`。虽然 $O(n log n)$ 时间复杂度优秀,但需额外空间,适合大规模数据排序。对于小规模数据,可考虑其他算法。**
34 4
|
11天前
|
算法 Python
Python算法高手进阶指南:分治法、贪心算法、动态规划,掌握它们,算法难题迎刃而解!
【7月更文挑战第10天】探索Python算法的精华:分治法(如归并排序)、贪心策略(如找零钱问题)和动态规划(解复杂问题)。通过示例代码揭示它们如何优化问题解决,提升编程技能。掌握这些策略,攀登技术巅峰。
|
25天前
|
开发者 Python
Python进阶:深入剖析闭包与装饰器的应用与技巧
Python进阶:深入剖析闭包与装饰器的应用与技巧
|
25天前
|
分布式计算 算法 Python
Python函数进阶:四大高阶函数、匿名函数、枚举、拉链与递归详解
Python函数进阶:四大高阶函数、匿名函数、枚举、拉链与递归详解
|
25天前
|
Python
Python面向对象进阶:深入解析面向对象三要素——封装、继承与多态
Python面向对象进阶:深入解析面向对象三要素——封装、继承与多态
|
25天前
|
Python
Python面向对象基础与魔法方法详解
Python面向对象基础与魔法方法详解
|
1天前
|
前端开发 开发者 Python
从零到一:Python Web框架中的模板引擎入门与进阶
【7月更文挑战第20天】模板引擎如Jinja2在Python Web开发中连接后端与前端,提高代码可读性和协作效率。Flask默认集成Jinja2,提供条件语句、循环、宏和模板继承等功能。例如,创建一个简单Flask应用,渲染&quot;Hello, World!&quot;,并展示如何使用条件语句和循环处理数据。通过宏定义重用代码,模板继承实现页面结构共享。学习模板引擎能提升开发效率和项目质量。
8 0
|
2天前
|
SQL 前端开发 数据库
Python Web开发进阶之路:从模板引擎到ORM的全面掌握
【7月更文挑战第19天】在Python Web开发中,提升技能的关键是理解和运用模板引擎(如Jinja2)与ORM技术。模板引擎,如在Flask中使用的Jinja2,使前端HTML与后端逻辑分离,便于维护。例如,通过路由函数`show_posts()`和`render_template()`呈现文章列表模板,用Jinja2的`for`循环展示内容。ORM,如SQLAlchemy,提供Pythonic的数据库操作,将表映射为类,SQL转化为方法调用。在博客系统中,定义Post模型并与数据库交互,展示了ORM简化数据管理的优势。通过实践这些工具,开发者能更好地驾驭复杂的Web项目。
10 0
|
25天前
|
Java Python
Python进阶之旅:深入理解变量作用域、垃圾回收、拷贝机制与异常处理
Python进阶之旅:深入理解变量作用域、垃圾回收、拷贝机制与异常处理