dbr*_*dbr 57 python static-typing python-3.x
我并没有像我希望的那样关注Python 3的开发,只是注意到一些有趣的新语法更改.具体来自这个SO答案函数参数注释:
def digits(x:'nonnegative number') -> "yields number's digits":
# ...
Run Code Online (Sandbox Code Playgroud)
对此一无所知,我认为它可以用于在Python中实现静态类型!
经过一些搜索,似乎有很多关于Python中的(完全可选的)静态类型的讨论,例如PEP 3107中提到的和"向Python添加可选的静态类型"(以及第2部分)
但是,我不清楚这有多大进展.是否有使用参数注释的静态类型的实现?是否有任何参数化类型的想法进入Python 3?
ily*_* n. 33
感谢您阅读我的代码!
实际上,在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)
Run Code Online (Sandbox Code Playgroud)
鉴于这种简单性,乍一看这件事并不是主流,这很奇怪.但是,我认为有充分的理由说明它没有看起来那么有用.通常,类型检查有帮助,因为如果你添加整数和字典,你可能会犯一些明显的错误(如果你的意思是合理的话,那么显性比隐式更好).
但在现实生活中,您经常混合使用编译器看到的相同计算机类型的数量,但明显不同的人类类型,例如以下代码段包含一个明显的错误:
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???
Run Code Online (Sandbox Code Playgroud)
任何人应立即看到上面的行了一个错误,只要它知道变量的"人型" height
和length
即使它看起来计算机完全合法的乘法int
和float
.
关于这个问题的可能解决方案可以说更多,但强制执行"计算机类型"显然是一个半解决方案,所以,至少在我看来,它比没有解决方案更糟糕.这就是为什么匈牙利系统是一个糟糕的想法,而匈牙利应用程序是一个伟大的想法.在Joel Spolsky的信息丰富的帖子中还有更多内容.
现在,如果有人要实现某种Pythonic第三方库,它会自动分配给它的人类类型的真实数据,然后注意转换类型width * height -> area
并强制执行带有函数注释的检查,我认为这将是一种类型检查人们真的可以使用!
syk*_*ora 14
正如PEP中所提到的,静态类型检查是可以使用函数注释的可能应用程序之一,但是它们将它留给第三方库来决定如何执行它.也就是说,核心python中不会有官方实现.
就第三方实现而言,有一些片段(例如http://code.activestate.com/recipes/572161/),它们似乎很好地完成了这项工作.
编辑:
作为一个注释,我想提一下检查行为比检查类型更可取,因此我认为静态类型检查并不是一个好主意.我上面的回答是为了回答这个问题,而不是因为我会以这种方式做自己的攻击.
Len*_*bro 12
Python中的"静态类型"只能实现,以便在运行时完成类型检查,这意味着它会降低应用程序的速度.因此,你不希望这是一般性的.相反,您需要一些方法来检查它的输入.如果您(错误地)认为您需要它很多,可以使用普通断言或装饰器轻松完成.
还有静态类型检查的替代方法,即使用面向方面的组件体系结构,如Zope组件体系结构.您可以调整它,而不是检查类型.所以代替:
assert isinstance(theobject, myclass)
Run Code Online (Sandbox Code Playgroud)
你做这个:
theobject = IMyClass(theobject)
Run Code Online (Sandbox Code Playgroud)
如果对象已经实现了IMyClass,则没有任何反应.如果没有,将查找包装任何对象到IMyClass的适配器,并使用而不是对象.如果找不到适配器,则会出现错误.
这结合了Python的动态主义和以特定方式获得特定类型的愿望.