On Jan 4, 2016, at 19:08, Emanuel Barry <vgr255@live.ca> wrote:

Output from both 3.4.1 and 3.5.0:

>>> def foo(): pass
>>> foo.__annotations__
{}

Probably an oversight. I'm also not a C expert, but func_get_annotations (line 396 and onwards in funcobject.c) explicitely returns a new, empty dict if the function doesn't have any annotations (unlike all the other slots, like __defaults__ or __kwdefaults__, which merely return None if they're not present).

But that code implies if you just create a new function object and never check its __annotations__, it's not wasting any space for them. Otherwise, it wouldn't have to check for NULL there.

We can't test this _directly_ from Python, but with a bit of ctypes hackery and funcobject.h, we can define a PyFunctionObject(Structure)... or, keeping things a bit more concise but a lot more hacky for the purposes of email:

    def func(): pass
    pf = cast(id(func), POINTER(c_voidp))
    assert pf[2] == id(func.__code__)
    assert not pf[12]
    f.__annotations__
    assert pf[12]

So it is indeed NULL until you check it, and then it becomes something (an empty dict).