Why does accessing the class attribute foo
fail when building a tuple with non-zero length only?
class Foo:
foo = 42
bar_ok1 = (foo for _ in range(10))
bar_ok2 = tuple(foo for _ in [])
bar_fail1 = tuple(foo for _ in range(10))
bar_fail2 = tuple(foo for _ in [0, 1, 2])
Traceback (most recent call last):
File "main.py", line 1, in <module>
class Foo:
File "main.py", line 7, in Foo
bar_fail1 = tuple(foo for _ in range(10))
File "main.py", line 7, in <genexpr>
bar_fail1 = tuple(foo for _ in range(10))
NameError: name 'foo' is not defined
That's because bar_ok1
is not evaluated yet, as it defines a generator, and the foo value is not accessed on class definition. The foo value is also not accessed for bar_ok2
, as does it not perform the iteration at all (empty list).
In contrast, the bar_fail* attributes are evaluated on class definition.
Run the following and you will notice it fails for bar_ok1:
class Foo:
foo = 42
bar_ok1 = (foo for _ in range(10))
bar_ok2 = tuple(foo for _ in [])
#bar_fail1 = tuple(foo for _ in range(10))
#bar_fail2 = tuple(foo for _ in [0, 1, 2])
list(Foo.bar_ok1)
list(Foo.bar_ok2)
list(Foo.bar_ok2)
will produce an empty list, as there are no elements to loop over and no reason to check the foo value.