python中类的__init_subclass__

python



一、python中类的__init_subclass__

__init_subclass__是一个特殊的类方法,它在Python 3.6中被引入。当一个类被定义为另一个类的子类时,__init_subclass__方法会被自动调用。这个方法可以用来自定义子类的初始化过程。

举个例子:

class MyClass:

    """
    __new__方法是一个静态方法,它的第一个参数是cls,表示要实例化的类
    这个方法的主要任务是创建新的实例并返回它。
    """
    def __new__(cls, *args, **kwargs):
        instance = super().__new__(cls)
        # 在这里可以添加一些额外的初始化代码
        return instance

    """
    __init__方法则是一个实例方法,它在__new__方法创建新实例后被调用,用于初始化新创建的实例。
    """
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

    def __init_subclass__(cls, /, default_name, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.default_name = default_name
        print(f'{cls} is a subclass of BaseClass')

class SubClass(MyClass, default_name="Bruce"):
    def __init__(self, arg1, arg2):
        self.arg1 = arg1
        self.arg2 = arg2

a = MyClass(1, 2)

b = SubClass(3, 4)

在这个例子中,当SubClass被定义为MyClass的子类时,BaseClass__init_subclass__方法会被自动调用,打印出一条消息。

这段代码中的__init_subclass__方法用于在子类创建时进行一些初始化操作。在这个例子中,它将default_name参数设置为子类的类属性,并打印一条消息。

/在函数参数列表中的作用是指定位置参数。在/之前的参数必须作为位置参数传入,不能作为关键字参数。在这个例子中,default_name必须作为位置参数传入。

这样做的好处是:

  1. 提供默认值:通过在__init_subclass__方法中设置类属性,我们可以为所有子类提供默认值。在这个例子中,所有的MyClass子类都会有一个default_name属性,其默认值为创建子类时传入的值。
  2. 强制参数传递方式:通过使用/,我们可以强制default_name必须作为位置参数传入,这可以避免在调用函数时出现歧义。

需要注意的是,__init_subclass__方法的第一个参数(cls)是子类,而不是实例。这个方法通常用于元编程,即编写可以影响或修改其他代码的代码。在大多数情况下,我们可能不需要使用__init_subclass__方法。

/在Python 3.8中被引入,如果我们使用的Python版本低于3.8,这段代码可能会出错。

运行过程
在这里插入图片描述

二、__init_subclass__会使用在什么场景

__init_subclass__主要用于元编程,即编写可以影响或修改其他代码的代码。它在一个类被子类化时被调用,允许我们在子类化时执行一些操作。以下是一些可能的使用场景:

  1. 注册子类:我们可以使用__init_subclass__来自动注册所有的子类。例如,如果我们正在编写一个插件系统,我们可能想要在一个类被子类化时自动注册这个子类。
class PluginBase:
    subclasses = []

    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        cls.subclasses.append(cls)

class Plugin1(PluginBase):
    pass

class Plugin2(PluginBase):
    pass

print(PluginBase.subclasses)
# 输出: [<class '__main__.Plugin1'>, <class '__main__.Plugin2'>]

在这个例子中,我们在PluginBase__init_subclass__方法中将每个子类添加到subclasses列表中。然后,我们可以通过查看subclasses列表来找出所有的插件。

  1. 强制子类实现某些方法:我们可以使用__init_subclass__来检查子类是否实现了某些方法,如果没有,我们可以抛出一个错误。
class AbstractBase:
    def __init_subclass__(cls, **kwargs):
        super().__init_subclass__(**kwargs)
        if not hasattr(cls, 'foo'):
            raise TypeError('Subclasses must define foo method')

class GoodSubclass(AbstractBase):
    def foo(self):
        pass

class BadSubclass(AbstractBase):
    pass
# 抛出错误: TypeError: Subclasses must define foo method

在这个例子中,我们在AbstractBase__init_subclass__方法中检查子类是否定义了foo方法。如果没有,我们就抛出一个错误。这样,我们就可以确保所有的子类都实现了foo方法。

__init_subclass__方法主要用于元编程,即编写可以影响或修改其他代码的代码。它在一个类被子类化时被调用,允许我们在子类化时执行一些操作。以下是一些可能的使用场景:

  1. 注册子类:我们可以使用__init_subclass__来自动注册所有的子类。例如,如果我们正在编写一个插件系统,我们可能想要在一个类被子类化时自动注册这个子类。
  2. 强制子类实现某些方法:我们可以使用__init_subclass__来检查子类是否实现了某些方法,如果没有,我们可以抛出一个错误。
  3. 自动添加类属性或方法:我们可以使用__init_subclass__来自动给子类添加一些属性或方法。
  4. 修改类的行为:我们可以使用__init_subclass__来修改子类的行为,例如修改类的元类。

这些都是__init_subclass__可能的使用场景,但并不是所有的场景都需要使用这个方法。在大多数情况下,我们可能不需要使用__init_subclass__方法。

三、什么是元编程,怎么学习元编程

元编程是一种编程技术,它允许开发者在运行时修改或生成代码。在Python中,元编程主要通过反射(introspection)和元类(metaclasses)来实现。

  1. 反射:Python的反射功能允许我们在运行时获取对象的类型信息,例如我们可以获取一个对象的类名,方法列表等。我们也可以动态地创建和修改对象。Python的type(), getattr(), setattr(), hasattr()等函数提供了反射功能。
  2. 元类:元类是创建类的类。在Python中,type是所有类的元类。我们可以通过继承type来创建自定义的元类,然后使用这个元类来创建类。元类可以用来修改类的行为,例如添加新的方法,修改属性等。

四、什么是 关键字参数?位置参数?

在Python中,函数的参数可以分为两种:位置参数(Positional arguments)和关键字参数(Keyword arguments)。

  1. 位置参数:位置参数是按照参数在函数定义中的位置来传递的。例如,在函数def func(a, b):中,ab都是位置参数。当我们调用func(1, 2)时,1会被传递给a2会被传递给b
  2. 关键字参数:关键字参数是通过参数名来传递的。例如,在函数def func(a, b):中,我们可以通过func(a=1, b=2)来调用函数。这样,无论参数在函数定义中的位置如何,1都会被传递给a2都会被传递给b

在函数调用时,位置参数必须在关键字参数之前。例如,func(1, b=2)是合法的,但func(a=1, 2)是不合法的。

此外,Python 3.8引入了一个新的语法/,用于在函数定义中指定位置参数。在/之前的参数必须作为位置参数传入,不能作为关键字参数。例如,在函数def func(a, /, b):中,a必须作为位置参数传入,b可以作为位置参数或关键字参数传入。

五、官方链接

https://docs.python.org/zh-cn/3/reference/datamodel.html#object.init_subclass

  • 55
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吊肩三角裤

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值