私のコードを読んでくれてありがとう!
実際、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が素晴らしいアイデアであるのと同じ理由です。Joel Spolskyの非常に有益な投稿には、さらに多くの情報があります。
誰かが、現実世界のデータに人間の型を自動的に割り当て、その型のように変換しwidth * height -> area
、関数注釈でそのチェックを強制する何らかの種類の Pythonic サードパーティ ライブラリを実装するとしたら、それは型になると思います。人々が実際に使用できるかどうかを確認してください!