I want to construct a dict as a class variable using another class variable.
This does work in a loop (see order1
below), but not in a dict comprehension (see order2
below). I get an error message that choices
was not defined.
A list comprehension, however, does work (see Edit: In fact, order3
), but that's not what I want.order3
also gives an error, but on invocation, not on definition, because it defines a generator object, not a list.
class Foo():
ALICE = 'TXT42'
BOB = 'TXT4711'
CHARLIE = 'TXT23'
# List of lists for usage in a Django ChoiceField
choices = (
(ALICE, 'Alice'),
(BOB, 'Bob'),
(CHARLIE, 'Charlie'),
)
# Now I want to define an order for my constants in a dict, with
# order[ALICE] < order[BOB] < order[CHARLIE]
# This works, but is clumsy
order1 = {}
for i in range(len(choices)):
order1[choices[i][0]] = i
# This gives an error (but works if 'choices' is global):
# "NameError: global name 'choices' is not defined"
order2 = { choices[i][0]: i for i in range(len(choices)) }
# This gives a list of dicts, not a dict (but doesn't throw an error)
# My mistake: it gives a generator object. It will throw the same
# error, if you try to access it or make it a list,
# e.g. order3 = list(...)
order3 = ( { choices[i][0]: i } for i in range(len(choices)) )
When I try the whole code in a function definition instead of a class, there is no error. It also works when choices
really is a global variable, but not when it is a class variable.
Apparently, there is a small difference in the possibilities of a list comprehension and a dict comprehension in the context of class variables. I consider this a bug for now, but feel free to give another explanation.
Python versions tried: 2.7.10 and 3.4.3 under Debian GNU/Linux
Edit: Thanks to @BrenBarn for finding the duplicate I didn't find. It explains the problem I encountered here. It's not a bug, but not really a feature either. ;-)