我并没有像我希望的那样真正关注 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)
..但是,我不清楚这进展到什么程度。是否有任何静态类型的实现,使用参数注释? Python 3 中是否有任何参数化类型的想法?
最佳答案
感谢阅读我的代码!
确实,在 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
的乘法。
关于这个问题的可能解决方案还有很多要说的,但强制“计算机类型”显然是一个半解决方案,所以,至少在我看来,它比根本没有解决方案更糟糕。这也是为什么 Systems Hungarian 是一个糟糕的想法而 Apps Hungarian 是一个很棒的想法的原因。内容丰富的 post of Joel Spolsky 中还有更多内容。
现在,如果有人要实现某种 Pythonic 第三方库,它会自动将其 human 类型 分配给现实世界的数据,然后小心地转换该类型,例如 width * height -> area
并使用函数注释强制检查,我认为这将是人们真正可以使用的类型检查!
关于Python 3 和静态类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1275646/