When you are learning something that is pretty different from anything you may have done before (like Python), there will be a lot of interesting features that you just won’t have the capacity to absorb the first time you are introduced to concepts. In this first part of the notes, we revisit some concepts that we’ve already covered but introduce these additional features. This will feel partly feel like a review, but hopefully, will make things clearer by giving you a more refined understanding.
We covered for-loops in only our second class on Python, which was arguably too early to do so in the semester. We were still try to get a sense of how to create variables, how to define and call functions, and then - bam!- we were applying functions to each element of a list using a for loop.
Now that we know how to create a for loop - for i in my_list
or for x in my_list
, we can sit back and try to get a better sense of when we want to really use a for loop. One key point to recognize about for loops is that there is a time component. For loops execute the indented code block sequentially. This will be helpful is certain contexts - like optimization or textual analysis- but if we think back to our initial application of iterating over a list to square each elements, we see that there’s nothing inherently sequential about this task.
The square of the second element in the list does not depend on the the first element of the lists or its square. Likewise, the square of the third element doesn’t depend on the first or second elements in the list. Our aim was to simply apply the same function to each element of the list and store the results as elements in a new list.
Python has just the function for this. map
is a built-in function in Python that takes a two arguments. The first is the function that we want to apply. The second is the list that we want to apply it to. Calling map
on a function and list applies the function to each element of the list. The only subtle part is that map
is lazy. When you call map
it is basically like - yes I understand your instructions, but I am going to wait until you actually need the output. It’s lazy. It doesn’t want to have to execute the instructions until you really need it to. So to make this all work, we wrap map
in with list
which tells python that we really need the output of map
. In the following example, we replace the for loop with map
.
At the end of the first class, we highlighted that the two fundamental aspects of programming are data (creating data, storing data), and functions (transforming data). And thus far, we’ve seen a variety of functions in python - those that we defined using the key word def
, those that came built in with python like print()
and +
, and more recently functions written by someone else like pd.read_csv
or pd.read_excel
.
Without trying to categorize everything, we’ll find in practice that we often want to make use of a fourth kind of function known as a temporary function. A temporary function is a function without a name. Below is a temporary function which squares the input: $x \mapsto x^2$ .
lambda x: x**2
A function without a name?! How could we call it? How could we use a function without a name? We’ll, let’s think for a moment — If the function has no name, how must it be constructed? If you recall, the typical order of working with functions has been to first define a function and then to call it. If you reverse the order of these steps, Python throws an error. Temporary functions essentially do both steps at once. And indeed you can see this in the code block below: we define and call the function in one line.