<jupyter_start><jupyter_text>CSCI E7 Introduction to Programming with Python Lecture 02 Jupyter NotebookFall 2021 (c) <NAME>  Review Day 1 Investigate the documentation<jupyter_code>## what does rfind() do in general?
## See https://docs.python.org/3/library/stdtypes.html

s = 'department of redundancy department'
 
print(len(s))
## find

print(s.find('department'))
## rfind

print(s.rfind('department'))
## Is there on-line help?

help(rfind)
help(s.rfind)
s.rfind?<jupyter_output><empty_output><jupyter_text>*rfind() was useful in the homework*  Notes from the TFs- Windows users:     - Don’t use IE to work with Canvas    - Use Command Prompt rather than PowerShell.- When writing posts for BBoard, note if you are using Mac or Windows or Linux.  - Share a few commands that will help others as some are getting used to the terminal commands too. - Add your name to your Notebook via a Markdown cell.  Also add comments.- If you learned something new share on the Ed BBoard  FunctionsWe have been using functions<jupyter_code>## Function len()

s = 'onetwo'

print(len(s))<jupyter_output>6<jupyter_text>len() is a functionlen() maps strings to non-negative integers Above len() takes a string *argument*, and *returns* an integer<jupyter_code>help(len)<jupyter_output>Help on built-in function len in module builtins:

len(obj, /)
    Return the number of items in a container.<jupyter_text>Here are some functions we have been using<jupyter_code>## len()

type(len)
## print()

type(print)
## help()

help(print)<jupyter_output>Help on built-in function print in module builtins:

print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.<jupyter_text>Functions are used to codify a well-defined activity In a French Restaurant - making white sauceWhite sauce is the basis of many other items In the movies - The Wilhelm Scream  www.youtube.com/watch?v=cdbYsoEasio  What happens when you call a function?<jupyter_code>def chorus():
    prnt('Bamba')

chorus()<jupyter_output><empty_output><jupyter_text>Python is keeping track of (at least) two spots```python----> 4 chorus()    Spot calling the function```and```python      1 def chorus():----> 2     prnt('Bamba')```the spot in the function that had a problem. Fix our definition<jupyter_code>def chorus():              # 'def', function name, parameters, colon
    print("Bamba-bamba")   # Body of the function
    print("Bamba-bamba")
    print("Bamba-bamba")
    print("Bam")
    
chorus()                   # Function call<jupyter_output>Bamba-bamba
Bamba-bamba
Bamba-bamba
Bam<jupyter_text>Run over compontents  Stack DiagramWho is calling whom?  main() calls chorus().  chorus calls print().```python    main()    chorus()        print()```  Longer Example<jupyter_code>def c():               
    print('\t\t c')
    
def b():               
    print('\t b 1')
    c()
    print('\t b 2')
    
def a():   
    print(' a 1')
    b()
    print(' a 2')
    
a()<jupyter_output>a 1
	 b 1
		 c
	 b 2
 a 2<jupyter_text>*Python pauses main while function is running*  Stop and Think- Can a function call a function that calls a function?- Can a function call itself?- len() can find the length of things other than strings.   Give two examples.<jupyter_code>list1 = [1, 2, 3]
len(list1)<jupyter_output><empty_output><jupyter_text>Functions with parameters<jupyter_code>def print_greeting(name):              # Parameter List
    print(f"Hello, {name}")

print_greeting('Sam')                  # Argument List
print_greeting('Dave')
print_greeting('<NAME>')<jupyter_output>Hello, Sam
Hello, Dave
Hello, <NAME><jupyter_text>Example from Real Life: Legal Contracthttps://www.youtube.com/watch?v=6u8AgUXPpLM<jupyter_code>## Party of the first part gives party of the second part...
def contract(first, second):
    return f"{first} will give to {second} the rights ..."


print(contract('Groucho', 'Chico'))<jupyter_output>Groucho will give to Chico the rights ...<jupyter_text>AssertAssert() takes a Boolean condition and halts if it is not True.  This can be useful when debugging to check your assumptionsWe will use assert() in our Unit Tests to test your programs<jupyter_code>assert((1 + 1) == 2)
assert('black' == 'white')<jupyter_output><empty_output><jupyter_text>Stop and ThinkNotice that we used '==' in the assertions above.  What happens if we use '=' instead?What is the difference between '==' and '='?What is the difference between '==' and 'is'?  Python, the OS, & Command Line Parameters What is your environment?We will explore this different ways.  We start with OS command line programsThe command line is discussed in **Python the Hardway**https://learnpythonthehardway.org/book/appendixa.html<jupyter_code>## From the DOS prompt
# Display the DOS Environment
! set                   
## From the Unix Prompt
## ! Tells the Notebook to pass the command through to the Operation System (OS)

