By Ivan Levkivskyi.
For simple names as assignment targets, if in class or module scope,
the annotations are evaluated and stored in a special class or module
attribute :attr:`__annotations__`
-that is a dictionary mapping from variable names to evaluated annotations.
-This attribute is writable and is automatically created at the start
-of class or module body execution, if annotations are found statically.
+that is a dictionary mapping from variable names (mangled if private) to
+evaluated annotations. This attribute is writable and is automatically
+created at the start of class or module body execution, if annotations
+are found statically.
For expressions as assignment targets, the annotations are evaluated if
in class or module scope, but not stored.
# class semantics
class C:
- x: int
+ __foo: int
s: str = "attr"
z = 2
def __init__(self, x):
self.x: int = x
- self.assertEqual(C.__annotations__, {'x': int, 's': str})
+ self.assertEqual(C.__annotations__, {'_C__foo': int, 's': str})
with self.assertRaises(NameError):
class CBad:
no_such_name_defined.attr: int = 0
compiler_annassign(struct compiler *c, stmt_ty s)
{
expr_ty targ = s->v.AnnAssign.target;
+ PyObject* mangled;
assert(s->kind == AnnAssign_kind);
if (s->v.AnnAssign.simple &&
(c->u->u_scope_type == COMPILER_SCOPE_MODULE ||
c->u->u_scope_type == COMPILER_SCOPE_CLASS)) {
+ mangled = _Py_Mangle(c->u->u_private, targ->v.Name.id);
+ if (!mangled) {
+ return 0;
+ }
VISIT(c, expr, s->v.AnnAssign.annotation);
- ADDOP_O(c, STORE_ANNOTATION, targ->v.Name.id, names)
+ /* ADDOP_N decrefs its argument */
+ ADDOP_N(c, STORE_ANNOTATION, mangled, names);
}
break;
case Attribute_kind: