最近我一直在使用Typescript,它允许表达以下内容:

interface Address {
    street: string;
    housenumber: number;
    housenumberPostfix?: string;
}

interface Person {
    name: string;
    adresses: Address[]
}

const person: Person = {
    name: 'Joe',
    adresses: [
        { street: 'Sesame', housenumber: 1 },
        { street: 'Baker', housenumber: 221, housenumberPostfix: 'b' }
    ]
}

非常简洁,在与人编码时提供了类型判断和代码完成等所有奢侈品.

这在Python中是如何实现的?

我一直在研究Mypy和ABC,但还没有成功地找到类似上述的Python方式(我的try 导致了太多符合我口味的样板文件).

推荐答案

对于IDE中的代码完成和类型提示,只需为PersonAddress类添加静态类型,就可以开始了.假设您使用的是最新的python3.6,下面是示例中typescript类的大致类似功能:

# spam.py
from typing import Optional, Sequence


class Address:
    street: str
    housenumber: int
    housenumber_postfix: Optional[str]

    def __init__(self, street: str, housenumber: int, 
                 housenumber_postfix: Optional[str] = None) -> None:
        self.street = street
        self.housenumber = housenumber
        self.housenumber_postfix = housenumber_postfix


class Person:
    name: str
    adresses: Sequence[Address]

    def __init__(self, name: str, adresses: Sequence[str]) -> None:
        self.name = name
        self.adresses = adresses


person = Person('Joe', [
    Address('Sesame', 1), 
    Address('Baker', 221, housenumber_postfix='b')
])  # type: Person

我想你提到的样板是在添加类构造函数时出现的.这确实是不可撤销的.我希望默认构造函数在运行时生成,而不是显式声明,如下所示:

class Address:
    street: str
    housenumber: int
    housenumber_postfix: Optional[str]


class Person:
    name: str
    adresses: Sequence[Address]


if __name__ == '__main__':
    alice = Person('Alice', [Address('spam', 1, housenumber_postfix='eggs')])
    bob = Person('Bob', ())  # a tuple is also a sequence

但不幸的是,您必须手动声明它们.


编辑

正如Michael0x2acomment中指出的,python3.7引入了@dataclass装饰符,因此可以避免对默认构造函数的需求,因此可以声明:

@dataclass
class Address:
    street: str
    housenumber: int
    housenumber_postfix: Optional[str]


@dataclass
class Person:
    name: str
    adresses: Sequence[Address]

并获得几种方法的默认impl,从而减少样板代码的数量.查看PEP 557了解更多详细信息.


我猜您可以看到可以从代码生成的存根文件,作为某种类型的接口文件:

$ stubgen spam  # stubgen tool is part of mypy package
Created out/spam.pyi

生成的存根文件包含模块的所有非私有类和函数的类型化签名,无需实现:

# Stubs for spam (Python 3.6)
#
# NOTE: This dynamically typed stub was automatically generated by stubgen.

from typing import Optional, Sequence

class Address:
    street: str
    housenumber: int
    housenumber_postfix: Optional[str]
    def __init__(self, street: str, housenumber: int, housenumber_postfix: Optional[str]=...) -> None: ...

class Person:
    name: str
    adresses: Sequence[Address]
    def __init__(self, name: str, adresses: Sequence[str]) -> None: ...

person: Person

IDE也可以识别这些存根文件,如果原始模块不是静态类型,它们将使用存根文件进行类型提示和代码完成.

Typescript相关问答推荐

交叉点对数字和布尔的处理方式不同

在Switch陈述中输入保护类

使用前的组件渲染状态更新

带有联合参数的静态大小数组

在配置对象上映射时,类型脚本不正确地推断函数参数

Redux—Toolkit查询仅在不为空的情况下添加参数

如何表示多层深度的泛型类型数组?

Angular NgModel不更新Typescript

如何将泛型对象作为返回类型添加到类型脚本中

嵌套对象的类型

防止重复使用 Select 器重新渲染

如何过滤文字中的类对象联合类型?

如何获取受类型脚本泛型约束的有效输入参数

如何将spread operator与typescripts实用程序类型`参数`一起使用

为什么特定的字符串不符合包括该字符串的枚举?

创建一个TypeScrip对象并基于来自输入对象的约束定义其类型

从联合提取可调用密钥时,未知类型没有调用签名

如何在Vue动态类的上下文中解释错误TS2345?

如何从联合类型推断函数参数?

React HashRouter,单击导航栏时页面重新加载出现问题