! env                   # Display the Unit Environment<jupyter_output>'env' is not recognized as an internal or external command,
operable program or batch file.<jupyter_text>When I run this on my machine, I see something like this:```python TERM_PROGRAM=Apple_Terminal SHELL=/bin/bash TERM=xterm-color CLICOLOR=1 TMPDIR=/var/<KEY>/ Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.CyKKXecMN1/Render TERM_PROGRAM_VERSION=421.2 TERM_SESSION_ID=0EDED937-A575-4CE0-B061-7231107AD8CB USER=jparker SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.KfsNEifAWf/Listeners JPY_PARENT_PID=2601 PAGER=cat VIRTUAL_ENV=/Users/jparker/Library/Enthought/Canopy_64bit/User PATH=//anaconda/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Users/jparker/Library/Enthought/Canopy_64bit/User/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin:/opt/X11/bin:/usr/local/git/bin:/usr/local/git/bin/:/Users/jparker/bin/ _=/usr/bin/env PWD=/Users/jparker/Documents/courses/Python/Programs/day2 LANG=en_US.UTF-8 XPC_FLAGS=0x0 XPC_SERVICE_NAME=0 HOME=/Users/jparker SHLVL=2 LOGNAME=jparker DISPLAY=/private/tmp/com.apple.launchd.BXFujiny00/org.macosforge.xquartz:0 GIT_PAGER=cat```  An important part of your environment is your path<jupyter_code>## From the DOS prompt

! PATH
## From the Unix prompt

! echo $PATH<jupyter_output>$PATH<jupyter_text>When I run this on my machine, I see something like this:```python/Users/jparker/opt/anaconda3/bin:/Users/jparker/opt/anaconda3/condabin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin:/opt/X11/bin:/usr/local/git/bin:/Users/jparker/bin```<jupyter_code>## Pick this appart

s = '/Users/jparker/opt/anaconda3/bin:/Users/jparker/opt/anaconda3/condabin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/TeX/texbin:/opt/X11/bin:/usr/local/git/bin:/Users/jparker/bin'

lst = s.split(':')
for line in lst:
    print(line)<jupyter_output>/Users/jparker/opt/anaconda3/bin
/Users/jparker/opt/anaconda3/condabin
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
/Library/TeX/texbin
/opt/X11/bin
/usr/local/git/bin
/Users/jparker/bin<jupyter_text>The Python Path Python also has a version of Path: where to look for libraries<jupyter_code>import sys              # Import the System Library sys

for line in sys.path:   # For each string 'line' in the list 
    print(line)<jupyter_output>C:\Users\Asus\Coding\WorkspaceJupyter
C:\Users\Asus\Coding\Tools\Anaconda\python38.zip
C:\Users\Asus\Coding\Tools\Anaconda\DLLs
C:\Users\Asus\Coding\Tools\Anaconda\lib
C:\Users\Asus\Coding\Tools\Anaconda

C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\locket-0.2.1-py3.8.egg
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\win32
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\win32\lib
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\Pythonwin
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\IPython\extensions
C:\Users\Asus\.ipython<jupyter_text>When I run this, I see something like this:The idea is the same: there is where I will look for resources.This path incudes directories for the notebook: you would get fewer items at the command line```python/Users/jparker/Documents/courses/Python/Programs/day2/Users/jparker/opt/anaconda3/lib/python38.zip/Users/jparker/opt/anaconda3/lib/python3.8/Users/jparker/opt/anaconda3/lib/python3.8/lib-dynload/Users/jparker/opt/anaconda3/lib/python3.8/site-packages/Users/jparker/opt/anaconda3/lib/python3.8/site-packages/aeosa/Users/jparker/opt/anaconda3/lib/python3.8/site-packages/IPython/extensions/Users/jparker/.ipython```  What else does sys know?<jupyter_code>import sys

dir(sys)
## What does dir() do?

help(dir)<jupyter_output>Help on built-in function dir in module builtins:

