Why doesn't exec("break") work inside a while loop - python

As the question asks, why doesn't the below code work:
while True:
exec("break")
I am executing the above in pycharm via python 3.5.2 console.
I initially thought it was a context issue but after reading the documentation, I haven't come closer to understanding why this error ocurs.
SyntaxError: 'break' outside loop
Thanks in advance :)
EDIT: I understand that it works without exec() by the way, I'm curious why it won't work with exec (as my circumstances required it) - comprehensive answers welcome.

This is because exec() is ignorant to your surrounding while loop. So the only statement that exec() sees in your example is break. Instead of using exec("break"), simply use break as is.
The only access the exec() function has to its surrounding scope, is the globals() and locals() dictionaries. The documentation for exec() provides some insight into how exec() works:
This function supports dynamic execution of Python code. object must be either a string or a code object. If it is a string, the string is parsed as a suite of Python statements which is then executed (unless a syntax error occurs). [1] If it is a code object, it is simply executed. In all cases, the code that’s executed is expected to be valid as file input (see the section “File input” in the Reference Manual). Be aware that the return and yield statements may not be used outside of function definitions even within the context of code passed to the exec() function. The return value is None.
In all cases, if the optional parts are omitted, the code is executed in the current scope. If only globals is provided, it must be a dictionary, which will be used for both the global and the local variables. If globals and locals are given, they are used for the global and local variables, respectively. If provided, locals can be any mapping object. Remember that at module level, globals and locals are the same dictionary. If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.
If the globals dictionary does not contain a value for the key builtins, a reference to the dictionary of the built-in module builtins is inserted under that key. That way you can control what builtins are available to the executed code by inserting your own builtins dictionary into globals before passing it to exec().

The exec statement runs a bit of code independently from the rest of your code.
Hence, the line:
exec("break")
is tantamount to calling break out of nowhere, in a script where nothing else happens, and where no loop exists.
The right way to call the break statement is:
while True:
break
EDIT
The comment from Leaf made me think about it.
Actually, the exec statement does not run the code out of nowhere.
>>> i = 12
>>> exec("print(i)")
12
A better answer, as far as I understand, is that exec runs a piece of code in the same environment as the original code, but independently from it.
This basically means that all the variables that exist at the moment exec is called can be used in the code called by exec. But the context is all new, so return, break, continue and other statements that need a context, will not work, unless the right context is created.
By the way, I kept the word "statement" when talking about exec, but it has become a function in Python3, the same way print did.

exec() is a function. Assuming for simplicity that a function call constitutes a statement of its own (just like in your example), it may end in one of the following ways:
the function returns normally - in this case the next statement according to the control flow is executed;
an exception is raised/thrown from the function - in this case the matching except clause on the call stack (if any) is executed
the entire program is terminated due to an explicit call to exit() or equivalent - there is nothing to execute.
Calling a break (as well as return or yield) from inside exec() would modify the program execution flow in a way that is incompatible with the described aspect of the function call semantics.
Note that the documentation on exec() contains a special note on the use of return and yield inside exec():
Be aware that the return and yield statements may not be used outside
of function definitions even within the context of code passed to the
exec() function.
A similar restriction applies to the break statement (with the difference that it may not be used outside loops), and I wonder why it was not included in the documentation.

exec is a built in function ,
Python insists that break should happen inside the loop,not inside a function
What is happening in your code is you are putting break inside a function which is exec you can't break out of a loop by executing a
break within a function that's called inside the loop.
For Ex
>>> def func():
break
SyntaxError: 'break' outside loop
>>>

Try break without exec():
while True:
break

exec function runs code inside a code and that means it runs out of nowhere! So, your while loop doesn't catch it. Your file is <stdin>. exec runs on another file called <string>. it doesn't recognize it where are you trying to break a loop where there is not a loop. So, your code is this:
while True:
exec("break")
It should be like this:
while True:
break

Related

Why the print statement is being executed from the function if the function is not called?

def enumerator(fruits):
for index, fruit in enumerate(fruits):
print(f"Fruit: {fruit}, under the index: {index}.")
just_a_variable = enumerator(["apple", "banana", "lemon"]) # Im just assigning function call
# to the variable "just_a_variable"
# and boom, when I run the program the function is called. Makes no sense (it shouldn't work this way, does it?)
I assume this is happening because there is a print statement in the function but it still doesn't make sense. if I change the print statement to "return" it suddenly doesn't compile, that is what I was expecting from just using print. I'm I missing something here?
In general if you add parenthesis after a function (like one of the two examples below), it is called.
function_name(arguments)
variable = function_name(arguments)
 
If you just want a variable to point to a function:
variable = function
Then the following two statements will become identical:
variable(arguments)
function(arguments)
Having said so, this seems a bit useless to me. With you function defined the way it currently is, there isn't a way I know to "assign" it to a variable and pass arguments at the same time.
This does change the structure of your code, but you can perhaps use yield instead of return.
The line just_a_variable = enumerator(["apple", "banana", "lemon"]) is calling function enumerator. Technically, that is what the parenthesis after enumerator do.
Perhaps you noticed that simply running the file is running that line (and calling enumerator). As a scripting language, this is how Python works (in contrast to Java or other compiled languages).

