diff options
author | Damien George <damien@micropython.org> | 2022-05-03 10:38:15 +1000 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2022-05-03 16:38:43 +1000 |
commit | 590de399f01cd08aa4825b26b91785e07abcf68c (patch) | |
tree | e5c2a629ec2f3d032f5d85803625ffdaf109d21e /tests | |
parent | a21fd7cc21270c8b286129a6fe79025c57b33102 (diff) | |
download | micropython-590de399f01cd08aa4825b26b91785e07abcf68c.tar.gz micropython-590de399f01cd08aa4825b26b91785e07abcf68c.zip |
py/emitcommon: Don't implicitly close class vars that are assigned to.
When in a class body or at the module level don't implicitly close over
variables that have been assigned to.
Fixes issue #8603.
Signed-off-by: Damien George <damien@micropython.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/basics/scope_class.py | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/tests/basics/scope_class.py b/tests/basics/scope_class.py new file mode 100644 index 0000000000..9c519695dc --- /dev/null +++ b/tests/basics/scope_class.py @@ -0,0 +1,77 @@ +# test scoping rules that involve a class + +# the inner A.method should be independent to the local function called method +def test1(): + def method(): + pass + + class A: + def method(): + pass + + print(hasattr(A, "method")) + print(hasattr(A(), "method")) + + +test1() + + +# the inner A.method is a closure and overrides the local function called method +def test2(): + def method(): + return "outer" + + class A: + nonlocal method + + def method(): + return "inner" + + print(hasattr(A, "method")) + print(hasattr(A(), "method")) + return method() # this is actually A.method + + +print(test2()) + + +# a class body will capture external variables by value (not by reference) +def test3(x): + class A: + local = x + + x += 1 + return x, A.local + + +print(test3(42)) + + +# assigning to a variable in a class will implicitly prevent it from closing over a variable +def test4(global_): + class A: + local = global_ # fetches outer global_ + global_ = "global2" # creates class attribute + + global_ += 1 # updates local variable + return global_, A.local, A.global_ + + +global_ = "global" +print(test4(42), global_) + + +# methods within a class can close over variables outside the class +def test5(x): + def closure(): + return x + + class A: + def method(): + return x, closure() + + closure = lambda: x + 1 # change it after A has been created + return A + + +print(test5(42).method()) |