dir(...)
    dir([object]) -> list of strings
    
    If called without an argument, return the names in the current scope.
    Else, return an alphabetized list of names comprising (some of) the attributes
    of the given object, and of attributes reachable from it.
    If the object supplies a method named __dir__, it will be used; otherwise
    the default dir() logic is used and returns:
      for a module object: the module's attributes.
      for a class object:  its attributes, and recursively the attributes
        of its bases.
      for any other object: its attributes, its class's attributes, and
        recursively the attributes of its class's base classes.<jupyter_text>What kind of things are these attributes?<jupyter_code>import sys

print(type(sys.copyright))
## What is the copyright?

print(sys.copyright)<jupyter_output>Copyright (c) 2001-2021 Python Software Foundation.
All Rights Reserved.

Copyright (c) 2000 BeOpen.com.
All Rights Reserved.

Copyright (c) 1995-2001 Corporation for National Research Initiatives.
All Rights Reserved.

Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
All Rights Reserved.<jupyter_text>What about getrefcount?Get Reference Count: How many references are there to an object?*How many people have my phone number?*<jupyter_code>print(type(sys.getrefcount))
print(help(sys.getrefcount))
s = 'cattywampus'

print(sys.getrefcount(s))
t = s
print(sys.getrefcount(s))
s = ''
print(sys.getrefcount(t))
u = t
v = t
w = t
x = t
y = t
z = t

print(sys.getrefcount(t))<jupyter_output>8<jupyter_text>Bottom line- Python keeps references to objects- It keeps track of how many references are out there  Command line programs use argumentsLet's consider programs that make copies of a file.  We need two parameters:```pythonoriginal.py - the name of existing filenew.py - name of copy we are making``````python The DOS file copy programcopy original.py new.py   The Unix file copy programcp original.py new.py  ``` The system argument vector sys.argv passes in command line parameters We will meet the program mypy belowmypy takes a command line parameter for the file it should check.```python Check type hintsmypy double.py     ```<jupyter_code>import sys

print(type(sys.argv))
print(sys.argv)
for w in sys.argv:
    print(w)<jupyter_output>C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\ipykernel_launcher.py
-f
C:\Users\Asus\AppData\Roaming\jupyter\runtime\kernel-55d960da-f1bf-462e-ba45-11ec8d06f5e4.json<jupyter_text>Stop and ThinkYou should have a path to the ipykernel_launcher.py in the output above.  Mine is in:/Users/jparker/opt/anaconda3/lib/python3.8/site-packages/ipykernel_launcher.pyTake a look at the file.  What does CWD mean in this context?  (Hint: it is not Chronic Wasting Disease)Can you imagine why having the CWD on your path might be a threat?  (Hint: Beware of Greeks bearing gifts)  Our first python scriptWe can run the program below from the command line or from a cell in a notebookThe results will be differentThe value of sys.platform remains the same, but the arguments and path are part of the program's environment, and they will differ.<jupyter_code># system.py
#
# Explore variables the system knows
# Usage:
#      % python system.py arguments
#
# <NAME>, June 2013

import sys

print(f"Arguments:, {sys.argv}\n")

print(f"Platform: {sys.platform}\n")

print("Path:")
# Print each component in the path
for p in sys.path:
    print(p)<jupyter_output>Arguments:, ['C:\\Users\\Asus\\Coding\\Tools\\Anaconda\\lib\\site-packages\\ipykernel_launcher.py', '-f', 'C:\\Users\\Asus\\AppData\\Roaming\\jupyter\\runtime\\kernel-55d960da-f1bf-462e-ba45-11ec8d06f5e4.json']

Platform: win32

Path:
C:\Users\Asus\Coding\WorkspaceJupyter
C:\Users\Asus\Coding\Tools\Anaconda\python38.zip
C:\Users\Asus\Coding\Tools\Anaconda\DLLs
C:\Users\Asus\Coding\Tools\Anaconda\lib
C:\Users\Asus\Coding\Tools\Anaconda

C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\locket-0.2.1-py3.8.egg
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\win32
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\win32\lib
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\Pythonwin
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\IPython\extensions
C:\Users\Asus\.ipython<jupyter_text>Run the cell above Now create a text file called system.py with the program above Place it in the same directory as the notebook, and run it by calling ```python    python system.py one two three```<jupyter_code>## Command Line Arguments will be system.py (name of program) 
## and one, two, three

