473,387 Members | 1,691 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Is this a bug, or is it me?

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?
Jan 17 '08 #1
18 1372
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
Jan 17 '08 #2
On Jan 17, 2008 10:05 AM, <cp*********@gmail.comwrote:
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***************@gmail.com>
Jan 17 '08 #3
On Jan 17, 2008 10:23 AM, Neil Cerutti <mr********@gmail.comwrote:
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***************@gmail.com>
Jan 17 '08 #4
>
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...
Jan 17 '08 #5
"Neil Cerutti" <mr********@gmail.comwrites:
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.
Jan 17 '08 #6
cp*********@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.
Jan 17 '08 #7
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
Jan 17 '08 #8
On Jan 17, 2008 10:44 AM, Hrvoje Niksic <hn*****@xemacs.orgwrote:
"Neil Cerutti" <mr********@gmail.comwrites:
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***************@gmail.com>
Jan 17 '08 #9
On Jan 17, 4:59 pm, "Neil Cerutti" <mr.ceru...@gmail.comwrote:
On Jan 17, 2008 10:44 AM, Hrvoje Niksic <hnik...@xemacs.orgwrote:
"Neil Cerutti" <mr.ceru...@gmail.comwrites:
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!
Jan 17 '08 #10
On Jan 17, 2008 11:08 AM, <co*********@gmail.comwrote:
On Jan 17, 4:59 pm, "Neil Cerutti" <mr.ceru...@gmail.comwrote:
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.

Ah, that explains why my random suggestion worked but was not
helpful :) I feel like I am learning a lot today!
Me, too. Especially about wrongly oversimplifying stuff that's
complicated. My statement above isn't exactly right, since generator
expressions usually *can* access stuff in the enclosing local scope.
They wouldn't be very useful if they couldn't.

--
Neil Cerutti <mr***************@gmail.com>
Jan 17 '08 #11
I filed a bug report, and here is the short answer to my question:
genexps are code blocks, and code blocks cannot see variables in class
scopes. Congrats to Neil Cerutti who figured it out.

Now here is another one for your enjoyment:

class C:
@staticmethod
def f1(): pass
F = { '1' : f1 }

C().F['1']()
>>TypeError: 'staticmethod' object is not callable

What do you think of this one?
Jan 18 '08 #12
On Jan 18, 2008 2:01 PM, <cp*********@gmail.comwrote:
Now here is another one for your enjoyment:

class C:
@staticmethod
def f1(): pass
F = { '1' : f1 }

C().F['1']()
>TypeError: 'staticmethod' object is not callable


What do you think of this one?
I'll get the ball rolling again, and hopefully it won't roll over me. ;)

The decoration is setting the class type's f1 attribute correctly, but
doing something strange in the local namespace.
>>class C:
.... @staticmethod
.... def f1(): pass
.... print f1
....
<staticmethod object at 0x00A69A70>
>>print C.f1
<function f1 at 0x00A60830>

The class statement's local namespace is pretty strange. I think I
mightl go back to pretending there isn't one.

--
Neil Cerutti
Jan 18 '08 #13
Neil Cerutti <mr********@gmail.comwrote:
>The decoration is setting the class type's f1 attribute correctly, but
doing something strange in the local namespace.
>>>class C:
... @staticmethod
... def f1(): pass
... print f1
...
<staticmethod object at 0x00A69A70>
>>>print C.f1
<function f1 at 0x00A60830>
It might help understand the problem if you do the something similar
without using @staticmethod:

class C:
def f1(): pass
print "f1", f1

print "C.f1", C.f1
print "C().f1", C().f1

You should see output something like:

f1 <function f1 at 0x2ac08d6377d0>
C.f1 <unbound method C.f1>
C().f1 <bound method C.f1 of <__main__.C instance at 0x2ac08d634cf8>>
>The class statement's local namespace is pretty strange. I think I
mightl go back to pretending there isn't one.
When class attributes are referenced, functions are turned into unbound
methods and staticmethod objects get turned into functions.

Something like the following should work:

class C:
def f1(): pass
F = {'1': f1}
f1 = staticmethod(f1) # if you need C.f1() to work as well

If you don't need C.f1() to work you can replace the last line with
"del f1".

Ross Ridge

--
l/ // Ross Ridge -- The Great HTMU
[oo][oo] rr****@csclub.uwaterloo.ca
-()-/()/ http://www.csclub.uwaterloo.ca/~rridge/
db //
Jan 18 '08 #14
On 1/18/08, Ross Ridge <rr****@caffeine.csclub.uwaterloo.cawrote:
Neil Cerutti <mr********@gmail.comwrote:
The decoration is setting the class type's f1 attribute correctly, but
doing something strange in the local namespace.
>>class C:
... @staticmethod
... def f1(): pass
... print f1
...
<staticmethod object at 0x00A69A70>
>>print C.f1
<function f1 at 0x00A60830>
The class statement's local namespace is pretty strange. I think I
mightl go back to pretending there isn't one.

When class attributes are referenced, functions are turned into unbound
methods and staticmethod objects get turned into functions.
OK, thank you. So the local namespace is just fine, you just can't
call the staticmethod using that name directly.

--
Neil Cerutti <mr***************@gmail.com>
Jan 18 '08 #15
cptnwillard wrote:
I filed a bug report, and here is the short answer to my question:
genexps are code blocks, and code blocks cannot see variables in class
scopes. Congrats to Neil Cerutti who figured it out.

Now here is another one for your enjoyment:

class C:
@staticmethod
def f1(): pass
F = { '1' : f1 }

C().F['1']()
>>>TypeError: 'staticmethod' object is not callable


What do you think of this one?
If you want it to be callable you can subclass:
>>class static(staticmethod):
.... def __call__(self, *args, **kw):
.... return self.__get__(object)(*args, **kw)
....
>>class A(object):
.... @static
.... def f(x="yadda"): print x
.... f()
....
yadda
>>A.f()
yadda
>>A().f()
yadda

Peter
Jan 18 '08 #16
On Fri, 18 Jan 2008 11:01:29 -0800, cptnwillard wrote:
Now here is another one for your enjoyment:

class C:
@staticmethod
def f1(): pass
F = { '1' : f1 }

C().F['1']()
>>>TypeError: 'staticmethod' object is not callable


What do you think of this one?

The trick is to realise that the object stored in the dict is not the
same object that you get back when you call C.f1().

>>C().f1 is C().F['1']
False
>>C().f1
<function f1 at 0xb7ec4a04>
>>C().F['1']
<staticmethod object at 0xb7ee57dc>
What you've done in inadvertently bypassed Python's method-access
mechanism:
>>C.__dict__['f1'] is C().f1
False
>>C.__dict__['f1'] is C().F['1']
True
Analogous results will occur without the decorator (although the error
you get is different):
>>class D:
.... def foo(self): pass
.... F = {'oo': foo}
....
>>D().foo()
D.F['oo']()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes exactly 1 argument (0 given)
So... not a bug, a feature :)


--
Steven
Jan 18 '08 #17
On Jan 18, 7:01*pm, cptnwill...@gmail.com wrote:
I filed a bug report, and here is the short answer to my question:
genexps are code blocks, and code blocks cannot see variables in class
scopes. Congrats to Neil Cerutti who figured it out.

Now here is another one for your enjoyment:

class C:
* * * * @staticmethod
* * * * def f1(): pass
* * * * F = { '1' : f1 }

C().F['1']()
>TypeError: 'staticmethod' object is not callable

What do you think of this one?
It's normal, the staticmethod decorator's role is to 'flag up' the
method as static for further processing when type(C).__new__ is
called.

--
Arnaud

Jan 19 '08 #18
On Jan 17, 3:55*pm, Peter Otten <__pete...@web.dewrote:
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
[...]
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
This is exactly the problem:

class A:
a = 42
list(a for _ in "a")

is in fact compiled as:

class A:
a = 42
def _genexpr():
for _ in "a":
yield a
list(_genexpr())

Except that the _genexpr function is not bound to any name, just left
on the stack for list to pick up next. This can be checked using the
dis module.
Trying it yields exactly the same error:
>>class A(object):
... a = 42
... def _genexpr():
... for _ in "a":
... yield a
... list(_genexpr())
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in A
File "<stdin>", line 5, in _genexpr
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.
It isn't necessary to do that to fix the problem. I think that the
semantics of genexprs concerning free variables are confusing (and
this is a good example!). I suggested a change on python-ideas a
while ago that would solve this particular issue.

In short, all free variables inside a generator expression could be
bound at the creation of the expression, not when it is evaluated.

So for example

((c, f(x)) for x in L)

would be the equivalent of what one could currently write as.

(lambda _c, _f: ((c, f(x) for x in L))(c, f)

so your example would compile to:

class A:
a = 42
def _genexpr(_a):
for _ in "a":
yield _a
list(_genexpr(a))

Which would behave as the OP expected (and I think as it is reasonable
to expect if one doesn't know about how genexprs are implemented).

Other reasons why I think this is desirable are exposed (maybe not
very convincingly) in this post to python-ideas.

http://mail.python.org/pipermail/pyt...er/001260.html

--
Arnaud

Jan 19 '08 #19

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: William C. White | last post by:
Does anyone know of a way to use PHP /w Authorize.net AIM without using cURL? Our website is hosted on a shared drive and the webhost company doesn't installed additional software (such as cURL)...
2
by: Albert Ahtenberg | last post by:
Hello, I don't know if it is only me but I was sure that header("Location:url") redirects the browser instantly to URL, or at least stops the execution of the code. But appearantely it continues...
3
by: James | last post by:
Hi, I have a form with 2 fields. 'A' 'B' The user completes one of the fields and the form is submitted. On the results page I want to run a query, but this will change subject to which...
0
by: Ollivier Robert | last post by:
Hello, I'm trying to link PHP with Oracle 9.2.0/OCI8 with gcc 3.2.3 on a Solaris9 system. The link succeeds but everytime I try to run php, I get a SEGV from inside the libcnltsh.so library. ...
1
by: Richard Galli | last post by:
I want viewers to compare state laws on a single subject. Imagine a three-column table with a drop-down box on the top. A viewer selects a state from the list, and that state's text fills the...
4
by: Albert Ahtenberg | last post by:
Hello, I have two questions. 1. When the user presses the back button and returns to a form he filled the form is reseted. How do I leave there the values he inserted? 2. When the...
1
by: inderjit S Gabrie | last post by:
Hi all Here is the scenerio ...is it possibly to do this... i am getting valid course dates output on to a web which i have designed ....all is okay so far , look at the following web url ...
2
by: Jack | last post by:
Hi All, What is the PHP equivilent of Oracle bind variables in a SQL statement, e.g. select x from y where z=:parameter Which in asp/jsp would be followed by some statements to bind a value...
3
by: Sandwick | last post by:
I am trying to change the size of a drawing so they are all 3x3. the script below is what i was trying to use to cut it in half ... I get errors. I can display the normal picture but not the...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.