Path: csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!news.albasani.net!feeder.news-service.com!news2.euro.net!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'instance': 0.05; 'sure.': 0.05; 'definitions': 0.07; 'method,': 0.07; 'see:': 0.07; 'python': 0.07; '>>>>': 0.09; 'defined,': 0.09; 'definitions.': 0.09; 'foo': 0.09; 'function:': 0.09; 'instance.': 0.09; 'nameerror:': 0.09; 'namespace': 0.09; 'prefix': 0.09; 'sun,': 0.09; 'pm,': 0.11; 'this:': 0.11; 'def': 0.13; 'received:74.125.82.44': 0.14; 'received:mail-ww0-f44.google.com': 0.14; 'wrote:': 0.14; 'defined': 0.15; '"def"': 0.16; 'a()': 0.16; 'cogently': 0.16; 'consulted': 0.16; 'docs.': 0.16; 'scopes': 0.16; 'subject:Namespaces': 0.16; 'subject:classes': 0.16; '\xc2\xa0i': 0.16; '\xc2\xa0if': 0.16; 'traceback': 0.16; '(most': 0.16; 'url:blog': 0.18; 'cc:2**0': 0.20; 'cheers,': 0.20; 'variable': 0.21; 'header:In-Reply-To:1': 0.22; 'cc:addr:python- list': 0.22; 'trying': 0.23; 'last):': 0.23; 'referring': 0.23; 'vs.': 0.23; "i'm": 0.26; 'chris': 0.27; 'object': 0.27; 'tried': 0.27; 'function': 0.27; 'message-id:@mail.gmail.com': 0.28; 'missed': 0.29; 'class': 0.29; 'answered': 0.29; 'class.': 0.29; 'variables': 0.29; 'cc:addr:python.org': 0.31; '17,': 0.31; 'argue': 0.31; 'differences': 0.31; 'fails.': 0.31; 'nested': 0.31; 'semantics': 0.31; 'it.': 0.31; 'however,': 0.31; '...': 0.32; 'skip:" 10': 0.34; 'requires': 0.35; 'face': 0.35; 'print': 0.35; '"",': 0.35; 'explicit': 0.35; 'function.': 0.35; 'problems': 0.37; 'some': 0.37; 'url:python': 0.37; 'apr': 0.38; 'received:google.com': 0.38; 'but': 0.38; 'url:org': 0.38; 'so,': 0.38; 'set': 0.39; 'could': 0.39; 'add': 0.39; 'works': 0.40; 'would': 0.40; 'header:Received:5': 0.40; 'might': 0.40; 'order': 0.61; '2011': 0.62; 'it)': 0.68; 'apologize': 0.75; '"foo"': 0.84; '12:30': 0.84; 'inheritance,': 0.91 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rebertia.com; s=google; h=domainkey-signature:mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type :content-transfer-encoding; bh=LnTzY40Ki2IsIDUd04zNYViP7CuoSwhcd9PAhWSEP9I=; b=adio0hhp2fKbS2mDW7glKdlES6RNwG7wBRcJN0HMhU7r9WAKFMBit2JWaqMikVKR13 V+ANq7c/pAGAIIyz4C2zA7GN6q3JyXQTRYJJ6Tx3E+vbQLGCwDpnpIS+Re2XYesKzVzs aFuyBF7EJ2fFMFpikQbz6xOLvdmcvIBbWjsh4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=rebertia.com; s=google; h=mime-version:sender:in-reply-to:references:date :x-google-sender-auth:message-id:subject:from:to:cc:content-type :content-transfer-encoding; b=KzFEpVUxmj4P8Zyh9rxrSkPKm3YK9PvId/1HMKjE+RJQQ20RqLd/+QPIT2stO8Z4+c 6mJ3zKUm/qp/hh68rJQNUjmkB/4MsDByRIGn9JtjWSJ85mqjVgMW3ZULrAwgj7CLEsMW ilOlsTg6mkbdtBmqvieX54KlY50Qpe4o6ATaQ= MIME-Version: 1.0 Sender: chris@rebertia.com In-Reply-To: References: Date: Sun, 17 Apr 2011 12:56:23 -0700 X-Google-Sender-Auth: zDPWj_hE1fPRiOaFp4C1TWMeXuU Subject: Re: Namespaces in functions vs classes From: Chris Rebert To: Gerald Britton Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Cc: "python-list \(General\)" X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 92 NNTP-Posting-Host: 82.94.164.166 X-Trace: 1303070185 news.xs4all.nl 81482 [::ffff:82.94.164.166]:58172 X-Complaints-To: abuse@xs4all.nl Xref: x330-a1.tempe.blueboxinc.net comp.lang.python:3424 On Sun, Apr 17, 2011 at 12:30 PM, Gerald Britton wrote: > I apologize if this has been answered before or if it is easy to find > in the docs. (I couldn't find it but might have missed it) > > I'm trying to understand the differences between namespaces in class > definitions vs. function definitions. =C2=A0Consider this function: > >>>> def a(): > ... =C2=A0 =C2=A0 foo =3D 'foo' > ... =C2=A0 =C2=A0 def g(x): > ... =C2=A0 =C2=A0 =C2=A0 =C2=A0 return foo > ... =C2=A0 =C2=A0 print g(1) > ... >>>> a() > foo >>>> > > Now, I replace the first "def" with "class": > >>>> class a(): > ... =C2=A0 =C2=A0 foo =3D 'foo' > ... =C2=A0 =C2=A0 def g(x): > ... =C2=A0 =C2=A0 =C2=A0 =C2=A0 return foo > ... =C2=A0 =C2=A0 print g(1) > ... > Traceback (most recent call last): > =C2=A0File "", line 1, in > =C2=A0File "", line 5, in a > =C2=A0File "", line 4, in g > NameError: global name 'foo' is not defined > > So, the variable "foo" is not available inside the function inside > class as it is inside the (inner) function. =C2=A0I figured this was just > because the class was still being defined, so I tried this: > >>>> class a(): > ... =C2=A0 =C2=A0 foo =3D 'foo' > ... =C2=A0 =C2=A0 def g(x): > ... =C2=A0 =C2=A0 =C2=A0 =C2=A0 return foo > ... >>>> x =3D a() >>>> x.g() > Traceback (most recent call last): > =C2=A0File "", line 1, in > =C2=A0File "", line 4, in g > NameError: global name 'foo' is not defined >>>> > > which still fails. =C2=A0I had expected that "foo" would be available > within the namespace of the object instance. =C2=A0I was wrong. =C2=A0For= my > final attempt, I add the prefix "a." to my use of "foo" > >>>> class a(): > ... =C2=A0 =C2=A0 foo =3D 'foo' > ... =C2=A0 =C2=A0 def g(x): > ... =C2=A0 =C2=A0 =C2=A0 =C2=A0 return a.foo > ... >>>> x =3D a() >>>> x.g() > 'foo' > > So, this works and I can use it. =C2=A0However, =C2=A0I would like a deep= er > understanding of why I cannot use "foo" as an unqualified variable > inside the method in the class. =C2=A0If Python allowed such a thing, wha= t > problems would that cause? Class-level scope is simply never consulted when looking up unqualified names in methods. When looking up such name from within a method, the following scopes are consulted, in order (ignoring some subtleties): 1. Local variables 2. Variables in nested functions 3. Global variables 4. Built-ins For "workarounds" for this, see: http://mail.python.org/pipermail/python-list/2009-December/1228354.html As to why Python works this way, I'm not sure. However, one could cogently argue that this requires you to be more explicit about what the scope is of the name you're referring to; which set of semantics you desire in the face of inheritance, monkey-patching, and instance variable shadowing makes this trickier than you might otherwise think. Cheers, Chris -- http://blog.rebertia.com