! python system.py one two three<jupyter_output>Arguments:, ['system.py', 'one', 'two', 'three']

Platform: win32

Path:
C:\Users\Asus\Coding\WorkspaceJupyter
C:\Users\Asus\Coding\Tools\Anaconda\python38.zip
C:\Users\Asus\Coding\Tools\Anaconda\DLLs
C:\Users\Asus\Coding\Tools\Anaconda\lib
C:\Users\Asus\Coding\Tools\Anaconda
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\locket-0.2.1-py3.8.egg
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\win32
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\win32\lib
C:\Users\Asus\Coding\Tools\Anaconda\lib\site-packages\Pythonwin<jupyter_text>When I run the cell above, the OS runs the program and prints```pythonArguments: ['system.py', 'one', 'two', 'three']Platform:  darwinPath:/Users/jparker/Documents/courses/Python/Programs/day2/Users/jparker/anaconda3/lib/python38.zip/Users/jparker/anaconda3/lib/python3.8/Users/jparker/anaconda3/lib/python3.8/lib-dynload/Users/jparker/anaconda3/lib/python3.8/site-packages/Users/jparker/anaconda3/lib/python3.8/site-packages/aeosa/Users/jparker/opt/anaconda3/lib/python3.8/site-packages/locket-0.2.1-py3.8.egg```  *Path and arguments differ from results with notebook*  Interactive Mode vs script modeAnother difference between running in a Notebook cell and running at the command line<jupyter_code># sum.py
#
# Show the difference between interactive and script mode
# Usage:
#      % python sum.py
#
# <NAME>, June 2019

17 + 25
# A script holding the program above
! more sum.py<jupyter_output># sum.py
#
# Show the difference between interactive and script mode
# Usage:
#      % python sum.py
#
# <NAME>, June 2019

17 + 25<jupyter_text>I see```python sum.py Show the difference between interactive and script mode Usage:      % python sum.py <NAME>, June 201917 + 25```<jupyter_code>! python sum.py    # Nothing is printed<jupyter_output><empty_output><jupyter_text>To get something from a script, we must call print()Write a new version<jupyter_code># script.py
#
# Show the difference between interactive and script mode
# Usage:
#      % python script.py
#
# <NAME>, June 2019

n = 17 + 25
print(n)
! python script.py<jupyter_output>42<jupyter_text>Commenting Scripts: always include following:We have more suggestions on Canvas: Modules/Resources/Documenting your Program<jupyter_code># programName.py
#
# Purpose of the program
# Usage
#     % python programName.py <params>
#
# Author and Date<jupyter_output><empty_output><jupyter_text>Stop and ThinkWhy do we need the Usage line?What would the usage line for the OS's copy program look like?Have you ever called a program with the wrong arguments?  What happened?  The Return value of a functionFunctions *return* a value to the caller.Sometimes we use the return value - len(s)- len() *returns* an integer representing the length of the argument.Sometimes we ignore the return value - print(s)- What does print() return?<jupyter_code>s = 'onetwo'

ret_val = len(s)
print(ret_val, type(ret_val))   # What does len() return?  
ret_val = print(s)
print(ret_val, type(ret_val))   # What does print() return?  
def print_greeting(name: str):              # Reminder
    print("Hello, " + name)

x = print_greeting('Sam')
print(x, type(x))   # What does the function return?<jupyter_output>Hello, Sam
None <class 'NoneType'><jupyter_text>print() and print_greeting() are "void functions"  They may do something useful, but they do not return a value*Well, they return **None**, but None isn't a useful value*  Downey calls functions that return a value 'Fruitful Functions"Void functions could be called Fruitless Functions<jupyter_code>def greeting(name: str):              # Reminder
    return "Hello, " + name

