From 4da3bbd1acbe141c4533ccb7cf3862353b96b41e Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Sun, 10 Apr 2011 22:05:30 +1000 Subject: [PATCH] Updated given statement torture test to show why renaming strategies are flawed --- pep-3150.txt | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/pep-3150.txt b/pep-3150.txt index a96ed1b8d..e8a9d17d3 100644 --- a/pep-3150.txt +++ b/pep-3150.txt @@ -314,16 +314,25 @@ code at module, class and function scope:: assert d[42] == 42 given: d = b assert "d" not in locals() + y = y given: + x = 42 + def f(): pass + y = locals("x"), f.__name__ + assert "x" not in locals() + assert "f" not in locals() + assert y == (42, "f") Most naive implementations will choke on the first complex assignment, while less naive but still broken implementations will fail when -the torture test is executed at class scope. +the torture test is executed at class scope. Renaming based strategies +struggle to support ``locals()`` correctly and also have problems with +class and function ``__name__`` attributes. And yes, that's a perfectly well-defined assignment statement. Insane, you might rightly say, but legal:: >>> def f(x): return x - ... + ... >>> x = 42 >>> b = {} >>> a = b[f(a)] = x @@ -349,6 +358,10 @@ two reasons mentioned in the Torture Test section above: * Return-based semantics struggle with complex assignment statements like the one in the torture test +The second thought is generally some kind of hidden renaming strategy. This +also creates problems, as Python exposes variables names via the ``locals()`` +dictionary and class and function ``__name__`` attributes. + The most promising approach is one based on symtable analysis and copy-in-copy-out referencing semantics to move any required name bindings between the inner and outer scopes. The torture test above @@ -371,6 +384,16 @@ would then translate to something like the following:: # Nothing to copy out (not an assignment) _anon2() assert "d" not in locals() + def _anon3() # Nothing to copy in (no references to other variables) + x = 42 + def f(): pass + y = locals("x"), f.__name__ + y = y # Assuming no optimisation of special cases + return y # 'y' reference copied out + y = _anon3() + assert "x" not in locals() + assert "f" not in locals() + assert y == (42, "f") However, as noted in the abstract, an actual implementation of this idea has never been tried. @@ -417,7 +440,7 @@ Copyright This document has been placed in the public domain. - + .. Local Variables: mode: indented-text