Need help with Python scoping rules

Steven D'Aprano steve at REMOVE-THIS-cybersource.com.au
Wed Aug 26 18:42:24 CEST 2009


On Wed, 26 Aug 2009 15:36:35 +0000, kj wrote:

> In <1bf83a7e-f9eb-46ff-84fe-cf42d9608e71 at j21g2000yqe.googlegroups.com>
> Carl Banks <pavlovevidence at gmail.com> writes:
> 
>>Yeah, it's a little surprising that you can't access class scope from a
>>function, but that has nothing to do with encapsulation.
> 
> It does: it thwarts encapsulation.  The helper function in my example is
> one that clearly rightfully belongs nowhere else than the class itself,
> i.e. encapsulated within the class.

There's nothing "clearly" about it. 

This helper function doesn't reference the class, or any instance of the 
class. Why should it be encapsulated in the class? It's not *part* of the 
class, it shouldn't be *inside* the class.

Look at it this way: classes are made from building blocks. Just because 
a building block ends up in a class, doesn't mean the function that makes 
the building block has to be inside the class too.

It's an accident of Python's execution model that a single function call 
*sometimes* works as you expect inside the class statement:

class Demo:
    def f():
        return 2
    def g():
        return f()+1
    x = f()  # works
    y = g()  # fails


As you can see, the problem is not because of recursion, but because the 
class scope is not inserted into the function scope. As I said earlier, 
your problem isn't too little class encapsulation, but too much: the 
class scope doesn't leak into the function scope.

Python could, of course, behave the way you want, but it would lead to 
some odd interactions:

class Weird(object):
    x = 1
    def __init__(self):
        self.y = 2
    def test(self):
        print self.x  # refers to attribute x with value 1
        print x       # refers to attribute x with value 1
        print self.y  # refers to attribute y with value 2
        print y       # refers to global y

In existing Python, both x and y will refer to globals, because it's 
considered more important for all attribute access to be consistently 
explicit than to insert the class scope into the function scope. This 
isn't a design flaw, or a bug, it's a feature. Yes, it makes it hard for 
you to solve your problem the way you want to solve it, but it doesn't 
stop you from solving your problem. The module is encapsulation enough.



-- 
Steven



More information about the Python-list mailing list