<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Lecture 6
Step1:  So what is going on?  Well, Python variables are reference variables.  You could say "the variable a (b) is assigned to a list" rather than "the list is assigned to the variable a (b)".
From the Python Language Reference, section 3.1
Step2:  Functions and Environments
We've already discussed how functions are first class in Python.  If you don't remember this, please consult previous lectures.
Step3:  Defining your own environment
When we apply a user defined function to some arguments, something slightly different happens from what we saw in the previous example
Step4:  Model of Evaluation
The combination of
environments
variables bound to values
functions 
together describes a Model of Evaluation. This model can be used to implement an interpreter for a programming language.
Parameters are passed by sharing in Python
Each formal parameter gets "a COPY of the REFERENCE". Thus the parameters inside the function arguments become aliases of the actual arguments. You could also say
Step5:  A few more comments
The binding of names (from Python Execution Model Document)
The following constructs bind names
<ASSISTANT_TASK:>
Python Code:
from IPython.display import HTML # Allows us to embed HTML into our notebook.
HTML('<iframe width="800" height="400" frameborder="0" src="http://pythontutor.com/iframe-embed.html#code=a%20%3D%20%5B1,%203,%205%5D%0Ab%20%3D%20a%0Aprint%28%22a%20%3D%20%7B0%7D%20and%20has%20id%20%7B1%7D%22.format%28a,%20id%28a%29%29%29%0Aprint%28%22b%20%3D%20%7B0%7D%20and%20has%20id%20%7B1%7D%22.format%28b,%20id%28b%29%29%29%0Aprint%28%22Is%20b%20a%3F%20%7B0%7D%22.format%28b%20is%20a%29%29%0A%0Aa.append%287%29%0Aprint%28%22a%20%3D%20%7B%7D%22.format%28a%29%29%0Aprint%28%22b%20%3D%20%7B%7D%22.format%28b%29%29&codeDivHeight=400&codeDivWidth=350&cumulative=false&curInstr=0&heapPrimitives=false&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe>')
Explanation: Lecture 6:  Towards Intermediate Python
Topics:
* Recap so far
* Nested environments
* Closures
* Decorators
Recap So Far
We have discussed the very basics of Python, but mostly from a syntactical point of view.  Today, we will fill in a few of the gaps by revealing a bit more about what is going on under the hood.
Preliminaries
Before we begin, there is something that you should know about.  It's http://pythontutor.com/ and it's a great way to learn what is going on under the hood when you write Python.  You can visualize the Python code you write:  Visualize.  I'll have you test out and visualize some very small scripts using that website.
Note:  When trying to embed HTML into your notebook, you need to use the syntax:  HTML('url').  pythontutor has a Generate embed code button which will generate the necessary code to embed into your webpage.
Reference Variables
Let's revisit the most basic Python.  Here, we'll just assign values to some names.
Note that a variable in Python is called a name.  So the assignment statement a = 1 says that the name a is assigned the integer value 1.  You can call a a variable too if you like.
End of explanation
HTML('<iframe width="1000" height="500" frameborder="0" src="http://pythontutor.com/iframe-embed.html#code=a%20%3D%20%5B2,%203,%204%5D%0Ac1%20%3D%202.0**2.0%0Ac2%20%3D%20%5Bi**2.0%20for%20i%20in%20a%5D%0Aprint%28c2%29&codeDivHeight=400&codeDivWidth=350&cumulative=false&curInstr=0&heapPrimitives=false&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe>')
Explanation: So what is going on?  Well, Python variables are reference variables.  You could say "the variable a (b) is assigned to a list" rather than "the list is assigned to the variable a (b)".
From the Python Language Reference, section 3.1:
Every object has an identity, a type and a value. An object’s identity never changes once it has been created; you may think of it as the object’s address in memory. The ‘is‘ operator compares the identity of two objects; the id() function returns an integer representing its identity (currently implemented as its address).
From Fluent Python: 
Python Types
Every variable in python gets a type 
Python is a strongly typed language
It is also dynamically typed 
Types are assigned at run-time rather than at compile time as in a language like C
This makes it slower since the way data is stored cannot be initially optimal
When the program starts you dont know what that variable will point to.
Here is a discussion from Chapter 11: Further Reading in Fluent Python:
Strong versus weak typing
If the language rarely performs implicit conversion of types, it’s considered strongly typed; if it often does it, it’s weakly typed. Java, C++, and Python are strongly typed. PHP, JavaScript, and Perl are weakly typed.
Static versus dynamic typing
If type-checking is performed at compile time, the language is statically typed; if it happens at runtime, it’s dynamically typed. Static typing requires type declarations (some modern languages use type inference to avoid some of that). Fortran and Lisp are the two oldest programming languages still alive and they use, respectively, static and dynamic typing.
Frames
Whenever we use Python Tutor we see two columns.  The first column is labeled Frames.
What is a frame?
The evaluation of any expression requires knowledge of the context in which the expression is being evaluated. This context is called a frame. An environment is a sequence of frames, with each frame or context having a bunch of labels, or bindings, associating variables with values. 
The sequence starts at the "global" frame, which has bindings for imports, built-ins, etc.
End of explanation
HTML('<iframe width="1000" height="500" frameborder="0" src="http://pythontutor.com/iframe-embed.html#code=s%20%3D%20\'The%20lost%20world...\'%0Alen_of_s%20%3D%20len%28s%29%0Amy_len%20%3D%20len%0Amy_len_of_s%20%3D%20my_len%28s%29&codeDivHeight=400&codeDivWidth=350&cumulative=false&curInstr=0&heapPrimitives=false&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe>')
Explanation: Functions and Environments
We've already discussed how functions are first class in Python.  If you don't remember this, please consult previous lectures.
End of explanation
HTML('<iframe width="1000" height="500" frameborder="0" src="http://pythontutor.com/iframe-embed.html#code=def%20check_oddness%28x%29%3A%0A%20%20%20%20if%20x%252%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20return%20x%20/%202.0%0A%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20return%20%28x%20-%201.0%29%20/%202.0%0A%0Aa%20%3D%206.0%0An1%20%3D%20check_oddness%28a%29%0A%0Ab%20%3D%2015.0%0An2%20%3D%20check_oddness%28b%29&codeDivHeight=400&codeDivWidth=350&cumulative=false&curInstr=0&heapPrimitives=false&origin=opt-frontend.js&py=3&rawInputLstJSON=%5B%5D&textReferences=false"> </iframe>')
Explanation: Defining your own environment
When we apply a user defined function to some arguments, something slightly different happens from what we saw in the previous example:
We bind the names of the arguments in a NEW local frame
We evaluate the body of the function in this new frame
End of explanation
def f(x):
    print(id(x))