ret_val = greeting('Sam')
print(ret_val, type(ret_val))   # What does the function return?<jupyter_output>Hello, Sam <class 'str'><jupyter_text>Composing Functions We can compose fruitful functions I feed the value that len() returns to function type()```python    type( len(s) )``` I feed the value that type() returns to function print()```python    print( type( len(s) ) )```<jupyter_code>print(type(len('Hello')))<jupyter_output><class 'int'><jupyter_text>What will this do?```python    len(print(type('Hello')))```- I feed the value type() returns to function print()- I feed the value print() returns to function len()<jupyter_code>len(print(type('Hello')))<jupyter_output><class 'str'><jupyter_text>- type() returns - print() *prints* but *returns* None- len() complains  Parker's Prohibition *Never print in a function - return the result* Exceptions- Functions with 'print' in the name, such as print_greeting()- While debugging- When we have encountered an error and want to tell the user, but see below*When we encounter an error, we will learn how to throw an exception*  *What is wrong with printing?*Do you want len() to print the length of a string?Or should len() return the length so you can use it? *I found an interesting change machine at the laundromat*It has LEDs that show how many bills you put in, but it never returns a coin.  Stop and ThinkWhat is the return value of greeting()?What is the return value of print_greeting()?What does sys.getrefcount() take as a parameter, and what does it return?  Type Hints We can declare what kind of arguments we expectI will use Type Hints to help document functions<jupyter_code>def print_greeting(name: str):          # Parameter List
    print(f"Hello, {name}")

print_greeting('Sam')                   # Argument List
print_greeting(2)                       # We are not passing in a string
print_greeting([1, 2, 3])<jupyter_output>Hello, [1, 2, 3]<jupyter_text>Double() takes a string and returns a string<jupyter_code>def double(s: str) -> str:              # Take a string and return a string
    return s + s<jupyter_output><empty_output><jupyter_text>Python ignores type hints<jupyter_code># RIP Aretha
print(double('Sock it to me! '))
print(double(2))
print(double([1, 2, 3]))<jupyter_output>[1, 2, 3, 1, 2, 3]<jupyter_text>We can use the mypy program to check type hintsWe create a small program to test double()<jupyter_code>! more double.py<jupyter_output># double.py
#
# Return twice as much
#
# Usage:
#      % python double.py
#
# <NAME>, Sept. 2019


# Double a string
def double(s: str) -> str:
    return s + s


# RIP Aretha
print(double('Sock it to me! '))
print(double(2))
print(double([1, 2, 3]))<jupyter_text>```python double.py Return twice as much Usage:      % python double.py <NAME>, Sept. 2019 Double a stringdef double(s: str) -> str:    return s + s RIP Arethaprint(double('Sock it to me! '))print(double(2))print(double([1, 2, 3]))```<jupyter_code>! python double.py<jupyter_output>Sock it to me! Sock it to me! 
4
[1, 2, 3, 1, 2, 3]<jupyter_text>Although it doesn't match the types, double runsLet's use mypy to see if we are following the type hintsIf you don't have mypy installed, see instructions below<jupyter_code>! mypy<jupyter_output>usage: mypy [-h] [-v] [-V] [more options; see below]
            [-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...]
mypy: error: Missing target module, package, files, or command.<jupyter_text>Programs that expect command line parameters should complainIt is best if they tell you what they expected to seeThis should match what the programmer put in the Usage line of her commentsmypy takes a command line parameter telling it what file to check<jupyter_code>! mypy double.py<jupyter_output>double.py:18: error: Argument 1 to "double" has incompatible type "int"; expected "str"
double.py:19: error: Argument 1 to "double" has incompatible type "List[int]"; expected "str"
Found 2 errors in 1 file (checked 1 source file)<jupyter_text>You may see something like```python     zsh:1: command not found: mypy```This means you need to install mypy - see instructions below.  What I see from mypy:```pythondouble.py:18: error: Argument 1 to "double" has incompatible type "int"; expected "str"double.py:19: error: Argument 1 to "double" has incompatible type "List[int]"; expected "str"Found 2 errors in 1 file (checked 1 source file)```This tells us that we are calling double() with an unexpected type of parameter: an integer in the first case, and a list of integers in the second.  Installing mypyIf you don't have mypy, you can install it.After installing, make sure that your PATH variable points to it...<jupyter_code>! conda install mypy<jupyter_output>Collecting package metadata (current_repodata.json): ...working... done
Solving environment: ...working... done

