1

I have (as it seems to me) some basic understanding of Python scoping rules (based on studying of this answer).

I have also learned from the documentation on exec, that it takes globals and locals as optional arguments, and that:

In all cases, if the optional parts are omitted, the code is executed in the current scope.


NOTE: all examples below assume usage of Python 3.

With that said, I have recently stumbled onto the case, which confused me a bit:

def test(passed_data):
    local_result = 5
    exec("print(passed_data)")
    exec("print(local_result)")

    return local_result

print (test('whatever'))

running code above results in:

whatever
5
5

Here, it is evident that exec has access to tests locals (passed_data and 'local_result').
Though if we will try to change any of them:

def test(passed_data):
    local_result = 5
    exec("print(passed_data)")
    exec("print(local_result)")

    exec("passed_data = 222")
    exec("local_result = 111")

    exec("print(passed_data)")
    exec("print(local_result)")

    return local_result

print (test('whatever'))

it will result in:

whatever
5
whatever
5
5

Using global inside exec:

def test(passed_data):
    local_result = 5

    exec("print(local_result)")
    exec("global local_result; local_result = 111")
    exec("print(local_result)")

    return local_result

print (test('whatever'))

gives the same result (of course, since local_result is local to the scope of test):

5
5
5

What enables us to chance local_result via exec — is defining it using global:

def test(passed_data):
    global local_result
    local_result = 5

    exec("print(local_result)")
    exec("global local_result; local_result = 111")
    exec("print(local_result)")

    return local_result

print (test('whatever'))

This gives us:

5
111
111

It seems to me that I'm just missing some basic understanding of Python scoping or the mechanics of exec, to grasp this case.
Nevertheless, I would like to understand the following:

  1. Why exec is able to print variable from the function scope, without using global, but is not able to change it?
  2. My understanding is that (given globals and locals are omitted) exec will execute any Python code, within the scope it is called from, as if this code was just in the source (without exec), where (and how) am I wrong in this assumption?

P.S.: I understand that changing local variable via exec is not 'right thing to do', I seek the understanding of exec scoping rules just for the sake of learning.

  • 1
    Local variables are subject to optimisations that prevent them from being modified dynamically. A similar example is the note in https://docs.python.org/3/library/functions.html#locals. Global variables don't have these restrictions, but it takes a `global` statement outside the exec for the compiler to recognise a variable as global rather than local. – Alex Hall Mar 10 '18 at 08:33
  • 1
    Checkout this answer I just posted https://stackoverflow.com/a/49208472/2867928 – Mazdak Mar 10 '18 at 11:22
  • @AlexHall, thanks for pointing out related doc section! –  Mar 13 '18 at 10:23
  • @Kasramvd, I've checked your answer — it explains the same thing indeed. Thanks! –  Mar 13 '18 at 10:24

0 Answers0