Reputation: 5812
I would like doing:
class Whatevs(object):
foo = 3
bar = foo * 3
def __init__(self):
# enhance!
or How acan I make it possible to work correctly. ;)
EDIT:
Ok, it turns out that that is not the problem, the above works fine, this though:
class Whatevs(object):
foo = 3
zap = list(foo for _ in range(10))
Oh you, Python! I can come up with some workarounds, but can someone explain to me what is going on precisely? Why can't the generator access the class variables?
Upvotes: 4
Views: 107
Reputation: 304137
A general solution is to wrap in a lambda function, works the same way in Python2 and Python3
class Whatevs(object):
foo = 3
zap = (lambda foo=foo:list(foo for _ in range(10)))()
Upvotes: 1
Reputation: 12755
You could try:
class Whatevs(object):
foo = 3
zap = [foo] * 10
or even:
class Whatevs(object):
foo = 3
zap = [foo for _ in range(10)]
The reason is that classes in Python have their own namespace. Scopes introduced into this namespace do not have access to this namespace, thus, from the scope of your generator expression, you cannot access the variables inside Whatevs
' namespace.
My list comprehension doesn't introduce a new scope - at least in Python 2.x. In Python 3.x, this has changed, so there also my option 2 wouldn't work.
Upvotes: 1
Reputation: 95652
A generator comprehension is actually shorthand for defining a generator explicitly. Behind the scenes what you are trying to write is equivalent to:
class Whatevs(object):
foo = 3
def _gen():
for _ in range(10):
yield foo
zap = list(_gen())
Unfortunately you cannot access scoped variables like foo
from inside a generator or a function defined in the class body (and you can't use Whatevs.foo
because Whatevs
doesn't exist yet.
One option is to move the code outside the class body:
class Whatevs(object):
foo = 3
Whatevs.zap = list(Whatevs.foo for _ in range(10))
Another option is to turn foo into a parameter:
def _init_zap(foo):
return list(foo for _ in range(10))
class Whatevs(object):
foo = 3
zaps = _init_zap(foo)
In Python 2.x a list comprehension works here, but one of the changes for Python 3.x was that list comprehensions also use a separate scope (i.e. a hidden function) just like generator comprehensions, so a list comprehension will also break in Python 3.
Upvotes: 4