# All requested packages already installed.<jupyter_text>You will see output like this from Anaconda when you install mypy.  Your details will differ: this was for a 3.7 base.  ```pythonconda install mypyCollecting package metadata (repodata.json): doneSolving environment: done Package Plan   environment location: /Users/jparker/anaconda3  added / updated specs:    - mypyThe following packages will be downloaded:    package                    |            build    ---------------------------|-----------------    conda-4.7.11               |           py37_0         3.0 MB    mypy-0.660                 |           py37_0         1.3 MB    mypy_extensions-0.4.1      |           py37_0           8 KB    typed-ast-1.1.0            |   py37h1de35cc_0         183 KB    ------------------------------------------------------------                                           Total:         4.6 MBThe following NEW packages will be INSTALLED:  mypy               pkgs/main/osx-64::mypy-0.660-py37_0  mypy_extensions    pkgs/main/osx-64::mypy_extensions-0.4.1-py37_0  typed-ast          pkgs/main/osx-64::typed-ast-1.1.0-py37h1de35cc_0The following packages will be UPDATED:  conda                                       4.7.10-py37_0 --> 4.7.11-py37_0Proceed ([y]/n)? yDownloading and Extracting Packagesmypy-0.660           | 1.3 MB    |  | 100% typed-ast-1.1.0      | 183 KB    |  | 100% conda-4.7.11         | 3.0 MB    |  | 100% mypy_extensions-0.4. | 8 KB      |  | 100% Preparing transaction: doneVerifying transaction: doneExecuting transaction: done```  For more on mypy and type hints, seehttps://mypy.readthedocs.io/en/latest/type_inference_and_annotations.html  Stop and ThinkWhat is the purpose of Type Hints?My medication tells me to take no more than 2 pills every 8 hours.    The Marriage vows ask the couple to care for each other in sickness and in health.Can you think of another examples IRL of similar caveats?  ScopeThe scope of a variable is where the variable is knownIn Boston, my friend Buzz lives in NewburyportIn Boulder, my friend Buzz is from St. Paul<jupyter_code># What variables are in scope in the notebook?

%who<jupyter_output>a	 b	 c	 chorus	 contract	 double	 greeting	 line	 list1	 
lst	 n	 p	 print_greeting	 ret_val	 s	 sys	 t	 u	 
v	 w	 x	 y	 z<jupyter_text>Example with multiple scope<jupyter_code>i = 1

def example():
    i = 5
    print(f"\t i is {i} in function example()")

    
print(f"i is {i} in main()")
example()
print(f"i is {i} in main()")<jupyter_output>i is 1 in main()
	 i is 5 in function example()
i is 1 in main()<jupyter_text>In the function we redefine i to be 5 This is said to 'occlude' the global value 1During a solar eclipse, the moon occludes the sun.https://en.wikipedia.org/wiki/Occultation When we leave the function, the global value is visible again.After the eclipse is over, we can see the sun again.  How to decide what the name 'Buzz' refers to Scope in Python is LEGB - Local, Enclosed, Global, then Builtin- Local: We try to resolve name in the Local name space- Enclosing: Next we look in the Enclosing definitions- Globasls: Next we look in Globals- Builtins: Finally we look in Builtins  Poorly chosen variable name can occlude a builtinThis is a common mistake: Caveat Emptor!Since we look in L, E, and G before we look in B, easy to mess upWe'll see two common victims: str and list str() takes an object and returns a string We also use repr() below, which returns the representation<jupyter_code>help(repr)
n = 17
print(f"n = {n} \t\t {type(n)}\n")

s = str(n)
print(f"s = {repr(s)} \t {type(s)}\n")

print(f"str \t\t {type(str)}")<jupyter_output>n = 17 		 <class 'int'>

s = '17' 	 <class 'str'>

str 		 <class 'type'><jupyter_text>To recap: str is a type, and str() takes an object and returns a string  Now override str<jupyter_code>str = 'guppy'
n = 17

s = str(n)   # Same statement as above, but
type(str)<jupyter_output><empty_output><jupyter_text>*That is, str is no longer a type: it is a simple string*In fact, str now has type str.    Repeat the experiment with class list<jupyter_code>x = list('cat')
print(x)
type(list)
# Now we override the meaning of list

list = [1, 2, 3]
y = list('cat')   # Same statement as above, but
print(y)
type(list)<jupyter_output><empty_output><jupyter_text>How to fix this?First, look at the environment.You will see that we have defined variables str and list<jupyter_code>%who<jupyter_output><empty_output><jupyter_text>Next, hit Kernel/Restart in your Notebook Then look again at the environment<jupyter_code>%who<jupyter_output><empty_output><jupyter_text>Once you have restarted the Kernel, you will see```pythonInteractive namespace is empty.```and you will have access to the original meaning of list() and str()<jupyter_code>x = str(17)
print(repr(x))

