类与实例,类与子类

本文深入探讨Python中的类与实例,解析魔法方法如__new__、__init__等的作用,详细介绍类属性、实例属性、类方法、静态方法的区别。此外,文章还讨论了类的继承、子类与父类的__dict__区别以及如何通过super()调用父类方法,旨在深化对Python面向对象编程的理解。
摘要由CSDN通过智能技术生成


前言

通过这篇笔记,来达成两个目的:
一、帮助自己巩固一下python中和类有关的一些基础知识点,明晰在定义类的过程中各部分代码(主要是魔法方法)所起的作用。
二、了解类的继承到底是继承了什么?super()函数起了什么作用?调用父类方法时python的执行顺序是什么?——以此加深自己对继承的理解。


阅读正文前应掌握的两个工具

魔法属性__dict__

类名._dict_,返回一个字典,由类中所有属性、方法的键值对组成。
实例的__dict__仅存储与该实例相关的实例属性,并不包含该实例的所有有效属性。类的__dict__存储所有实例共享的变量和函数(类属性,方法等),类的__dict__并不包含其父类的属性。

class A():
    z = 100

    def __init__(self, a, b):
        self.a = a
        self.b = b

    def foo(self):
        print('hello')


a = A(4, 6)

print(a.__dict__)  #{'a': 4, 'b': 6}
print(A.__dict__)
#  {'__module__': '__main__', 'z': 100,
'__init__': <function A.__init__ at 0x000002127989ED30>,
'foo': <function A.foo at 0x000002127989EDC0>, 
'__dict__': <attribute '__dict__' of 'A' objects>,
'__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}

super()函数

格式:super(cls,self).方法名(参数)
cls是类名,self代指当前类的实例。(你在为哪个类写方法,这个类就是“当前类”)
python3之后,super().方法名(参数)等同于super(当前类,self).方法名(参数)。(见下方示例)

代码运行解析:类super实例化。这一实例包含了两个信息:一是以当前类为基础的MRO列表,二是处于该MRO列表中的类cls。还有一个条件:当前类必须是cls的子类。(当前类也是自身的子类,所以cls可以是当前类)
【当前类的MRO列表可以通过“print(当前类.mro())”查看】

作用:搜索在类A的MRO列表中处于类cls右方的类,找到某一方法然后调用它。例如[A,B,C,D,cls,E,F,G,object],从类E、类F、类G、类object中搜索。

class A():
    def __init__(self, a, b):
        self.a = a
        self.b = b
        print('this is A')


class B(A):
    def __init__(self, a, b, c):
        super().__init__(a, b)  #等同于super(B,self).__init__(a,b)
        #在这里可以使用“A.__init__(a,b)”代替上行代码
        self.c = c
        print('this is B')


B(1, 2, 3)
#this is A
#this is B

这里有个问题:虽然python3之后将super(当前类,self).方法名(参数)省略为super().方法名(参数),但并未强制我们将super()的第一个参数写成当前类的标识符。

class A():
    def __init__(self):
        print('this is A')


class B():
    def __init__(self):
        print('this is B')


class C(B, A):
    def __init__(self):
        super().__init__()  #等同于super(C,self)

C()  #将类C实例化。或者c=C()也是一样的。目的是触发类C的__init__()
#this is B

——类C的MRO列表为“[<class ‘main.C’>, <class ‘main.B’>, <class ‘main.A’>, <class ‘object’>]”。

显然,这里super()函数会调用类B的__init__方法。

但是,类C同样是类B和类A的子类。

我们可以将代码改成super(B,self)._init_() 或者super(A,self)._init_(a,b),然后创建类C的实例,因为这会触发类C的__init__方法。让我们看看会发生什么?

class A():
    def __init__(self):
        print('this is A')


class B():
    def __init__(self):
        print('this is B')


class C(B, A):
    def __init__(self):
        super(B,self).__init__()

C()
#this is A
class A():
    def __init__(self):
        print('this is A')


class B():
    def __init__(self):
        print('this is B')


class C(B, A):
    def __init__(self):
        super(A, self).__init__()


C()  #

还记得类C的MRO列表吗?

[<class ‘main.C’>, <class ‘main.B’>, <class ‘main.A’>, <class ‘object’>]

当我们使用super()._init_()时,实际上是运行了代码“super(C,self)._init_()”,它会调用类B的_init_(),打印出‘this is B’;
当我们使用super(B,self)._init_()时,

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值