Review of control flow / basic for loops

In [1]:
# Fill in based off of confusion from yesterday

Advanced for loop keywords

In [6]:
# This is a reminder of what a loop looks like

for i in range(20):
    print(i)
print('Loop completed!')
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Loop completed!
In [7]:
# There are two keywords for loops that you will need to know
# The first is "break"
# Notice "break" is in green
# Break will exit a for loop once it is executed

for i in range(20):
    if i == 10:
        break
    print(i)
print('Loop completed!')
0
1
2
3
4
5
6
7
8
9
Loop completed!
In [8]:
# The other keyword you need to know is "continue"
# "continue" will make it so that the rest of the loop body is not executed
# but ONLY for the time it is called
# Notice that "10" is not printed

for i in range(20):
    if i == 10:
        continue
    print(i)
print('Loop completed!')
0
1
2
3
4
5
6
7
8
9
11
12
13
14
15
16
17
18
19
Loop completed!
In [9]:
# You can have continue and break in the same loop

for i in range(20):
    if i == 10:
        continue
    if i == 15:
        break
    print(i)
print('Loop completed!')
0
1
2
3
4
5
6
7
8
9
11
12
13
14
Loop completed!

While loops

In [ ]:
# This is the generic syntax for a while loop

while CONTIDION:
    LOOP_BODY
In [10]:
# A "while loop" is a loop that executes while CONDITION is true
# The CONDITION is evaluated once the loop body finishes, and only then

i = 0
while i < 10:
    print(i)
    i += 1
print('Loop completed!')
0
1
2
3
4
5
6
7
8
9
Loop completed!
In [1]:
# If CONDITION is False at the start of the loop, the loop body will not execute!

i = 0
while i < 0:
    print(i)
    i += 1
print('Loop completed!')
Loop completed!
In [12]:
# What is different about this and the one two above?

i = 0
while i < 10:
    i += 1
    print(i)
print('Loop completed!')
1
2
3
4
5
6
7
8
9
10
Loop completed!
In [14]:
# WARNING!!!!
# You can have loops that run forever.
# These are really really bad.
# Make sure the loop terminates.

while True:
    print('hi!')
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
hi!
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-14-06f2361de3ce> in <module>()
      1 while True:
----> 2     print('hi!')

/usr/local/lib/python3.5/dist-packages/ipykernel/iostream.py in write(self, string)
    372                 string = string.decode(self.encoding, 'replace')
    373 
--> 374             is_child = (not self._is_master_process())
    375             # only touch the buffer in the IO thread to avoid races
    376             self.pub_thread.schedule(lambda : self._buffer.write(string))

/usr/local/lib/python3.5/dist-packages/ipykernel/iostream.py in _is_master_process(self)
    299 
    300     def _is_master_process(self):
--> 301         return os.getpid() == self._master_pid
    302 
    303     def set_parent(self, parent):

KeyboardInterrupt: 
In [15]:
# WARNING!!!!!
# Even if you don't mean to, the loop can run forever.
# DO NOT do this.

i = 0
while i < 10:
    print(i)
print('Loop completed!') # This will never execute!
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-15-108318566107> in <module>()
      2 i = 0
      3 while i < 10:
----> 4     print(i)
      5 print('Loop completed!')

/usr/local/lib/python3.5/dist-packages/ipykernel/iostream.py in write(self, string)
    374             is_child = (not self._is_master_process())
    375             # only touch the buffer in the IO thread to avoid races
--> 376             self.pub_thread.schedule(lambda : self._buffer.write(string))
    377             if is_child:
    378                 # newlines imply flush in subprocesses

/usr/local/lib/python3.5/dist-packages/ipykernel/iostream.py in schedule(self, f)
    201             self._events.append(f)
    202             # wake event thread (message content is ignored)
--> 203             self._event_pipe.send(b'')
    204         else:
    205             f()

/usr/local/lib/python3.5/dist-packages/zmq/sugar/socket.py in send(self, data, flags, copy, track, routing_id, group)
    389                                  copy_threshold=self.copy_threshold)
    390             data.group = group
--> 391         return super(Socket, self).send(data, flags=flags, copy=copy, track=track)
    392 
    393     def send_multipart(self, msg_parts, flags=0, copy=True, track=False, **kwargs):

zmq/backend/cython/socket.pyx in zmq.backend.cython.socket.Socket.send()

zmq/backend/cython/socket.pyx in zmq.backend.cython.socket.Socket.send()

zmq/backend/cython/socket.pyx in zmq.backend.cython.socket._send_copy()

/usr/local/lib/python3.5/dist-packages/zmq/backend/cython/checkrc.pxd in zmq.backend.cython.checkrc._check_rc()

KeyboardInterrupt: 
In [18]:
# You can use "continue" in while loops
# The syntax and behavior is exactly the same as in for loop

i = 0
while i < 10:
    i += 1
    if i == 5:
        continue
    print(i)
print('Loop completed!')
1
2
3
4
6
7
8
9
10
Loop completed!
In [19]:
# WARNING!!!!
# This loop will also run forever. Why?
# Don't do this.

i = 0
while i < 10:
    if i == 5:
        continue
    print(i)
    i += 1
print('Loop completed!')
0
1
2
3
4
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-19-33c68528fb8a> in <module>()
      2 i = 0
      3 while i < 10:
----> 4     if i == 5:
      5         continue
      6     print(i)

KeyboardInterrupt: 
In [20]:
# You can also use "break" in while loops
# The syntax and usage is exactly the same as in for loops

i = 0
while True:
    if i > 10:
        break
    print(i)
    i += 1
0
1
2
3
4
5
6
7
8
9
10
In [21]:
# What will happen?

i = 0
while True:
    i += 1
    if i > 10:
        break
    print(i)
1
2
3
4
5
6
7
8
9
10

Functions (variable scoping)

In [2]:
# WARNING!!!
# Variables are "scoped"
# This is a complex topic, and we won't have time to cover all of it in lecture
# We will only cover the basics: variables inside a function
# Variables inside a function have no relation to variables outside the function
# See what happens when "i" is printed inside and outside the function

i = 0
def func(x):
    i = 10
    print(i, x)
    
func(5)
print(i)
10 5
0
In [23]:
# Variables across functions have no relation to each other
# A variable declared inside a function will have no relation to outside the function
# Why is there an error?

def func1(x):
    j = 10
    print(j, x)
    
def func2(x):
    j = 5
    func1(x)
    print(x)
    
func2(3)
print(j)
10 3
3
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-23-012d2fd7e23e> in <module>()
      9 
     10 func2(3)
---> 11 print(j)

NameError: name 'j' is not defined
In [24]:
# WARNING: Indentation is not the same scoping
# Scoping only applies to functions
# If blocks, for loops, and while loops ARE NOT functions

i = 0
for i in range(3):
    print(i)
0
1
2
In [25]:
# Why is this the output?

k = 0
for i in range(3):
    print(k)
0
0
0
In [26]:
# How about here?

k = 0
for i in range(3):
    k = 6
    print(k)
6
6
6