Python 3

home

Practice Problems

Practice Problem: List sum (linear and recursion)

Given a list of numbers, sum them up using a linear approach and using recursion. Answers appear on next slide.





Practice Problem: List sum (linear and recursion) (Answers)

Given a list of numbers, sum them up using a linear approach and using recursion. linear approach


def list_sum_linear(num_list):
    the_sum = 0
    for i in num_list:
        the_sum = the_sum + i
    return the_sum

print(list_sum([1,3,5,7,9]))

recursion approach


def list_sum_recursive(num_list):
    if len(num_list) == 1:
        return num_list[0]
    else:
        return num_list[0] + list_sum_recursive(num_list[1:])

print(list_sum_recursive([1,3,5,7,9]))




Practice Problems: ETL Developer

This was a question in an interview at AppNexus that I helped conduct, calling for a Python ETL developer (extract, transform, load) -- not a high-end position, but still one of value (and significant remuneration). Answers appear on next slide. Class and STDOUT data stream


class OT(object):
    def __init__(self, *thisfile):
        self.file = thisfile

    def write(self, obj):
        for f in self.file:
            f.write(obj)

sys.stdout = OT(sys.stdout, open('myfile.txt'))

1. What does this code do? Feel free to talk it through 2. What is the 'object' in the parentheses? 3. What does the asterisk in *thisfile mean? local and global namespace


var = 10

def myfunc():
    var = 20
    print(var)

myfunc()
print(var)

1. What will this code output? Why? "sort" functions and multidimensional structures


def myfunc(arg):
    return arg

struct = [ { 'a': [1, 2, 3], 'b': [4, 5, 6], 'c': [7, 8, 9] }, { 'a': [10, 12, 13], 'b': [1, 2, 3], 'c': [1, 2, 3] },  { 'a': [1, 2, 3], 'b': [1, 2, 3], 'c': [1, 2, 3] } ]

dd = sorted(struct, key=myfunc)

1. What type of object is arg? 2. Rewrite the 'myfunc' function so the dicts are sorted by the sum of values associated with 'c'. 3. Convert your 'myfunc' function as a lambda 4. Loop through struct and print out just the last value of each list. import statements 1. which of these import statements do you favor and why?


import datetime

import datetime as dt

from datetime import *




Practice Problems: ETL Developer (Answers)

Class and STDOUT data stream


class OT(object):
    def __init__(self, *thisfile):
        self.file = thisfile

    def write(self, obj):
        for f in self.file:
            f.write(obj)

sys.stdout = OT(sys.stdout, open('myfile.txt', 'w'))

1. What does this code do? Feel free to talk it through. The class creates an object that stores multiple open data streams (in this case, sys.stdout and an open filehandle) in an attribute of the instance. When the write() method is called on the object, the class will write to each of the stream(s) initialized in the instance, in this case to sys.stdout() and to the open file. The OT instance is being assigned to sys.stdout. This means that any call to sys.stdout.write() will pass to the instance. In addition, the print statement will also call sys.stdout.write(). The effect of this code is for any print statements that occur afterward to write to both STDOUT and to the filehandle initialized when the instance was constructed. 2. What is the 'object' in the parentheses? It causes the OT class to inherit from object. Thus OT is a new-style class. 3. What does the asterisk in *thisfile mean? It allows any number of arguments to be passed to the constructor / to __init__. local and global namespace


var = 10

def myfunc():
    var = 20
    print(var)

myfunc()
print(var)