y = list('cat')
print(y)<jupyter_output><empty_output><jupyter_text>Stop and ThinkIn the program fragment below, we have a function which occludes the name list.The first call, list('cat'), will work.  We then call example, which redefines list.  Will the final call, list('dog'), work? Put some skin in the game! Don't run the program until you have a hypothesis! You can cut and paste the text below into the cell and run it once you have a hypothesis.```pythondef example():    list = [1, 2, 3]    print(list)    x = list('cat')print(x)example()x = list('dog')print(x)```<jupyter_code>## Run the example

...<jupyter_output><empty_output><jupyter_text>Why use Functions?  Four reasonsThe competent programmer is fully aware of the limited size of his own skull. He therefore approaches his task with full humility, and avoids clever tricks ... -- <NAME>   1) Fix Errors only once Example suggested by <NAME> in the CACM, April 1984 http://www.cs.bme.hu/~friedl/alg/knuth_song_complexity.pdf"However, the advent of modern drugs has led to demands for still less memory, and the ultimate improvement of Theorem 1 has consequently just been announced:"THEOREM 2.There exist arbitrarily long songs of complexity O(1)."<jupyter_code>## See https://www.youtube.com/watch?v=q3svW8PM_jc

def grunt():
    print("uh-huh")
          
          
def chorus():
    print("That's the way")
    grunt()
    print("I like it")
    grunt()
    print()
    
chorus()<jupyter_output><empty_output><jupyter_text>In fact, that is not correct.  grunt() should be:<jupyter_code>## Only need to fix this in one place
##
def grunt():
    print("uh-huh")
    print("uh-huh")<jupyter_output><empty_output><jupyter_text>2) Only write each task once<jupyter_code>def hit_single():
    chorus()
    chorus()
    chorus() 
    chorus()
    chorus()
    chorus()
    
hit_single()<jupyter_output><empty_output><jupyter_text>3) Separation of concerns<jupyter_code>def sausage():
    ...

sausage()       # I don’t want to know the details<jupyter_output><empty_output><jupyter_text>4) Debugging  Decompose your program into functions - makes it easier to debug Verify that each function is working Then assemble the components Allows you to take a leap of faith:  "grunt() is working, so problem is elsewhere"  Stop and ThinkThink of three complex tasks can you perform on autopilot, such as brushing your teeth.  If you drive, you can probably make a 'three point turn'. https://en.wikipedia.org/wiki/Three-point_turnDo you remember learning a three point turn?  Do you remember the attention it took?A function can codify a complex task so that we don't have to rethink it each time.    Python Library of the Week -  https://pymotw.com/3/index.html<jupyter_code>import platform                             # Not supported by Python Tutor

print('Ver:  ', platform.python_version())  # Note use of whitespace to lineup output
print('Build:', platform.python_build())<jupyter_output><empty_output><jupyter_text>I saw```pythonVer:   3.8.8Build: ('default', 'Apr 13 2021 12:59:45')```  Animal, vegetable, or mineral?<jupyter_code>print(type(platform.python_version()))
print(type(platform.python_build()))
platform.python_build()[1]<jupyter_output><empty_output><jupyter_text>Stop and thinkUse platform.system() call to find name of your Operating System (OS)  Drop days- We want you to succeed- But if you are struggling, please take stock- Do you have the time to continue?- There will be another version this Spring   Wow, That's Fantastic!  Turtle Graphics: A peek ahead to next week<jupyter_code># If you can't run this on your system, you can run on https://trinket.io
#
import turtle

# Create a turtle ojbect
bob = turtle.Turtle()

# Draw a picture
for i in range(45):
    # Draw an edge
    bob.fd(200)
    bob.lt(86)
    
turtle.mainloop()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11068949860543556, 'fraction_numerical': 0.01670234157099306, 'mean_word_length': 4.202463303526236, 'pattern_counts': {'":': 0, '<': 201, '<?xml version=': 0, '>': 208, 'https://': 9, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '53', 'dir': 'jupyter-structured-clean-dedup', 'id': '144931', 'license': 'MIT', 'n_tokens_mistral': 10509, 'n_tokens_neox': 9876, 'n_words': 3247, 'path': 'introduction-to-programming-with-python/lectures/cscie7_lecture_02.ipynb', 'repo_name': 'dark-teal-coder/harvard-graduate', 'size': '30936'}