Skip to content

Instantly share code, notes, and snippets.

@dcrosta
Created April 30, 2012 20:17
Show Gist options
  • Save dcrosta/2562350 to your computer and use it in GitHub Desktop.
Save dcrosta/2562350 to your computer and use it in GitHub Desktop.
A Python Mystery
Guess the output:
>>> def exec_code_object_and_return_x(codeobj, x):
... exec codeobj
... return x
...
>>> co1 = compile("""x = x + 1""", '<string>', 'exec')
>>> co2 = compile("""del x""", '<string>', 'exec')
>>> exec_code_object_and_return_x(co1, 1)
# What do you get here?
>>> exec_code_object_and_return_x(co2, 1)
# And what about here?
@varun06
Copy link

varun06 commented Apr 30, 2012

The output is 2 and 1.Can you please explain what is this and what is happening here?

@dcrosta
Copy link
Author

dcrosta commented Apr 30, 2012

@varun06 I'm in the process of writing a blog post about exec broadly, and this example in particular. I'll post the URL here once I have it finished.

@figgybit
Copy link

well this might enlighten the gist.

def test3():
x = 1
co2 = compile("""del x""", '', 'exec')
exec co2
print x
return x

This actually doesn't error but you would expect it to because the statement below fails.

x = 1
co2 = compile("""del x""", '', 'exec')
exec co2
print x

the reason is all about compiling. first we compile the codeobj (co2) and then the function is compiled. but when we compile the function the codeobj is not evalulated and as a result the deletion of the attribute x doesn't actually effect the results of the function.

so when we call the function it doesn't crash, YO!

@maxamante
Copy link

Thanks @figgybit. As a Python noob, I was assuming that was happening and now I know it was.

@dcrosta
Copy link
Author

dcrosta commented May 1, 2012

@dcrosta
Copy link
Author

dcrosta commented May 1, 2012

@figgybit I go into this in a bit more detail in the blog post, but I think the main difference between your first and second examples is that in the first, the exec'd code object is operating on locals, while in the second there are no locals (in module scope, locals and globals are the same; that is, there are only globals). Thus, in the second case, after execing the code object, the variable x no longer exists in the (global) scope; in the first example, the variable x is deleted in the exec'd code object's frame's locals, but not in the wrapping function's frame's locals.

@varun06
Copy link

varun06 commented May 1, 2012 via email

@figgybit
Copy link

figgybit commented May 1, 2012

@dcrosta thanks for the puzzle it was fun and I enjoy your explanation. Tell Mr. Diamond I say 'HI'

Hackers Unite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment