侧边栏壁纸
  • 累计撰写 123 篇文章
  • 累计创建 27 个标签
  • 累计收到 1 条评论

目 录CONTENT

文章目录

继承

梁来福
2022-02-18 / 0 评论 / 0 点赞 / 0 阅读 / 9362 字
温馨提示:
本文最后更新于 2024-05-06,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

拓展:经典类和旧式类

经典类

不由任意内置类型派生出的类,称之为经典类(python2默认)

class 类名:
    代码
    ......

新式类

class 类名(object):
    代码

概念

python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法

体验

# 定义父类
class A(object):
    def __init__(self):
        self.num = 1

    def info_print(self):
        print(self.num)


# 定义子类 继承父类
class B(A):
    pass


# 创建对象 验证
result = B()

注意

在python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类

单继承

多继承

代码示例

# 定义父类
class A(object):
    def __init__(self):
        self.num = "A类"

    def info_print(self):
        print(self.num)


class C(object):
    def __init__(self):
        self.num = "C类"

    def info_print(self):
        print(self.num)


# 定义子类 继承多个父类
class B(A, C):
    pass


class D(C, A):
    pass


# 创建对象 验证
result = B()
print(result.num)
result.info_print()

result = D()
print(result.num)
result.info_print()

结论

当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法

子类重写父类同名方法和属性

代码示例

# 定义父类
class A(object):
    def __init__(self):
        self.num = "A父类"

    def info_print(self):
        print(f"这是{self.num}")


class C(object):
    def __init__(self):
        self.num = "C父类"

    def info_print(self):
        print(f"这是{self.num}")


# 定义子类
class B(A, C):
    def __init__(self):
        self.num = "B子类"

    def info_print(self):
        print(f"这是{self.num}")


# 创建对象 验证
result = B()
print(result.num)
result.info_print()

结论

如果子类和父类拥有同名属性和方法,子类创建对象调用属性和方法的时候,调用的是子类里面的同名属性和方法

拓展-mro顺序

代码示例

# 定义父类
class A(object):
    def __init__(self):
        self.num = "A父类"

    def info_print(self):
        print(f"这是{self.num}")


class C(A):
    def __init__(self):
        self.num = "C父类"

    def info_print(self):
        print(f"这是{self.num}")


# 创建对象 验证
result = C()
print(result.num)
result.info_print()

print(C.__mro__)

输出

C父类
这是C父类
(<class 'main.C'>, <class 'main.A'>, <class 'object'>)

子类调用父类的同名方法和属性

代码示例

# 定义父类
class A(object):
    def __init__(self):
        self.num = "A父类"

    def info_print(self):
        print(f"我是{self.num}")


class B(object):
    def __init__(self):
        self.num = "B父类"

    def info_print(self):
        print(f"我是{self.num}")


class LaiFu(A, B):
    def __init__(self):
        self.num = "来福子类"

    def info_print(self):
        # 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
        self.__init__()
        print(f"我是{self.num}")

    # 子类调用父类的同名方法和属性
    def a_info_print(self):
        # 调用父类方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
        A.__init__(self)
        A.info_print(self)

    def b_info_print(self):
        B.__init__(self)
        B.info_print(self)


# 创建对象 验证
lianglaifu = LaiFu()
lianglaifu.info_print()

lianglaifu.a_info_print()
lianglaifu.b_info_print()

lianglaifu.info_print()

输出

我是来福子类
我是A父类
我是B父类
我是来福子类

多层继承

代码示例

# 定义父类
class A(object):
    def __init__(self):
        self.num = "A父类"

    def info_print(self):
        print(f"我是{self.num}")


class B(object):
    def __init__(self):
        self.num = "B父类"

    def info_print(self):
        print(f"我是{self.num}")


# 来福子类,继承A类和B类
class LaiFu(A, B):
    def __init__(self):
        self.num = "来福子类"

    def info_print(self):
        # 如果是先调用了父类的属性和方法,父类属性会覆盖子类属性,故在调用属性前,先调用自己子类的初始化
        self.__init__()
        print(f"我是{self.num}")

    # 子类调用父类的同名方法和属性
    def a_info_print(self):
        # 调用父类方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
        A.__init__(self)
        A.info_print(self)

    def b_info_print(self):
        B.__init__(self)
        B.info_print(self)


# 徒孙类,继承来福子类
class Tusun(LaiFu):
    pass


# 使用徒孙类创建对象 验证
lianglaifu = Tusun()

lianglaifu.info_print()
lianglaifu.a_info_print()
lianglaifu.b_info_print()

输出

我是来福子类
我是A父类
我是B父类

super()调用父类方法

有参数super

代码示例

# 定义父类
class A(object):
    def __init__(self):
        self.num = "A父类"

    def info_print(self):
        print(f"我是{self.num}")


class B(A):
    def __init__(self):
        self.num = "B父类"

    def info_print(self):
        print(f"我是{self.num}")

        # 2.1 super()带参数写法
        super(B, self).__init__()
        super(B, self).info_print()

