Merci pour la lecture de mon code!
En effet, il n'est pas difficile de créer un générique d'annotation de l'outil en Python. Voici mon point de vue:
'''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)
Compte tenu de cette simplicité, c'est étrange à première vue, que cette chose n'est pas ordinaire. Cependant, je crois qu'il y a de bonnes raisons pourquoi c'est pas aussi utile que cela puisse paraître. En général, la vérification du type aide parce que si vous ajoutez entier et dictionnaire, les chances sont que vous avez fait quelques erreur évidente (et si vous vouliez dire quelque chose de raisonnable, c'est toujours mieux d'être explicite qu'implicite).
Mais dans la vraie vie, vous avez souvent mélanger des quantités du même type d'ordinateur tel que vu par le compilateur, mais clairement les différents type d'homme, par exemple le fragment de code suivant contient une erreur évidente:
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???
Tout homme doit voir immédiatement une erreur dans la ligne ci-dessus pour autant qu'elle sache le "type d'homme" de variables height
et length
, même si elle ressemble à l'ordinateur comme parfaitement légal multiplication des int
et float
.
Il n'y a plus à dire sur les solutions possibles à ce problème, mais l'application de l'ordinateur de types " est apparemment une demi-solution, de sorte que, au moins à mon avis, c'est pire que pas de solution du tout. C'est la même raison pourquoi les Systèmes hongrois est une idée terrible, tandis que les Applications hongrois est un grand. Il n'y a plus à le très instructif post de Joel Spolsky.
Maintenant, si quelqu'un était de mettre en place une sorte de Pythonic de la troisième partie de la bibliothèque qui permettrait d'attribuer automatiquement des données du monde réel de son type d'homme , puis a pris le soin de transformer ce type comme width * height -> area
et faire valoir ce que de vérifier avec la fonction annotations, je pense que ce serait une vérification du type de personnes pourraient vraiment utiliser!