Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Scope and classes

4 views
Skip to first unread message

David

unread,
Aug 18, 2009, 6:47:09 PM8/18/09
to
Hi all,

I'm trying to understand how scopes work within a class definition.
I'll quickly illustrate with an example. Say I had the following class
definition:

class Abc:
message = 'Hello World'

def print_message(self):
print message

>>> instance = Abc()
>>> instance.print_message()
NameError: global name 'message' not defined

My question is, why? message is not defined in print_message, but it
is defined in the enclosing scope (the class)?

Thanks!

Chris Rebert

unread,
Aug 18, 2009, 7:16:07 PM8/18/09
to David, pytho...@python.org

A class' scope is never consulted when resolving variable names in its methods.

The scopes consulted are roughly (and in this order):
1. Local variable scope (i.e. of the current function/method)
2. Enclosing functions (if you have functions nested inside other functions)
3. Globals (i.e. module-level variables)
3. Builtins (i.e. the built-in functions and methods, such as len())

To access class-level variables from within instance methods of the
class, you have 2 options:
A. Use the class name, i.e. Abc.message
B. Reference the class indirectly, i.e. self.__class__.message

Cheers,
Chris
--
http://blog.rebertia.com

David

unread,
Aug 18, 2009, 7:38:15 PM8/18/09
to
On Aug 19, 12:16 am, Chris Rebert <c...@rebertia.com> wrote:

Ah, thanks!

Steven D'Aprano

unread,
Aug 18, 2009, 7:39:38 PM8/18/09
to

It's a deliberate design decision. I don't recall the reasons for it, but
the class namespace is deliberately excluded from the method scope.

The correct way of writing the above is:

class Abc:
message = 'Hello World'
def print_message(self):

print self.message


self.message will first search the instance namespace for an attribute
`message`, then search the class, then any superclasses. If you
specifically want the class attribute, even if the instance masks it with
an instance attribute of the same name, you do this instead:

print self.__class__.message

--
Steven

Jan Kaliszewski

unread,
Aug 18, 2009, 8:10:58 PM8/18/09
to David, pytho...@python.org

Note that when *running* the code that is *inside* print_message() method
called within the global scope, the outer (enclosing) scope is indeed the
global scope (the scope in which e.g. 'instance' name exists; note that
e.g. 'print instance' in that method would be ok).

As Chris wrote, class' scope (contrary to outer function scope) is not
considered as the 'enclosing' scope.

The only ways to reach Abc's attribute 'message' from that method are:
* 'Abc.message'
* 'self.__class__.message'
* 'self.message' (unless there is an instance attribute 'message' which
overrides the class attribute).

Cheers,
*j

--
Jan Kaliszewski (zuo) <z...@chopin.edu.pl>

Jan Kaliszewski

unread,
Aug 18, 2009, 8:17:22 PM8/18/09
to Jan Kaliszewski, David, pytho...@python.org
19-08-2009 o 02:10:58 Jan Kaliszewski <z...@chopin.edu.pl> wrote:

> The only ways to reach Abc's attribute 'message' from that method are:
> * 'Abc.message'
> * 'self.__class__.message'
> * 'self.message' (unless there is an instance attribute 'message' which
> overrides the class attribute).

And of course getattr(Abc), getattr(self.__class__) etc. :-)

David

unread,
Aug 18, 2009, 9:12:39 PM8/18/09
to

Out of 'Abc.message' and 'self.message', which is the favoured
convention? It would be very easy to accidentally override
'self.messages' with an instance attribute!

Ben Finney

unread,
Aug 18, 2009, 9:22:32 PM8/18/09
to
David <david...@googlemail.com> writes:

> Out of 'Abc.message' and 'self.message', which is the favoured
> convention?

It's not a matter of convention. They mean different things, so you use
each depending on what you mean.

> It would be very easy to accidentally override 'self.messages' with an
> instance attribute!

Right. So you use ‘Abc.message’ when you specifically want a class
independent of any instance, and you use ‘self.message’ when you want
the attribute of this instance (with fallback to the usual resolution
order).

--
\ “Any intelligent fool can make things bigger and more complex… |
`\ It takes a touch of genius – and a lot of courage – to move in |
_o__) the opposite direction.” —Albert Einstein |
Ben Finney

Ben Finney

unread,
Aug 18, 2009, 10:01:29 PM8/18/09
to
Ben Finney <ben+p...@benfinney.id.au> writes:

> Right. So you use ‘Abc.message’ when you specifically want a class
> independent of any instance

That's “a class attribute independent of any instance”, of course.

--
\ “Humanity has advanced, when it has advanced, not because it |
`\ has been sober, responsible, and cautious, but because it has |
_o__) been playful, rebellious, and immature.” —Tom Robbins |
Ben Finney

Bruno Desthuilliers

unread,
Aug 19, 2009, 5:18:59 AM8/19/09
to
Chris Rebert a écrit :
(snip)

> To access class-level variables from within instance methods of the
> class, you have 2 options:
> A. Use the class name, i.e. Abc.message
> B. Reference the class indirectly, i.e. self.__class__.message

Or even simpler - *if* there's no synonym instance attribute:

=> self.message

Attribute lookup will try to resolve the attribute name on the class
(and it's parent classes) if it's not found on the instance.

Bruno Desthuilliers

unread,
Aug 19, 2009, 5:31:55 AM8/19/09
to
David a �crit :
(snip)

> Out of 'Abc.message' and 'self.message', which is the favoured
> convention? It would be very easy to accidentally override
> 'self.messages' with an instance attribute!

Only use 'Abc.message' if you want to make sure you get the Abc class
'message' attribute - that is, if you want to skip possible overrides in
subclasses. As far as I'm concerned, I'd tend to consider this bad style
unless it's a very very specific implementation point of an abstract
class (in which case it would probably be named '__message' to prevent
accidental override) - but YMMV of course.

Use 'self.__class__.message' (or 'type(self).message') if you want to
make sure you get the class 'message' attribute - that is, if you want
to honor possible overrides in subclasses, but not per-instance
override. But then - at least in your example code - I'd use a classmethod:

class Abc:
message = 'Hello World'

@classmethod
def print_message(cls):
print cls.message


Now the most common idiom - that is, outside classmethods - is to just
use 'self.message'. Someone (even you) might have a very valid reason to
override the 'message' attribute on a per-instance basis. FWIW, if you
start to worry about possible accidental overrides here, then Python
might not be the right language for you - nothing prevents "accidental"
overrides of method and even the class (the '__class__' attribute)
itself - yes, they are all attributes, and you can dynamically override
them !-)

0 new messages