How does the declaration of a class in Python handle the external scope?

Asked

Viewed 61 times

0

To illustrate, let’s consider this class statement:

x = 1

class Foo:
    a = x
    b = [x]
    c = [x for _ in range(1)]

print(f'x = {x}')  # x = 1
print(f'Foo.a = {Foo.a}')  # Foo.a = 1
print(f'Foo.b = {Foo.b}')  # Foo.b = [1]
print(f'Foo.c = {Foo.c}')  # Foo.c = [1]

See working on Ideone | Repl.it

This shows that during class declaration the value of x is searched in the global scope, since the scope of the class is not defined. However, if we define a value for x in the class the output changes:

x = 1

class Foo:
    x = 2
    a = x
    b = [x]
    c = [x for _ in range(1)]

print(f'x = {x}')  # x = 1
print(f'Foo.a = {Foo.a}')  # Foo.a = 2
print(f'Foo.b = {Foo.b}')  # Foo.b = [2]
print(f'Foo.c = {Foo.c}')  # Foo.c = [1]

See working on Ideone | Repl.it

The values of Foo.a and Foo.b use the value of Foo.x, but the value of Foo.c continues to consider the x global.

This behavior occurs because in Foo.c is used to comprehensilist on? How, in fact, the interpreter manages the scope during the declaration of a class?

1 answer

1

This is crazy! I found this thread speaking of which, the name is List Comprehensions Leak. The Guido himself explains here.

Different behaviors in python 2 and 3 (based on Guido’s post):

x = 42
a = [x for x in (1, 2, 3)]
print(x) # imprime 3 no py2 e 42 no py3

For you to access the x local cannot use list comprehension,
I think they did it to avoid the one Leak

x = 111

class Foo:
    x = 222
    a = x
    b = [x]

    c = [x for _ in range(1)]

    d = []
    for _ in range(1):
        d.append(x)

print(f'x = {x}')  # x = 111
print(f'Foo.a = {Foo.a}')  # Foo.a = 222
print(f'Foo.b = {Foo.b}')  # Foo.b = [222]
print(f'Foo.c = {Foo.c}')  # Foo.c = [111]
print(f'Foo.d = {Foo.d}')  # Foo.c = [222]

Browser other questions tagged

You are not signed in. Login or sign up in order to post.