[Tutor] Local variable look up outside the function and method

Martin A. Brown martin at linux-ip.net
Sun May 12 10:12:01 EDT 2019


Hello Arup,

> In the following the function, x is reachable outside the scope of foo function.
> In [1]: x = 10
> In [2]: def foo():
>    ...:     return x
> In [3]: print(foo())
> 10

> But why it is not the case when the look up happens inside a 
> instance method of a class?
> 
> In [1]: class Foo:
>    ...:     x = 10
>    ...:     def bar(self):
>    ...:         return x
> In [2]: Foo().bar()
> ---------------------------------------------------------------------------
> NameError                                 Traceback (most recent call last)
> <ipython-input-2-77cc08b8637b> in <module>
> ----> 1 Foo().bar()
> 
> <ipython-input-1-202509464a3d> in bar(self)
>       2     x = 10
>       3     def bar(self):
> ----> 4         return x
> 
> NameError: name 'x' is not defined
> 
> I figured I have to access it like:
> 
> In [1]: class Foo:
>    ...:     x = 10
>    ...:     def bar(self):
>    ...:         return self.__class__.x
>    ...:
>    ...: print(Foo().bar())
> 10
> 
> Just want to know how these search happens in 2 contexts.

Probably the following is the best section of the documentation to 
read:

  https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables

Here's also a little sample that may help.  By the way, I wouldn't 
normally be doing things like "unset self.x" and creating those 
peculiar methods, but I thought it might be instructive in this 
case.  This is using the same sort of technique you were with your 
class called Foo.  (I don't know all of the reasons why to inherit 
from object, but I usually do...)

class Foo(object):
    x = 10  # -- class variable

    def __init__(self):
        self.y = 20  # -- instance variable named 'y'

    def setinstancex(self, x):
        self.x = x

    def removeinstancex(self):
        del self.x

    def report(self):
        return (self.x, self.y)

if __name__ == '__main__':
    f = Foo()
    print('# -- f.x retrieves class value, f.y instance value')
    print('f.x = %s, f.y = %s, Foo.x = %s' % (f.x, f.y, Foo.x))
    print()

    f.setinstancex(3.14159)
    print('# -- f.x retrieves instance value, f.y instance value')
    print('f.x = %s, f.y = %s, Foo.x = %s' % (f.x, f.y, Foo.x))
    print()

    print('# -- warning, we are about to change the value for Foo.x')
    print()
    Foo.x = 6.022141e-23

    print('# -- f.x retrieves class value, f.y instance value')
    print('f.x = %s, f.y = %s, Foo.x = %s' % (f.x, f.y, Foo.x))
    print()

    f.removeinstancex()
    print('# -- f.x retrieves class value, f.y instance value')
    print('f.x = %s, f.y = %s, Foo.x = %s' % (f.x, f.y, Foo.x))
    print()


Good luck,

-Martin

--
Martin A. Brown
http://linux-ip.net/


More information about the Tutor mailing list