代码之家  ›  专栏  ›  技术社区  ›  dbr

Python3和静态类型

  •  57
  • dbr  · 技术社区  · 17 年前

    我并没有像我所希望的那样关注Python 3的开发,只是注意到一些有趣的新语法变化。特别是从 this SO answer 功能参数注释:

    def digits(x:'nonnegative number') -> "yields number's digits":
        # ...
    

    我对此一无所知,我认为它可以用于在Python中实现静态类型!

    在进行了一些搜索之后,关于Python中的(完全可选)静态类型(如中提到的)似乎有很多讨论 PEP 3107 "Adding Optional Static Typing to Python" (及 part 2 )

    5 回复  |  直到 9 年前
        1
  •  35
  •   ilya n.    17 年前

    谢谢你阅读我的代码!

    事实上,在Python中创建通用注释执行器并不困难。以下是我的看法:

    '''Very simple enforcer of type annotations.
    
    This toy super-decorator can decorate all functions in a given module that have 
    annotations so that the type of input and output is enforced; an AssertionError is
    raised on mismatch.
    
    This module also has a test function func() which should fail and logging facility 
    log which defaults to print. 
    
    Since this is a test module, I cut corners by only checking *keyword* arguments.
    
    '''
    
    import sys
    
    log = print
    
    
    def func(x:'int' = 0) -> 'str':
        '''An example function that fails type checking.'''
        return x
    
    
    # For simplicity, I only do keyword args.
    def check_type(*args):
        param, value, assert_type = args
        log('Checking {0} = {1} of {2}.'.format(*args))
        if not isinstance(value, assert_type):
            raise AssertionError(
                'Check failed - parameter {0} = {1} not {2}.'
                .format(*args))
        return value
    
    def decorate_func(func):    
        def newf(*args, **kwargs):
            for k, v in kwargs.items():
                check_type(k, v, ann[k])
            return check_type('<return_value>', func(*args, **kwargs), ann['return'])
    
        ann = {k: eval(v) for k, v in func.__annotations__.items()}
        newf.__doc__ = func.__doc__
        newf.__type_checked = True
        return newf
    
    def decorate_module(module = '__main__'):
        '''Enforces type from annotation for all functions in module.'''
        d = sys.modules[module].__dict__
        for k, f in d.items():
            if getattr(f, '__annotations__', {}) and not getattr(f, '__type_checked', False):
                log('Decorated {0!r}.'.format(f.__name__))
                d[k] = decorate_func(f)
    
    
    if __name__ == '__main__':
        decorate_module()
    
        # This will raise AssertionError.
        func(x = 5)
    

    考虑到这种简单性,乍一看这个东西不是主流很奇怪。然而,我相信这是有充分理由的 没有看上去那么有用 . 一般来说,类型检查很有帮助,因为如果您添加整数和字典,很可能会犯一些明显的错误(如果您的意思是合理的,则仍然是错误的) ).

    正如编译器所看到的,但显然不同 ,例如,以下代码段包含一个明显的错误:

    height = 1.75 # Bob's height in meters.
    length = len(sys.modules) # Number of modules imported by program.
    area = height * length # What's that supposed to mean???
    

    height length 即使它看起来像计算机一样 乘法 int float

    关于这个问题的可能解决方案还有很多,但强制执行“计算机类型”显然是半个解决方案,所以,至少在我看来,这是一个解决方案 比根本没有解决方案更糟糕 . 原因也是一样 匈牙利系统 这是个糟糕的主意 这是一个伟大的故事。在信息量非常丰富的网站上还有更多内容 post of Joel Spolsky .

    现在,如果有人要实现某种Pythonic第三方库,它会自动分配给真实世界的数据 然后小心地把这种类型转换成 width * height -> area

        2
  •  15
  •   sykora    17 年前

    正如该PEP中提到的,静态类型检查是函数注释可以用于的可能应用程序之一,但它们将由第三方库决定如何进行。也就是说,在核心python中不会有正式的实现。

    就第三方实现而言,有一些代码片段(例如 http://code.activestate.com/recipes/572161/ ),这项工作似乎做得很好。

    编辑:

    作为说明,我想提到检查行为比检查类型更可取,因此我认为静态类型检查不是一个好主意。我上面的回答是为了回答这个问题,不是因为我会用这种方式自己打字。

        3
  •  14
  •   Lennart Regebro    17 年前

    Python中的“静态类型”只能在运行时执行类型检查,这意味着它会降低应用程序的速度。因此,您不希望将其作为一个通用性。相反,您需要一些方法来检查它的输入。如果你(错误地)认为你非常需要它,这可以很容易地用简单的断言或装饰来完成。

    还有一种替代静态类型检查的方法,即使用面向方面的组件体系结构,如Zope组件体系结构。不是检查类型,而是调整它。因此,不是:

    assert isinstance(theobject, myclass)
    

    您可以这样做:

    theobject = IMyClass(theobject)
    

    如果对象已经实现IMyClass,则不会发生任何事情。否则,将查找将对象包装到IMyClass的适配器,并使用它代替对象。如果找不到适配器,则会出现错误。

    这结合了Python的动态性和以特定方式拥有特定类型的愿望。

        4
  •  13
  •   Ciantic    13 年前

    mypy-lang.org 当然,我们不能依赖它,因为它仍然是很小的努力,但很有趣。

        5
  •  0
  •   Community Mohan Dere    9 年前

    当然,静态输入似乎有点“不和谐”,我并不总是使用它。但在某些情况下(例如,嵌套类,如特定于领域的语言解析),它确实可以加快您的开发速度。

    beartype 解释如下 post *.它附带了一个git回购协议,测试和解释它能做什么和不能做什么。。。我喜欢这个名字;)

    *请不要注意Cecil关于Python为什么不附带电池的咆哮。

    推荐文章