可选的静态类型是否有利于Python API设计或者是一个缺点? (包括类型检查装饰器示例)

我是一名长期的
Python开发人员,我非常喜欢该语言的动态特性,但我想知道Python是否会受益于可选的静态类型.

能够将静态类型应用于库的API是否有益,这会带来什么缺点?

我快速勾勒出一个实现运行时静态类型检查on pastebin的装饰器,它的工作原理如下:

# A TypeError will be thrown if the argument "string" is not a "str" and if 
# the returned value is not an "int"
@typed(int, string = str)
def getStringLength(string):
    return len(string)

在库的API函数上使用这样的装饰器是否可行?在我的观点中,在库的域特定模块的内部工作中不需要类型检查,但是在库和它的客户端之间的连接点上,通过应用类型检查的合同设计的简单版本可能是有用的.特别是作为一种强制文档,它明确向库的客户说明它期望和返回的内容.

像这个示例中,addObjectToQueue()和isObjectProcessed()被公开以供客户端使用而processTheQueueAndDoAdvancedStuff()是一个内部库函数.我认为类型检查对于面向外的函数可能很有用,但如果在内部函数上使用,它只会膨胀并限制python的动态性和有用性.

# some_library_module.py

@typed(int, name = string)
def addObjectToQueue(name):
    return random.randint() # Some object id

def processTheQueueAndDoAdvancedStuff(arg_of_library_specific_type)
    # Function body here

@typed(bool, object_id = int)
def isObjectProcessed(object_id):
    return True

使用这种技术的缺点是什么?
我的天真实施on pastebin的缺点是什么?

我不希望答案讨论将Python转换为静态类型语言的问题,而是关于API设计特定优缺点的想法. (如果您认为这不是问题,请将其移至programmers.stackexchange.com)

最佳答案 就个人而言,我并不觉得这个想法对Python很有吸引力.当然,这只是我的意见,但对于上下文我会告诉你Python和Haskell可能是我最喜欢的两种编程语言 – 我喜欢静态与动态类型谱的两端极端的语言.

我看到静态类型的主要好处如下:

>一旦编译器接受了代码,代码更正的可能性就越大;如果我知道我已经通过我调用的所有操作来调整我的值,使得一个的结果类型总是匹配另一个的输入类型,并且最终结果类型是我想要的那个,它增加了我的概率选择了正确的操作.这一点具有深刻的争论价值,因为只有你没有进行太多测试才会真正重要,这会很糟糕.但是,当我在Haskell编程时,当我坐下来说“那里,完成了!”时,确实如此.我实际上已经做了很多次,而我的Python代码几乎都没有.
>当我对数据结构或接口进行不兼容的更改时(大多数情况下),编译器会自动指出需要更改的大多数位置.同样,仍然需要进行测试以确保你已经发现了所有的含义,但是在我的经验中,大多数时候编译器的唠叨实际上已经足够了,这极大地简化了这种重构;你可以直接从实现重构的核心到测试程序仍然正常工作,因为实现所有流程变化的实际工作几乎是机械的.
>高效实施.编译器可以使用它拥有的有关类型的所有知识来进行优化.

您建议的系统并不能真正提供任何这些好处.

>编写了一个使用您的库的程序后,我仍然不知道它是否包含对函数的任何类型错误的使用,直到我使用完整代码覆盖进行大量测试,以查看是否有任何执行路径包含错误的调用.
>当我重构某些东西时,我需要经历许多轮“运行完整的测试套件,寻找异常,找到它来自哪里,修复代码”以获得任何东西,就像静态类型编译器的问题检测一样.
> Python仍然会表现得好像这些变量可以随时出现.

为了得到这么多,你已经牺牲了Python鸭子打字的灵活性;仅仅提供一个足够“类似列表”的对象是不够的,我必须提供一个列表.

对我来说,这种静态打字是两个世界中最糟糕的.主要的动态类型参数是“你必须测试你的代码,所以你也可以使用这些测试来捕获类型错误,让你不必在你没有帮助时解决类型系统问题”.对于一个非常好的静态类型系统,这可能是也可能不是一个好的论据,但对于只在运行时检测类型错误的弱部分静态类型系统,它绝对是一个令人信服的论据.我不认为更好的错误消息(这大部分都是它真正购买的;在接口上没有捕获的类型错误几乎肯定会在调用堆栈中引发更多异常)值得失去灵活性.

点赞