Examples of open-source projects using Python 3 function annotations
Can anyone give me some examples of Python open-source projects using the function annotations introduced in Python 3?
I want to see some practical uses of this 开发者_开发百科feature and see if I can use it my own project.
I have never seen this feature used in the wild. However, one potential use of function annotations that I explored in an article on Python 3 that I wrote for USENIX ;Login: was for enforcing contracts. For example, you could do this:
from functools import wraps
def positive(x):
'must be positive'
return x > 0
def negative(x):
'must be negative'
return x < 0
def ensure(func):
'Decorator that enforces contracts on function arguments (if present)'
return_check = func.__annotations__.get('return',None)
arg_checks = [(name,func.__annotations__.get(name))
for name in func.__code__.co_varnames]
@wraps(func)
def assert_call(*args):
for (name,check),value in zip(arg_checks,args):
if check:
assert check(value),"%s %s" % (name, check.__doc__)
result = func(*args)
if return_check:
assert return_check(result),"return %s" % (return_check.__doc__)
return result
return assert_call
# Example use
@ensure
def foo(a:positive, b:negative) -> positive:
return a-b
If you do this, you'll see behavior like this:
>>> foo(2,-3)
5
>>> foo(2,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "ensure.py", line 22, in assert_call
assert check(value),"%s %s" % (name, check.__doc__)
AssertionError: b must be negative
I should note that the above example needs to be fleshed out more to work properly with default arguments, keyword arguments, and other details. It's only a sketch of an idea.
Now, whether or not this is a good idea or not, I just don't know. I'm inclined to agree with Brandon that the lack of composability is a problem--especially if annotations start to be used by different libraries for different purposes. I also wonder if something like this contract idea couldn't be accomplished through decorators instead. For example, making a decorator that was used like this (implementation left as an exercise):
@ensure(a=positive,b=negative)
def foo(a,b):
return a-b
A historial note, I've always kind of felt that function annotations were an outgrowth of discussions about "optional static typing" that the Python community had more than 10 years ago. Whether that was the original motivation or not, I just don't know.
I will play the curmudgeon, and recommend against using the feature. Hopefully it will someday be removed. Python has so far done a great job of deploying features that are attractive, orthogonal, and that can be stacked — function decorators are a great example: if I use three different libraries that all want me to decorate my function, the result looks rather clean:
@lru_cache(max_items=5)
@require_basic_auth
@view('index.html')
def index(…):
⋮
But this newfangled awkward “annotations” feature takes Python in the opposite direction: because you can only annotate a given function exactly once, it breaks completely the ability to compose solutions out of various pieces. If you had two libraries that each wanted you to annotate the same function on their behalf, then, from what I can see, you would be completely stymied.
精彩评论