Minimal example
class foo:
loadings = dict(hi=1)
if 'hi' in loadings:
print(loadings['hi'])
# works
print({e : loadings[e] for e in loadings})
# NameError global name 'loadings' not defined
I tried referencing the class namespace as well but that isn't working either
class foo:
loadings = dict(hi=1)
if 'hi' in loadings:
print(loadings['hi'])
#works
print({e : foo.loadings[e] for e in foo.loadings})
#NameError: name 'foo' is not defined
And of course, this works as expected
class foo:
loadings = dict(hi=1)
if 'hi' in loadings:
print(loadings['hi'])
print({e : foo.loadings[e] for e in foo.loadings})
I want to understand why this scope issue is happening then, if I am trying to do something insane understand the best way to do it otherwise. My feeling was that the first code snip should have worked as is, but of course it does not.
The goal
I am creating a DataManager class/module for some csv/json files along with canned database queries, a one stop shop for my program and obtaining data. There is some static data and some dynamic data so it seemed like a great use of static and non-static data members in the same class. While I understand that these could be module level variables, I like the concept of having static class data members (possibly because of a bias from Java). Any help is much appreciated
My solution (for now)
I ended up unfurling the list comprehension to stay in class scope, in the above it would become something like this
class foo:
loadings = dict(hi=1)
temp = dict()
for e in loadings:
temp[e] = loadings[e] # keep in mind this is a minimal example, I probably wouldn't do (just) this
print(temp) # works
del temp
It is not pretty but it works for now
Per the Name and Binding docs:
The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods – this includes comprehensions and generator expressions since they are implemented using a function scope. This means that the following will fail:
class A: a = 42 b = list(a + i for i in range(10))
See this answer for more details.
In Python2, it is possible to use list comprehensions, since they were implemented without using a function scope:
dict([(e,loadings[e]) for e in loadings])
But this code would break if run in Python3. So here is an alternative workaround which would work in Python2 and Python3:
class Foo:
def loadings():
load = dict(hi=1)
if 'hi' in load:
print(load['hi'])
print({e:load[e] for e in load})
return load
loadings = loadings()
print(Foo.loadings)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With