What happens when a resource-managed variable is used outside of its scope? [duplicate]

I am reading only firstline from python using :
with open(file_path, 'r') as f:
my_count = f.readline()
print(my_count)
I am bit confused over scope of variable my_count. Although prints work fine, would it be better to do something like my_count = 0 outside with statement first (for eg in C in used to do int my_count = 0)
A with statement does not create a scope (like if, for and while do not create a scope either).
As a result, Python will analyze the code and see that you made an assignment in the with statement, and thus that will make the variable local (to the real scope).
In Python variables do not need initialization in all code paths: as a programmer, you are responsible to make sure that a variable is assigned before it is used. This can result in shorter code: say for instance you know for sure that a list contains at least one element, then you can assign in a for loop. In Java assignment in a for loop is not considered safe (since it is possible that the body of the loop is never executed).
Initialization before the with scope can be safer in the sense that after the with statement we can safely assume that the variable exists. If on the other hand the variable should be assigned in the with statement, not initializing it before the with statement actually results in an additional check: Python will error if somehow the assignment was skipped in the with statement.
A with statement is only used for context management purposes. It forces (by syntax) that the context you open in the with is closed at the end of the indentation.
You should also go through PEP-343 and Python Documentation. It will clear that its not about creating scope its about using Context Manager. I am quoting python documentation on context manager
A context manager is an object that defines the runtime context to be established when executing a with statement. The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code. Context managers are normally invoked using the with statement (described in section The with statement), but can also be used by directly invoking their methods.
Typical uses of context managers include saving and restoring various kinds of global state, locking and unlocking resources, closing opened files, etc.

When does a closure in Python finish execution or go out of scope?

I am trying to wrap my brain around closures. I’ve been looking at a lot of sources, but this question is based mainly on the explanation in Wikipedia.
I think I get the idea of a callback as a closure, to handle events that happen after something in the outer function has happened / been called. I guess that’s what happening with deferreds in Scrapy.
I’ve also seen examples in Python using the logging module.
Ok, but, but, you can’t call a closure on its own, right? Because that would be calling it outside the scope of where it was defined. Putting it another way, you can’t call a closure directly, you have to call the enclosing function which returns it. But if that’s the case, then the use case for closures is limited by its dependency on the outer function. The fact that it remembers the free variables of the enclosing environment after the outer function has ceased execution does not make the closure a little portable unit you can take and use anywhere and it will work without the outer function, right?
But if that’s right, then how can this also be right:
“...When the closure is entered at a later time, possibly with a
different lexical environment, the function is executed with its
non-local variables referring to the ones captured by the closure, not
the current environment…” Wikipedia - same link - #(“Implementation and theory”)
This is why I am struggling so hard with closures. The idea that they remember values post execution sounds, at least to me, like it has a life independent of the enclosing function, as though you can call it or use it in “a different lexical environment”. But that’s not true if the enclosing function is right there with it, is it?
This example from datacamp helps spell out what I find confusing in a simpler example:
In Python, a function is also considered a object, which means that it
can be returned and assigned to a variable. In the next example,
you'll see that instead of inner() being called inside outer(), return
inner is used. Then, outer() is called with a string argument and
assigned to closure. Now, even though the functions inner() and
outer() have finished executing, their message is still preserved. By
calling closure(), the message can be printed.
def outer(message):
# enclosing function
def inner():
# nested function
print(message)
return inner
closure = outer("Hello world!")
closure()
Hello world!
Notice that if you call closure without parentheses, only the type of
the object will be returned. You can see that it's of the type function
__main__.outer.<locals>.inner.closure
<function __main__.outer.<locals>.inner>
Now, even though the functions inner() and outer() have finished
executing, their message is still preserved.
In what sense have either inner() or outer() “finished executing” in this example? They haven’t even been called until you call closure()!
What am I missing here? Thanks.
They haven’t even been called until you call closure()!
Actually, the statement closure = outer("Hello world!") calls the outer() function with the argument "Hello world!". At that time, the outer() function executes, thereby defining the inner() function and returning the function inner itself, assigning the function to the variable closure. At this point, outer() has "finished executing".
Next, by calling closure(), the function inner() is actually invoked, returning the preserved message.
The description is poorly worded; the function inner wasn't executed during the call to outer, just the def statement that defines it.
Among other attributes, the function object defined by def inner(): ... has one named _closure__ that contains the value to use when the nonlocal name message is looked up.
>>> closure.__closure__[0].cell_contents
'Hello'
To the best of my understanding (which is not, admittedly, great), each nonlocal variable in the definition of inner is numbered, and a tuple containing one cell object per nonlocal name is stored in __closure__. Each cell has an attribute cell_contents which contains the value held by the nonlocal name when outer returns.

What is the difference between a statement and a function in Python?

