2

I have a class with some class variables:

import itertools

class MyClass:
    _ORIENTATIONS = ['F', 'L', 'B', 'R']
    _ORIENTATION_PERMUTATIONS = [
        ''.join(p) for i in range(1,
                                  len(_ORIENTATIONS) + 1)
        for p in itertools.permutations(_ORIENTATIONS, r=i)
    ]

    _ORIENTATIONS_METAVAR = '{F,L,B,R}'
    _ORIENTATION_PERMUTATIONS_METAVAR = '{}_PERMUTATION'.format(
        _ORIENTATIONS_METAVAR)

    def __init__():
         pass

This piece of code works in python2 but in python3 I get a NameError: name '_ORIENTATIONS' is not defined.

Why?

skalkoto
  • 159
  • 5
  • This is interesting. I was able to simplify this example considerably. Basically the problem occurs when the *second* `for` in the comprehension attempts to refer to the class variable. If the order is reversed, or if there is only one `for`, the problem does not occur. It seems as if the second `for` is evaluated in a different scope from the first. I assume this is a well-known issue, but it is unintuitive. – Tom Karzes Nov 13 '20 at 06:22
  • See also https://stackoverflow.com/questions/13905741/accessing-class-variables-from-a-list-comprehension-in-the-class-definition – Dennis Nov 13 '20 at 06:28
  • Here's a workaround (with a simplified example): Suppose you have `x = [1, 2, 3]`, followed by `y = [p for i in range(3) for p in x]`. This gives an "`x` not defined" error. But you can change it to: `y = (lambda x: [p for i in range(3) for p in x])(x)` and it works. The `lambda` captures the value of `x`, eliminating the scope problem in the `for`. – Tom Karzes Nov 13 '20 at 06:31

0 Answers0