I'm trying to create a class which has multiple class-level variables, some of which have calculated values which reference previously declared class-level variables. However, I'm having difficulty referencing the variables at certain points.
My first attempt:
#!/usr/bin/env python
from decimal import Decimal
import math
class Foo(object):
NUM_BUCKETS = 10
BUCKET_SIZE = Decimal(1.0 / NUM_BUCKETS)
BUCKET_LABELS = tuple("BUCKET_{}".format(int(BUCKET_SIZE * i * 100)) for i in xrange(1, NUM_BUCKETS + 1))
print Foo.BUCKET_LABELS
Result:
> python test.py
Traceback (most recent call last):
File "test.py", line 5, in <module>
class Foo(object):
File "test.py", line 8, in Foo
BUCKET_LABELS = tuple("BUCKET_{}".format(int(BUCKET_SIZE * i * 100)) for i in xrange(1, NUM_BUCKETS + 1))
File "test.py", line 8, in <genexpr>
BUCKET_LABELS = tuple("BUCKET_{}".format(int(BUCKET_SIZE * i * 100)) for i in xrange(1, NUM_BUCKETS + 1))
NameError: global name 'BUCKET_SIZE' is not defined
Trying to access the class variable via the class name doesn't work either:
#!/usr/bin/env python
from decimal import Decimal
import math
class Foo(object):
NUM_BUCKETS = 10
BUCKET_SIZE = Decimal(1.0 / NUM_BUCKETS)
BUCKET_LABELS = tuple("BUCKET_{}".format(int(Foo.BUCKET_SIZE * i * 100)) for i in xrange(1, NUM_BUCKETS + 1))
print Foo.BUCKET_LABELS
Result:
> python test2.py
Traceback (most recent call last):
File "test2.py", line 5, in <module>
class Foo(object):
File "test2.py", line 8, in Foo
BUCKET_LABELS = tuple("BUCKET_{}".format(int(Foo.BUCKET_SIZE * i * 100)) for i in xrange(1, NUM_BUCKETS + 1))
File "test2.py", line 8, in <genexpr>
BUCKET_LABELS = tuple("BUCKET_{}".format(int(Foo.BUCKET_SIZE * i * 100)) for i in xrange(1, NUM_BUCKETS + 1))
NameError: global name 'Foo' is not defined
Replacing the reference to BUCKET_SIZE with a hardcoded value fixes the problem; even though there's another class-level variable reference in the same line, it works just fine:
#!/usr/bin/env python
from decimal import Decimal
import math
class Foo(object):
NUM_BUCKETS = 10
BUCKET_SIZE = Decimal(1.0 / NUM_BUCKETS)
BUCKET_LABELS = tuple("BUCKET_{}".format(int(Decimal(0.1) * i * 100)) for i in xrange(1, NUM_BUCKETS + 1))
print Foo.BUCKET_LABELS
Result:
> python test3.py
('BUCKET_10', 'BUCKET_20', 'BUCKET_30', 'BUCKET_40', 'BUCKET_50', 'BUCKET_60', 'BUCKET_70', 'BUCKET_80', 'BUCKET_90', 'BUCKET_100')
Does anybody know the correct way of referencing BUCKET_SIZE in that spot? Is this a bug in Python itself? (I'm running Python 2.7.5, BTW.)