Lab: Some Python Extras

Optional extra credit

If you're done with the exam review labs and in good shape with the homework, here is another lab that you can do.

One of our TAs wanted to create a lab for you with some advanced Python language features. The questions are down at the bottom, the top comments explain how to use lambda, filter and map.

As a historical note, these features come from the Lisp family of functional programming languages, which Python takes many cues from. Guido van Rossum, who created and maintains Python (now being paid by Google to do so), wanted to remove lambda, filter and map from Python 3, because they mostly end up serving the same purpose as list comprehensions, any and all, which he considers the most Pythonic way to do things. There was enough pushback from people who like using them that they stayed.

from math import cos
"""
Pythonic goods,




Functions,

We are all familiar with this function:

def pow(base, exp):
    return base ** exp

Now, let's write it a different way. Declare a variable called "pow" and set
it equal to "lambda base, exp: base ** exp". Notice everything to the left
of the colon. Think of that as your parameters in a function just like the example
above. Everything to the right of the colon is the function definition, without the
return.

def addition(a,b):
    return a+b

You would not create a function for this, but the idea is you can write this in
a one liner as

addition = lambda a,b: a+b

You call these "anonymous" functions like you would call a regular function.

addition(3,4)

Lambdas are useful when you want to write a small function like the above
examples.



Map,

Say you're given the task to square each number in a list and add 17 to it.
You would have something like:

mylist = [1,2,3,4]
index = 0
for number in mylist:
    mylist[index] = pow(number, 2) + 17
    index += 1

Or,

mylist = [1,2,3,4]
for index, number in enumerate(mylist):
    mylist[index] = pow(number, 2) + 17

Notice enumerate.

It creates an iterable object that contains tuples of indices and their values.

e.g. enumerate(mylist) => (0, 1), (1, 2), (2, 3), (3, 4) where the first number
is the index and the second number in each tuple is the value associated with
mylist.

There is another way of writing this and we can do this with a one liner.
Lambda is useful in this situation.

mylist = map(lambda number: pow(number, 2) + 17, mylist)

Let's break it down,

f = lambda number: pow(number, 2) + 17.
f(5) = 5^2+17 => 25 + 17 => 42 <- the meaning of life, bad joke.

From map(lambda number: pow(number, 2) + 17, mylist) let's replace the lambda
part with f, since f has the functionality of lambda number: pow(number, 2) + 17.

So now we have mylist = map(f, mylist)

f is mapped to each value of mylist and returns an iterable object.

Once you iterate through it you should have
18.0
21.0
26.0
33.0






Filter,


Say we need to find all the odd numbers in a list and store them in a seperate
list. We can do the following:

numbers = range(100)
odds = []
for number in numbers:
    if number % 2 == 1:
        odds.append(number)

Again, lambda comes in handy.

Say we had to write a function that checks to see if a number is odd. It would
look like

def isodd(number):
    return number % 2 == 1

With a lambda it would look like this:

isodd = lambda number: number % 2 == 1

The code to filter out odds would look like this with the filter function:

odds = filter(isodd, numbers)
or
odds = filter(lambda number: number%2==1, numbers)


Same idea from map, you map every value in numbers with the lambda expression
and it returns an iterable object. Note the lambda expression argument for filter
should return a boolean value.





Strings,


Strings are immutable. That means you can not assign a value to a specific index.
e.g.

hey = "hello Guys!"
Try to change the first letter to H

hey[0] = 'H'

That should give you an error saying "'str' object does not support item assignment"

so to get around that is to cast it to a list of characters:

hey = list(hey)

Now hey is a list of characters rather than a string.

so hey[0] = 'H' works now.

But hey is a list of characters instead of a string so you need to convert back.
You can do:

hey = ''.join(hey)


Where join, joins or concatenates the list seperate by no spaces.

hey = "Hello Guys!"



"""




# given a string, reverse it without using reverse or [::-1]
# reverse_string("Hello") => "olleH"
# hint: use list() and .join

# given a sentence, reverse the order of words and reverse the words, without
# using reverse or [::-1]
# reverse_sentence("Hello World") => "dlroW olleH"

# check if a string is a palindrome
# palindrome("racecar") => True

# given a list of 999 unique numbers, sorted, there is one missing number that
# completes the numbers 1...1000, find that number
# hint use enumerate
# find_number([1,2,4,5,6]) => 3

# given a list of lists, flatten it
# flattener([[1,2,3],[8,9]]) => [1,2,3,8,9]