0

I am not able to understand the scope of few variables and why python is throwing an error while trying to do few things inside a class that is defined a method

Let me start with a basic example which works and then move on to few examples which work and which doesn't. I have an idea about what is working and sometimes what is not. But I feel that I lack an understanding the scope in this case (class inside a method)

First an example which works

Case 1:

def foo_method(a, b, c):
    return b, c, a

def bar_method(a=1, b=2, c=3):
    class BarClass:

        a_ = a + 1
        b_ = b + 1
        c_ = c + 1

        b_, c_, a_ = foo_method(a, b, c)

    return BarClass()

When I try to run the above code it works i.e temp = bar_method() works with out any issue

Case 2:

def foo_method(a, b, c):
    return b, c, a

def bar_method(a=1, b=2, c=3):
    class BarClass:

        a_ = a + 1
        b_ = b + 1
        c_ = c + 1

        b, c, a = foo_method(a, b, c)

    return BarClass()

Case 2 doesnt work i.e temp = bar_method() throws the error NameError: name 'a' is not defined

Case 3:

def foo_method(a, b, c):
    return b, c, a

def bar_method(a=1, b=2, c=3):
    class BarClass:

        a = a + 1
        b = b + 1
        c = c + 1

    return BarClass()

Case 3 doesnt work i.e temp = bar_method() throws the error NameError: name 'a' is not defined

Case 4

def foo_method(a, b, c):
    return b, c, a

def bar_method(a=1, b=2, c=3):
    class BarClass:

        a_ = a + 1
        b_ = b + 1
        c_ = c + 1

        a_ = a_ + 1

        b_, c_, a_ = foo_method(a_, b_, c_)

    return BarClass()

Case 4 works.

I got confused as to why certain operations are working and why others aren't. Can anyone shed some explanation on what I am not able to comprehend here. It seems like I can't make any modifications to the variables defined in the bar_method

RTM
  • 759
  • 2
  • 9
  • 22
  • Thanks for the link. The question seems similar. I couldn't see an explanation of it can't be modified in that thread – RTM Aug 02 '19 at 03:54
  • Note that you could slim down your examples since `b` and `c` are redundant. Also note in case 1, `a_`, `b_`, and `c_` are immediately overwritten. – wjandrea Aug 02 '19 at 03:55
  • Oh wait, sorry, you don't want to modify the nonlocals, just access them. I'll remove the duplicate flag. – wjandrea Aug 02 '19 at 03:57

1 Answers1

1

The assignments in the classes:

#case 2
b, c, a = ...

#case 3
a = ...
b = ...
c = ...

make those names local to the class's scope so the names on the right-hand-side of the assignment are interpreted as the local scope names. Which haven't been evaluated yet.
(that might not have been said well, feel free to improve wording)


https://stackoverflow.com/a/23471004/2823755
https://stackoverflow.com/a/370380/2823755


From 4. Execution model:
4.1. Structure of a program

A Python program is constructed from code blocks. A block is a piece of Python program text that is executed as a unit. The following are blocks: a module, a function body, and a class definition.

4.2.1 Binding of names discusses name binding by assignment within code blocks.

In 4.2.2. Resolution of names, the 4th paragraph states:

If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block.

I cannot find a reference yet but the name binding is occurring before the evaluations.
(my assumption -maybe someone will clarify)


An finally (?) from the Programming FAQ
Why am I getting an UnboundLocalError when the variable has a value?

wwii
  • 23,232
  • 7
  • 37
  • 77
  • Very interesting. The way I have learned variable assignment is that python evaluates the portion on the right and then assigns to the variable on the left – RTM Aug 02 '19 at 04:00
  • @RTM See my edit – wwii Aug 02 '19 at 04:30