Python 3和静态types
我没有真正把注意力放在Python 3的开发上,而只是注意到了一些有趣的新的语法变化。 具体从这个SO回答函数参数注释:
def digits(x:'nonnegative number') -> "yields number's digits": # ...
不知道这件事情,我认为它可能被用来在Python中实现静态input!
经过一番search之后,似乎有很多关于(完全可选的)Python中的静态types的讨论,比如PEP 3107中提到的“添加可选静态types到Python” (和第2部分 )
但是,我不清楚这个进展有多远。 有静态types的任何实现,使用参数注释? 有没有参数化types的想法使它成为Python 3?
感谢您阅读我的代码!
的确,在Python中创build一个通用的注释执行器并不困难。 这是我的意见:
'''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)
鉴于这种简单性,一见到这个东西就不是主stream。 不过,我认为有充分的理由说明它没有看起来那么有用 。 一般来说,types检查是有帮助的,因为如果你添加整数和字典,你可能会犯一些明显的错误(如果你的意思是合理的, 比隐式更好 )。
但在现实生活中,您经常会混合编译器所看到的相同计算机types的数量,但显然不同的人类types ,例如下面的代码片段包含一个明显的错误:
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???
任何人都应该立即看到上面一行中的错误,只要它知道variablesheight
和length
的“人类types”,即使它把计算机看作是int
和float
完全合法的乘法。
关于解决这个问题的可能的解决办法还有更多,但是强制执行“计算机types”显然是一个半解决scheme,所以至less在我看来,这比任何解决scheme都要糟糕 。 “ 匈牙利语系统”是一个糟糕的主意,而“ 匈牙利语言应用程序”则是一个很好的理由。 乔尔·斯波斯基(Joel Spolsky)的信息很丰富。
现在,如果有人要实现某种Pythonic第三方库,它会自动将真实世界的数据分配给它的人类types ,然后小心地转换width * height -> area
并使用函数注释强制执行该检查。认为这将是一个types检查人可以真正使用!
正如在PEP中所提到的那样,静态types检查是函数注释可以使用的一种可能的应用程序,但是他们将把它留给第三方库来决定如何去做。 也就是说,核心python中不会有官方的实现。
至于第三方实现方面,有一些片段(如http://code.activestate.com/recipes/572161/ ),这似乎做得很好。
编辑:
作为一个说明,我想提到检查行为比检查types更可取,因此我认为静态types检查并不是一个好主意。 我上面的答案旨在回答这个问题,而不是因为我会以这种方式进行types检查。
Python中的“静态types”只能实现,因此types检查是在运行时完成的,这意味着它减慢了应用程序的速度。 所以你不希望这是一个普遍性。 相反,你想要一些你的方法来检查它的input。 如果你(错误地)认为你需要它,这可以很容易地用简单的断言来完成,或者用装饰器来完成。
还有一种替代静态types检查的方法,那就是使用面向方面的组件架构,比如Zope组件架构。 而不是检查types,你适应它。 所以,而不是:
assert isinstance(theobject, myclass)
你做这个:
theobject = IMyClass(theobject)
如果这个对象已经实现了IMyClass,则什么都不会发生。 如果没有的话,将会查找一个包含IMyClass对象的适配器,而不是该对象。 如果找不到适配器,则会出现错误。
这将Python的dynamic性与以特定方式具有特定types的愿望相结合。
这不是直接回答问题,但我发现了一个Python分支,它增加了静态types: mypy-lang.org ,当然不能依赖它,因为它仍然是一个小小的努力,但是很有趣。
当然,静态打字看起来有点“不合理”,我不会一直使用它。 但是有些情况下(例如嵌套类,就像在特定领域的语言parsing中),它可以真正加速你的开发。
那么我更喜欢使用beartype在这篇文章中解释*。 它带有一个git回购,testing和解释它可以做什么,不能做什么…我喜欢这个名字;)
*请不要关注塞西尔咆哮为什么Python不包含在这种情况下的电池。