From 590de399f01cd08aa4825b26b91785e07abcf68c Mon Sep 17 00:00:00 2001 From: Damien George Date: Tue, 3 May 2022 10:38:15 +1000 Subject: 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 --- tests/basics/scope_class.py | 77 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 tests/basics/scope_class.py (limited to 'tests/basics') 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()) -- cgit v1.2.3