[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

Is this a bug, or is it me?

cptnwillard

1/17/2008 3:06:00 PM

Hello all,
For some reason, the following does not work :


class C:
TYPES = [None]
DICT = {}
for Type in TYPES:
DICT.update((E,Type) for E in [1])

>>> NameError: global name 'Type' is not defined


What do you think? Is this a bug?
19 Answers

cokofreedom

1/17/2008 3:14:00 PM

0

On Jan 17, 4:05 pm, cptnwill...@gmail.com wrote:
> Hello all,
> For some reason, the following does not work :
>
> class C:
> TYPES = [None]
> DICT = {}
> for Type in TYPES:
> DICT.update((E,Type) for E in [1])
>
> >>> NameError: global name 'Type' is not defined
>
> What do you think? Is this a bug?

Do not use those names...really poor choice...

thingydingy = [None]
my = {}
for dingaling in thingydingy:
my.update([(E,dingaling ) for E in [1]])
print my

cptnwillard

1/17/2008 3:22:00 PM

0

On Jan 17, 4:14 pm, cokofree...@gmail.com wrote:
>
> Do not use those names...really poor choice...

This is not the way it looks it my code. I simplified it, with generic
names, in order to point out something that does not work... The only
question here is why?

Neil Cerutti

1/17/2008 3:23:00 PM

0

On Jan 17, 2008 10:05 AM, <cptnwillard@gmail.com> wrote:
> Hello all,
> For some reason, the following does not work :
>
>
> class C:
> TYPES = [None]
> DICT = {}
> for Type in TYPES:
> DICT.update((E,Type) for E in [1])
>
> >>> NameError: global name 'Type' is not defined
>
>
> What do you think? Is this a bug?

You cannot access a class's class variables in it's class-statement
scope, since the name of the type is not bound until after the class
statement is completed.

Try:

class C:
TYPES = [None]
DICT = {}

for Type in C.TYPES:
C.DICT.update((E, Type) for E in [1])

--
Neil Cerutti <mr.cerutti+python@gmail.com>

Neil Cerutti

1/17/2008 3:29:00 PM

0

On Jan 17, 2008 10:23 AM, Neil Cerutti <mr.cerutti@gmail.com> wrote:
> You cannot access a class's class variables in it's class-statement
> scope, since the name of the type is not bound until after the class
> statement is completed.

Arrgh! I hate making the "its" error. But I wanted to add that this
property of Python's class statement bothers me only when I think it
would be good to use class variables as default method argument
values. Luckily, I don't think very often. ;)

--
Neil Cerutti <mr.cerutti+python@gmail.com>

cptnwillard

1/17/2008 3:29:00 PM

0

>
> You cannot access a class's class variables in it's class-statement
> scope, since the name of the type is not bound until after the class
> statement is completed.
>

Thanks for the answer, but then why is there no error with the
variable 'TYPES'? This one is accessed first...

Hrvoje Niksic

1/17/2008 3:44:00 PM

0

"Neil Cerutti" <mr.cerutti@gmail.com> writes:

> You cannot access a class's class variables in it's class-statement
> scope, since the name of the type is not bound until after the class
> statement is completed.

But they are still available as locals, so you can access them using
their names, like this:

>>> class C:
.... a = 1
.... b = 2
.... print a+b
....
3

The question is, why doesn't the OP's code snippet work? It seems
that the generator expression can't read the surrounding locals().
But when you change the generator expression to a list comprehension
using a pair of [] around it, it starts working. Compare:

class C(object):
d = {}
for a in 1, 2, 3:
ignore = list((a, b) for b in (4, 5, 6))

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in C
File "<stdin>", line 4, in <genexpr>
NameError: global name 'a' is not defined

with:

class C(object):
d = {}
for a in 1, 2, 3:
ignore = [(a, b) for b in (4, 5, 6)]

It seems that generator expressions and list comprehensions have
subtly different scoping rules. Whether this is a bug or not is a
good question.

Hrvoje Niksic

1/17/2008 3:45:00 PM

0

cptnwillard@gmail.com writes:

> Hello all,
> For some reason, the following does not work :
>
>
> class C:
> TYPES = [None]
> DICT = {}
> for Type in TYPES:
> DICT.update((E,Type) for E in [1])
>
>>>> NameError: global name 'Type' is not defined
>
>
> What do you think? Is this a bug?

It works if you change the generator expression to a list
comprehension, by adding [] around it. Feels like a bug to me, but
there might be subtleties involved.

Peter Otten

1/17/2008 3:56:00 PM

0

cptnwillard wrote:

> Hello all,
> For some reason, the following does not work :
>
>
> class C:
> TYPES = [None]
> DICT = {}
> for Type in TYPES:
> DICT.update((E,Type) for E in [1])
>
>>>> NameError: global name 'Type' is not defined
>
>
> What do you think? Is this a bug?

Here is a simpler example:

>>> class A:
.... a = 42
.... list(a for _ in "a")
....
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in A
File "<stdin>", line 3, in <genexpr>
NameError: global name 'a' is not defined

The equivalent code using a list comprehension instead of the generator
expression works without complaint:

>>> class A:
.... a = 42
.... [a for _ in "a"]
....
>>>

So it seems that Python gets puzzled by the extra scope introduced by the
genexp, i. e. you are seeing an obscure variant of the following
(expected) behaviour:

>>> class B:
.... a = 42
.... def f(): a
.... f()
....
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in B
File "<stdin>", line 3, in f
NameError: global name 'a' is not defined

I think you should file a bug report, though making the genexp recognizing
the class scope probably isn't worth the effort.

Peter

Neil Cerutti

1/17/2008 3:59:00 PM

0

On Jan 17, 2008 10:44 AM, Hrvoje Niksic <hniksic@xemacs.org> wrote:
> "Neil Cerutti" <mr.cerutti@gmail.com> writes:
>
> > You cannot access a class's class variables in it's class-statement
> > scope, since the name of the type is not bound until after the class
> > statement is completed.
>
> But they are still available as locals, so you can access them using
> their names, like this:
>
> >>> class C:
> ... a = 1
> ... b = 2
> ... print a+b
> ...
> 3

Thanks! I had never tried that before. That actually solved my default
method argument problem.

> The question is, why doesn't the OP's code snippet work? It seems
> that the generator expression can't read the surrounding locals().
> But when you change the generator expression to a list comprehension
> using a pair of [] around it, it starts working. Compare:
>
> class C(object):
> d = {}
> for a in 1, 2, 3:
> ignore = list((a, b) for b in (4, 5, 6))
>
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<stdin>", line 4, in C
> File "<stdin>", line 4, in <genexpr>
> NameError: global name 'a' is not defined
>
> with:
>
> class C(object):
> d = {}
> for a in 1, 2, 3:
> ignore = [(a, b) for b in (4, 5, 6)]
>
> It seems that generator expressions and list comprehensions have
> subtly different scoping rules. Whether this is a bug or not is a
> good question.

Generator expressions, unlike list comprehensions, have their own
scope so that they don't "leak" names to the enclosing scope. The
Python rule forbidding access to the locals of enclosing scopes is
preventing the class names from working in the generator expression.

--
Neil Cerutti <mr.cerutti+python@gmail.com>

cokofreedom

1/17/2008 4:08:00 PM

0

On Jan 17, 4:59 pm, "Neil Cerutti" <mr.ceru...@gmail.com> wrote:
> On Jan 17, 2008 10:44 AM, Hrvoje Niksic <hnik...@xemacs.org> wrote:
>
> > "Neil Cerutti" <mr.ceru...@gmail.com> writes:
>
> > > You cannot access a class's class variables in it's class-statement
> > > scope, since the name of the type is not bound until after the class
> > > statement is completed.
>
> > But they are still available as locals, so you can access them using
> > their names, like this:
>
> > >>> class C:
> > ... a = 1
> > ... b = 2
> > ... print a+b
> > ...
> > 3
>
> Thanks! I had never tried that before. That actually solved my default
> method argument problem.
>
>
>
> > The question is, why doesn't the OP's code snippet work? It seems
> > that the generator expression can't read the surrounding locals().
> > But when you change the generator expression to a list comprehension
> > using a pair of [] around it, it starts working. Compare:
>
> > class C(object):
> > d = {}
> > for a in 1, 2, 3:
> > ignore = list((a, b) for b in (4, 5, 6))
>
> > Traceback (most recent call last):
> > File "<stdin>", line 1, in <module>
> > File "<stdin>", line 4, in C
> > File "<stdin>", line 4, in <genexpr>
> > NameError: global name 'a' is not defined
>
> > with:
>
> > class C(object):
> > d = {}
> > for a in 1, 2, 3:
> > ignore = [(a, b) for b in (4, 5, 6)]
>
> > It seems that generator expressions and list comprehensions have
> > subtly different scoping rules. Whether this is a bug or not is a
> > good question.
>
> Generator expressions, unlike list comprehensions, have their own
> scope so that they don't "leak" names to the enclosing scope. The
> Python rule forbidding access to the locals of enclosing scopes is
> preventing the class names from working in the generator expression.
>
> --
> Neil Cerutti <mr.cerutti+pyt...@gmail.com>

Ah, that explains why my random suggestion worked but was not
helpful :) I feel like I am learning a lot today!