首页 > 解决方案 > 如何创建一个类型“等于”int的类?

问题描述

我正在尝试创建一个可以从类型定义生成 clickhouse (sql-ish) 模式的数据类。

例如,clickhouse 支持:

在 python 中,这些类型不存在(afaik)。只是int。我希望我仍然可以创建一个类型结构,让我表达它并自动生成我想要的模式,并可能对类型运行验证。我也希望我的类型提示(我使用 PyCharm,不确定 mypy)在传递 int 类型的值时不会抱怨

到目前为止,这是我的想法:

@dataclass
class ClickhouseType:
    @classmethod
    def schema_type(cls):
        return cls.__name__

    @classmethod
    def validate(cls, value):
        # just included as an example, not important as part of this discussion :) 
        pass


@dataclass
class Int8(int, ClickhouseType):
    @classmethod
    def validate(cls, value):
        # just included as an example, not important as part of this discussion :)
        assert -128 <= value <= 127

@dataclass
class MySchema:
    some_number: Int8


x = MySchema(some_number=4)  # type hint complaints that I pass an int when an Int8 is required

有没有办法让 python/我的类型提示理解我想Int8与之互换int

标签: pythontypestype-hintingpython-dataclasses

解决方案


尝试使用直接继承创建您的类型:

class int8 (int):
    def __new__ (cls, value):
        assert -128<=value<=127
        return int(value) # Simplified
        # Or if you need more things:
        self = int.__new__(cls, value)
        self.something = "something else"
        return self

shadowranger 的评论提示编辑:

这里的一切都是 type(int(...))==type(int8(...))==True,除了类
实例化后的 __name__ 属性。当然还有 int8().__class__。
请记住,__new__() 构造函数在类中的任何其他内容被“视为对象化”之前被调用。因此在 __init__() 之前也是如此。__init__() 在对象构造之后调用,而 __new__() 实际上在它之前调用。
__new() 接收类作为第一个参数,而 __init__() 接收已经构造的对象。
所以,如果使用多重继承,一些初始化应该去__new__(),主要是那些修改数据类型的,还有一些应该在__init__()中完成。

请注意 type(int)!=type(int8)==True 在这里,所以这并不是你问题的确切答案,但它应该是一个很好的指针,结合你已经知道的内容。

推荐阅读