Edit: The suggested duplicate, does not answer my question, as I am primarily concerned with the difference in Python specifically. The suggested duplicate is far broader than this question.
I have recently started to learn Python. I'm currently reading "Learn Python the Hard Way". I have some ad-hoc programming experience, but am going back to the beginning to learn everything from the ground up this time.
In the book, one of the first lessons concerns print and the author provides various instructions of its use in Python 2.7, e.g.:
print "This is fun."
I found myself wondering what print is technically called here from the programming perspective. Some research found this, PEP-3105
In which case is made to make print a function:
The print statement has long appeared on lists of dubious language
features that are to be removed in Python 3000, such as Guido's
"Python Regrets" presentation 1 . As such, the objective of this PEP
is not new, though it might become much disputed among Python
developers.
So print is a statement in Python 2.7, and a function in Python 3.
But I have been unable to find a straight-forward definition for the difference between a statement and a function. I found this also by the person who invented Python, Guido van Rossum in which he explains why it would be good to make print a function instead of a statement.
From what I have read it appears that a function is some code that takes parameters and returns a value. But isn't print doing this in python 2.7? Isn't it taking in strings and returning a concatenated string?
What is the difference between a statement and a function in Python?
A statement is a syntax construct. A function is an object. There's statements to create functions, like def:
def Spam(): pass
So statements are one of the ways to indicate to Python that you want it to create a function. Other than that, there's really not much relation between them.
A statement in Python is any chunk of code you've written. It's more a theoretical concept than a real thing. If you use the correct syntax when writing your code, your statements will get executed ("evaluated"). If you use the incorrect syntax, your code will throw an error. Most people use "statement" and "expression" interchangeably.
Probably the easiest way to see the difference between a statement and a function is to see some example statements:
5 + 3 # This statement adds two numbers and returns the result
"hello " + "world" # This statement adds to strings and returns the result
my_var # This statement returns the value of a variable named my_var
first_name = "Kevin" # This statement assigns a value to a variable.
num_found += 1 # This statement increases the value of a variable called num_found
print("hello") # This is a statement that calls the print function
class User(BaseClass): # This statement begins a class definition
for player in players: # This statement begins a for-loop
def get_most_recent(language): # This statement begins a function definition
return total_count # This statement says that a function should return a value
import os # A statement that tells Python to look for and load a module named 'os'
# This statement calls a function but all arguments must also be valid expressions.
# In this case, one argument is a function that gets evaluated
mix_two_colors(get_my_favorite_color(), '#000000')
# The following statement spans multiple lines and creates a dictionary
my_profile = {
'username': 'coolguy123'
}
Here is an example of a statement that is invalid:
first+last = 'Billy Billson'
# Throws a Syntax error. Because the plus sign is not allowed to be part of a variable name.
In Python, you tend to put each statement on their own line, except in the case of nested statements. But in other programming languages like C and Java, you could put as many statements on a single line as you wanted as long as they are separated by a colon (;).
In both Python2 and Python3, you can call
print("this is a message")
and it will print the string to standard out. This is because they both have a function defined called print that takes in a string argument and prints it.
Python2 also allowed you to make a statement to print to standard out without calling a function. The syntax of this statement was that it started with the word print and whatever came after was what got printed. In Python3 this is no longer a valid statement.
print "this is a message"
Both function and statement are words that Python understands.
Function needs parenthesis to act on anything (including nothing).
Statement does not.
Hence in Python 3 print is function not statement.
Let us take a funny case. not True and not(True) both work. But type(not) is not function hence not is statement. not(True) works only because Python takes parenthesis also for grouping. Bad design, indeed.
Another difference: (not) fails, (print) does not fail, because a statement has no value while a function has one (for the interpreter, not in the mathematical sense of the image of some antecedent).

Python deleting local variables through a loop

I wrote the following code in middle of a function to delete all variables except few.
dontDelete = ['Cat','Dog']
for vi in dir(): #'Cat','Dog','Pig','Elephant','Lion'
if vi in dontDelete:
continue
else:
del locals()[vi]
But it doesn't delete any variables even though it goes to the del locals()[vi] statement
Edit1: I am running out of memory in middle of the function. So, I thought about removing the 100's of variables I have locally in the function. I wrote the snippet above only to show what I am seeking on doing.
Edit2: can someone explain why negative votes on this question. Is there an obvious solution that I am missing.
Edit3: I am not able to create another function in middle of what I am doing. So, I want to try the delete variables option
locals() is a view on the locals, mutating it is not recommended and provides no guarantees as to whether the "real" values are changed or not., per the note from the docs:
Note: The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.
The correct solution is usually to refactor your function, so all the stuff you want to delete are local variables in a separate function, and the stuff you want to keep is returned by that function. Python will clean the locals for you when the subfunction returns, so only the return values are kept; if there are reference cycles in that local scope that must be freed immediately, you can explicitly call gc.collect() after the function returns to force a full cycle collection, but that's usually not necessary.

Categories

Resources