d={'a':17.0, 'b':35.0}
print(id(d))
f(d)
Explanation: Model of Evaluation
The combination of
environments
variables bound to values
functions 
together describes a Model of Evaluation. This model can be used to implement an interpreter for a programming language.
Parameters are passed by sharing in Python
Each formal parameter gets "a COPY of the REFERENCE". Thus the parameters inside the function arguments become aliases of the actual arguments. You could also say: a function gets a copy of the arguments, but the arguments are always references.
End of explanation
import numpy as np
c = 5000.0
def do_integral(function):
    c = 13.0
    # Some algorithm for carrying out an integration
    print(c)
x = np.linspace(-1.0, 1.0, 100)
y = x * x
do_integral(y)
Explanation: A few more comments
The binding of names (from Python Execution Model Document)
The following constructs bind names: formal parameters to functions, import statements, class and function definitions (these bind the class or function name in the defining block), and targets that are identifiers if occurring in an assignment, for loop header, or after as in a with statement or except clause. The import statement of the form from ... import * binds all names defined in the imported module, except those beginning with an underscore. This form may only be used at the module level.
If a name is bound in a block, it is a local variable of that block, unless declared as nonlocal or global. If a name is bound at the module level, it is a global variable. (The variables of the module code block are local and global.) If a variable is used in a code block but not defined there, it is a free variable.
The lookup of names
A scope defines the visibility of a name within a block. If a local variable is defined in a block, its scope includes that block. If the definition occurs in a function block, the scope extends to any blocks contained within the defining one, unless a contained block introduces a different binding for the name.
When a name is used in a code block, it is resolved using the nearest enclosing scope. The set of all such scopes visible to a code block is called the block’s environment.
End of explanation
<END_TASK>