class Laifu(B):
    def __init__(self):
        self.num = "梁来福"

    def info_print(self):
        print(f"我是{self.num}")

    # 子类调用父类的同名方法和属性
    def a_info_print(self):
        # 调用父类方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
        A.__init__(self)
        A.info_print(self)

    def b_info_print(self):
        B.__init__(self)
        B.info_print(self)

    # 需求:一次性调用父类A和B的方法
    def new_info_print(self):
        # 方法一:代码冗余;父类类名如果变化,这里代码需要频繁修改
        #B.__init__(self)
        #B.info_print(self)
        #A.__init__(self)
        #A.info_print(self)

        # 方法二:super()
        # 方法2.1 super(当前类名, self).函数()
        super(Laifu, self).__init__()
        super(Laifu, self).info_print()

lianglaifu = Laifu()

lianglaifu.new_info_print()

输出

我是B父类
我是A父类

无参数super

代码示例

# 定义父类
class A(object):
    def __init__(self):
        self.num = "A父类"

    def info_print(self):
        print(f"我是{self.num}")


class B(A):
    def __init__(self):
        self.num = "B父类"

    def info_print(self):
        print(f"我是{self.num}")

        # 2.1 super()带参数写法
        # super(B, self).__init__()
        # super(B, self).info_print()

        # 2.2 super()无参数写法
        super().__init__()
        super().info_print()

class Laifu(B):
    def __init__(self):
        self.num = "梁来福"

    def info_print(self):
        print(f"我是{self.num}")

    # 子类调用父类的同名方法和属性
    def a_info_print(self):
        # 调用父类方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
        A.__init__(self)
        A.info_print(self)

    def b_info_print(self):
        B.__init__(self)
        B.info_print(self)

    # 需求:一次性调用父类A和B的方法
    def new_info_print(self):
        # 方法一:代码冗余;父类类名如果变化,这里代码需要频繁修改
        #B.__init__(self)
        #B.info_print(self)
        #A.__init__(self)
        #A.info_print(self)

        # 方法二:super()
        # 方法2.1 带参数:super(当前类名, self).函数()
        # super(Laifu, self).__init__()
        # super(Laifu, self).info_print()

        # 方法2.2 无参数:super
        super().__init__()
        super().info_print()


lianglaifu = Laifu()
lianglaifu.new_info_print()

输出

我是B父类
我是A父类

注意

使用super()可以自动查找父类。调用顺序遵循__mro__类属性的顺序,比较适合单继承使用

私有权限

定义私有属性和方法

在python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类

设置方法

设置私有权限的方法:在属性名和方法名前面加上两个下划线__

代码示例

......
class Laifu(B):
    def __init__(self):
        self.num = "梁来福"
        # 定义私有属性
        self.__money = 20000000000

    def info_print(self):
        print(f"我是{self.num}")

    # 定义私有方法
    def __info_print(self):
        print("这是私有方法")
......

获取和修改私有属性值

代码示例

# 定义父类
class A(object):
    def __init__(self):
        self.num = "A父类"

    def info_print(self):
        print(f"我是{self.num}")


class B(A):
    def __init__(self):
        self.num = "B父类"

    def info_print(self):
        print(f"我是{self.num}")

        # 2.1 super()带参数写法
        # super(B, self).__init__()
        # super(B, self).info_print()

        # 2.2 super()无参数写法
        super().__init__()
        super().info_print()


class Laifu(B):
    def __init__(self):
        self.num = "梁来福"
        # 定义私有属性
        self.__money = 20000000000

    def info_print(self):
        print(f"我是{self.num}")

    # 定义函数:获取私有属性值
    def get_money(self):
        return self.__money

    # 定义函数:修改私有属性值
    def set_money(self):
        self.__money = 500

    # 定义私有方法
    def __info_print(self):
        print("这是私有方法")

    # 子类调用父类的同名方法和属性
    def a_info_print(self):
        # 调用父类方法,为保证调用到的也是父类的属性,必须在调用方法前调用父类的初始化
        A.__init__(self)
        A.info_print(self)

    def b_info_print(self):
        B.__init__(self)
        B.info_print(self)

    # 需求:一次性调用父类A和B的方法
    def new_info_print(self):
        # 方法一:代码冗余;父类类名如果变化,这里代码需要频繁修改
        #B.__init__(self)
        #B.info_print(self)
        #A.__init__(self)
        #A.info_print(self)

        # 方法二:super()
        # 方法2.1 带参数:super(当前类名, self).函数()
        # super(Laifu, self).__init__()
        # super(Laifu, self).info_print()

        # 方法2.2 无参数:super
        super().__init__()
        super().info_print()


class Tusun(Laifu):
    pass


lianglaifu = Tusun()
print(lianglaifu.get_money())
# 修改完私有属性再次打印
lianglaifu.set_money()
print(lianglaifu.get_money())

输出

20000000000
500

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
博主关闭了所有页面的评论