python中可继承的自定义类构造函数

Posted

技术标签:

【中文标题】python中可继承的自定义类构造函数【英文标题】:Inheritable custom class constructor in python 【发布时间】:2021-11-20 12:35:30 【问题描述】:

如何实现在python中可继承的自定义构造函数(类方法)?

以下最小化的示例可能会提供一个想法:

from dataclasses import dataclass
from typing import Type, TypeVar

T = TypeVar("T")


@dataclass
class Parent:
    something: int = 2

    @classmethod
    def from_float(cls: Type[T], something_as_float: float) -> T:
        return Type[T](something=int(something_as_float))


@dataclass
class Child(Parent):
    """ Should also be constructible via from_float
    """


assert isinstance(Parent.from_float(1.0), Parent)
assert isinstance(Child.from_float(1.0), Child)

mypy 不喜欢我从 from_float 返回时调用的构造函数。我不知道如何从类方法中引用类(Parent 或 Child)。

【问题讨论】:

你的意思是像一个实例工厂? 不确定...添加一个 C++ 模式以便我可以在 python 中实现一个 Rust 模式感觉就像我只是在给垃圾火添油:) 为什么不实现__new__方法? @dataclass 隐式添加了获取字段的构造函数(以及 __new__?),我不能打扰它。我正在尝试将 rust 启发的转换方法添加到一些相互继承的现有数据类中,并且我无法更改设计的 dataclasses-with-inheritance 部分。 Type[T] 不是构造函数; cls 是。 【参考方案1】:

bound 参数传递给TypeVar 以指定该类型是Parent 的子类。这让 mypy 知道该类型具有 something 属性

创建实例时使用cls 而不是Type[T]

from dataclasses import dataclass
from typing import Type, TypeVar

T = TypeVar("T", bound='Parent')


@dataclass
class Parent:
    something: int = 2

    @classmethod
    def from_float(cls: Type[T], something_as_float: float) -> T:
        return cls(something=int(something_as_float))


@dataclass
class Child(Parent):
    pass


assert isinstance(Parent.from_float(1.0), Parent)
assert isinstance(Child.from_float(1.0), Child)

【讨论】:

太棒了。谢谢!我可以在本地确认它在没有断言的情况下运行,并且还通过了 mypy! 您不能在其定义中引用一个类......并且转义为 cls: "Parent" 和 -> "Parent" 也没有帮助。我点击“自我的擦除类型“minimized_typing_puzzle.Parent”不是其类“Type [minimized_typing_puzzle.Parent]”的超类型,然后错误:“Parent”不可调用。 Iain 的解决方案有效,但如果您喜欢输入谜题,请随时保持线程继续运行。谢谢!

以上是关于python中可继承的自定义类构造函数的主要内容,如果未能解决你的问题,请参考以下文章

[C++11 类的改进] --- 继承控制:=default和=delete

通过定义默认私有构造函数使类不可继承

类(对象)的定义 自定义对象构造函数

C# 继承和默认构造函数

继承默认构造函数,矛盾吗?

scala入门教程:scala中的面向对象定义类,构造函数,继承