I have a problem understanding what is happening with the outcome of the following pieces of code:
my_str = "outside func"
def func():
my_str = "inside func"
class C():
print(my_str)
print((lambda:my_str)())
my_str = "inside C"
print(my_str)
The output is:
outside func
inside func
inside C
Another piece of code is:
my_str = "not in class"
class C:
my_str = "in the class"
print([my_str for i in (1,2)])
print(list(my_str for i in (1,2)))
The output is:
[‘in the class’, 'in the class’]
['not in class’, 'not in class’]
The question is:
Edit 1:
I think this is different from this question because I humbly think the answers there do not explain this variation:
my_str = "outside func"
def func():
my_str = "inside func"
class C():
print(my_str)
print((lambda:my_str)())
#my_str = "inside C"
print(my_str)
The output is:
inside func
inside func
inside func
Edit 2:
Indeed, this is a duplicate from this question because as Martijn Pieters says:
The answer there states: If a name is assigned to within a class body, almost at the start. You assigned to my_str, making it the same case as y there. Commenting out that line means you are no longer assigning to my_str, making it the same case as x.
There are four scopes here:
When creating a class statement, the class body is executed as a function would and the local namespace of that 'function' is used as the class attributes.
However, a class body is not a scope, and as such behaves differently from functions. In a function body, binding defines scope; assign to a name in a function and it is marked as a local. In a class, assigning to a name makes it a global until you actually do the assignment.
So your first print()
call finds my_str
as a global, because later in the class body you bind to the name. This is a consequence of class bodies not taking part in scopes.
Next, you define a lambda and call it. my_str
is never assigned to in that lambda so it has to be found in a parent scope. Here the class body is not a scope, and the next scope up is the function scope. This is why that line prints inside func
.
Last, you assign to the local name my_str
in the class body, and print that local.
The moment you remove the assignment, the names in the class are treated as non-local; the first and last print()
statements are now equal, and the name is simply looked up according to the normal scoping rules.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With