0

still learning python.

In this code, I can reference v0 and v1 to compute v2 inside the Foo class. So far, so good.

class Foo():

  v0="abcd"
  v1="efgh"
  v2=(v0, v1)
  #v3=[(v0, c) for c in v2]     # NameError: name 'v0' is not defined.
  #v3=[("abcd", c) for c in v2] # Works

print(Foo.v0, Foo.v1, Foo.v2)
#print(Foo.v0, Foo.v1, Foo.v2, Foo.v3)

But if I uncomment the v3=[(v0, c) for c in v2] line, I get an error that states v0 is not defined.

Traceback (most recent call last):
  File "/private/tmp/machin.py", line 1, in <module>
    class Foo():
  File "/private/tmp/machin.py", line 6, in Foo
    v3=[(v0, c) for c in v2]
  File "/private/tmp/machin.py", line 6, in <listcomp>
    v3=[(v0, c) for c in v2]
NameError: name 'v0' is not defined. Did you mean: '.0'?

Strangely enough, v2 does not receive the same treatment and this line works :

    v3=[("abcd", c) for c in v2]

Reading the python doc about classes, scopes and namespaces does not help me to understand what is happening...

So questions :

  1. Why is the variable v0 suddenly out of scope but v2 is still reachable ?
  2. Is there a workaround that does not involve retyping the v0 literal again ? Which one ?
khelwood
  • 55,782
  • 14
  • 81
  • 108
exore
  • 194
  • 11
  • 1
    This is a weird edge case. Essentially, list comprehensions use a local, function scope. But class blocks *do not create enclosing scopes* (this is why you cannot access a variable in a class block from a function/method directly, you have to use `self.whatever`). See the linked duplicate for details. – juanpa.arrivillaga Aug 02 '22 at 17:08
  • 1
    `v2` is still reachable because the leftmost for-clause is evaluated in *the scope where the list comprehension is executed*, not in it's internal scope. It works essentially like passing whatever is in `for x in ` to a function (this is literally what happens underneath the hood, examine the dissasembly of a list comprehension using the `dis` module) – juanpa.arrivillaga Aug 02 '22 at 17:09
  • Thanks both of you, Juanpa.Arrivallaga and @khelwood. I did not find the linked question that is exactly the same as mine. What should I do now ? just delete the my question, or leave it here ? – exore Aug 02 '22 at 17:16
  • It's fine to leave it, but it's up to you – juanpa.arrivillaga Aug 02 '22 at 17:19

0 Answers0