1. What will this code output? Why? 20 10 Inside myfunc() the local variable var is set to 20 and printed. Once returned from the function, the global var is "revealed" (i.e., it is now accessible under the name var. "sort" functions and multidimensional structures


def myfunc(arg):
    return arg

struct = [ { 'a': [1, 2, 3], 'b': [4, 5, 6], 'c': [7, 8, 9] }, { 'a': [10, 12, 13], 'b': [1, 2, 3], 'c': [1, 2, 3] },  { 'a': [1, 2, 3], 'b': [1, 2, 3], 'c': [1, 2, 3] } ]

dd = sorted(struct, key=myfunc)

1. What type of object is arg? arg is a string, or a key from the dict. 2. Rewrite the 'myfunc' function so the dicts are sorted by the sum of values associated with 'c'. def myfunc(arg): return sum(myfunc(arg)) 3. Convert your 'myfunc' function as a lambda lambda arg: sum(myfunc(arg)) 4. Loop through struct and print out just the last value of each list. for key in struct: print(struct[key][-1]) import statements 1. which of these import statements do you favor and why?


import datetime

import datetime as dt

from datetime import *

The answer should see the candidate disavowing any use of the last form, which imports all symbols from the datetime module into the global namespace, and thus risks collisions with other modules





Practice Problems: Calculate a Factorial using linear approach and recursion

A factorial is the multiplication of each integer in a consecutive range starting at 0. So 4 factorial is 1 * 2 * 3 * 4 = 24. In the recursive approach, the function's job is very simply to multiply the number passed to it by the product produced by another call to the function with a number one less than the one passed to it. The function thus continues to call itself with one less integer until the argument becomes 0, at which point it returns. As each recursively called function returns, it passes back the value it was passed, multiplied by the value passed to it. So on the way back the values are multiplied. Answers appear on next slide.





Practice Problems: Calculate a Factorial using linear approach and recursion (Answers)

factorial: "linear" approach


def factorial_linear(n):
    prod = 1
    for i in range(1, n+1):
        prod = prod * i
    return prod

factorial: "recursion" approach


def factorial_recursive(n):
   if n < 1:
       return 1
   else:
       return_number = n * factorial_recursive(n-1)  # recursive call
       print('{}! = {}'.format(n, return_number))
       return return_number




Practice Problems: Calculate a fibonacci series using linear approach and recursion

A fibonacci series is one in which each number is the sum of the two previous numbers. Answers appear on next slide.





Practice Problems: Calculate a fibonacci series using linear approach and recursion (Answers)

A fibonacci series is one in which each number is the sum of the two previous numbers. linear approach


def fib_lin(max):

    prev = 0
    curr = 1

    while curr < max:
        print(curr, end=' ')
        newcurr = prev + curr
        prev = curr
        curr = newcurr




Practice Problems: Calculate prime numbers to a max value

Answers appear on next slide.





Practice Problems: Calculate prime numbers to a max value (Answer)

def get_primes(maxval):
    startval = 2

    while startval <= maxval:
        counter = 2

        while counter < startval:
            if startval % counter == 0:
                startval = startval + 1
                counter = 2
                continue
            else:
                counter = counter + 1
                continue

        print(startval)

        startval = startval + 1




Practice Problems: reverse a sequence

this_list = ['a', 'b', 'c', 'd', 'e']

Answers appear on next slide.





Practice Problems: reverse a sequence (Answer)

this_list = ['a', 'b', 'c', 'd', 'e']


# using reversed
print(list(reversed(this_list)))

# using sorted
print(sorted(this_list, reverse=True))

# using negative stride
print(this_list[::-1])

# using list.insert()
newlist = []
for el in this_list:
    newlist.insert(0 ,el)

# using indices
newlist = []
index = len(this_list)-1
while index >= 0:
    newlist.append(this_list[index])
    index = index - 1




Practice Problems: given two strings, detect whether one is an anagram of the other

Answers appear on next slide.





Practice Problems: given two strings, detect whether one is an anagram of the other (Answer)

def ispalindrome(test1, test2):

    test2 = list(test2)
    for char in test1:
        try:
            test2.remove(char)
        except ValueError:
            return False
    if test2:
        return False
    return True

str1 = 'allabean'
str2 = 'beallana'

print(ispalindrome('allabean', 'beallana'))

print(ispalindrome('allabean', 'beallaaa'))




Practice Problems: given a string, detect whether it is a palindrome

Answers appear on next slide.





Practice Problems: given a string, detect whether it is a palindrome (Answer)

test_string = 'Able was I ere I saw Elba'

if test_string.lower() == test_string.lower()[::-1]:
    print('"{}" is a palindrome'.format(test_string))




Python "gotcha" questions

These really are unfair, and not necessarily a good barometer -- they simply require that you know the quirks that lead to the strange output. But they can point out interesting aspects of the language. Answers appear on next slide. for each of the following blocks of code, what is the output?


def extendList(val, list=[]):
    list.append(val)
    return list

list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')

print("list1 = %s" % list1)
print("list2 = %s" % list2)
print("list3 = %s" % list3)

def multipliers():
    return [lambda x : i * x for i in range(4)]

print([m(2) for m in multipliers()])

class Parent(object):
    x = 1

class Child1(Parent):
    pass

class Child2(Parent):
    pass

print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Parent.x = 3
print(Parent.x, Child1.x, Child2.x)

def div1(x,y):
    print("%s/%s = %s" % (x, y, x/y))

def div2(x,y):
    print("%s//%s = %s" % (x, y, x//y))

div1(5,2)
div1(5.,2)
div2(5,2)
div2(5.,2.)

1. list = [ [ ] ] * 5
2. list  # output?
3. list[0].append(10)
4. list  # output?
5. list[1].append(20)
6. list  # output?
7. list.append(30)
8. list  # output?




Python "gotcha" questions (Answers)

for each of the following blocks of code, what is the output?


def extendList(val, list=[]):
    list.append(val)
    return list

list1 = extendList(10)
list2 = extendList(123,[])
list3 = extendList('a')

print("list1 = %s" % list1)
print("list2 = %s" % list2)
print("list3 = %s" % list3)

# [10, 'a']
# [123]
# [10, 'a']

default list is constructed at time of definition


def multipliers():
    return [lambda x : i * x for i in range(4)]

print([m(2) for m in multipliers()])


# [6, 6, 6, 6]

Python closures are late binding, means that when we finally call the function it will look up the value of i and find a 6


class Parent(object):
    x = 1

class Child1(Parent):
    pass

class Child2(Parent):
    pass

print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
Parent.x = 3
print(Parent.x, Child1.x, Child2.x)

## 1 1 1
## 1 2 1
## 3 2 3

Attribute lookup starts in instance, then checks class and then parent class(es).


def div1(x,y):
    print("%s/%s = %s" % (x, y, x/y))

def div2(x,y):
    print("%s//%s = %s" % (x, y, x//y))

div1(5,2)
div1(5.,2)
div2(5,2)
div2(5.,2.)


## 2
## 2.5
## 2
## 2

"floor division" (i.e., integerized result) is the default with integer operands; also can be specified with the // "floor division" operator


1. list = [ [ ] ] * 5
2. list  # output?
3. list[0].append(10)
4. list  # output?
5. list[1].append(20)
6. list  # output?
7. list.append(30)
8. list  # output?


## [[], [], [], [], []]
## [[10], [10], [10], [10], [10]]
## [[10, 20], [10, 20], [10, 20], [10, 20], [10, 20]]
## [[10, 20], [10, 20], [10, 20], [10, 20], [10, 20], 30]

key: in a * multiplication, Python simply duplicates the reference rather than the list





[pr]