I719 Fundamentals of Python/lecture5

From ICO wiki

Advanced Testing

See
https://wiki.itcollege.ee/index.php/I719_Fundamentals_of_Python/testing

Linting

Python has a style guide called PEP8.

you can check if your code follows PEP8 using the PEP8 linter.

(you may also install this using your OS's package manager)

pip3 install pep8
python3 -m pep8 ~/path/to/your_file.py

This will print out each error as a line in stdout

path/to/your_file.py:LINE:COLUMN PEP8_ERROR EXPLANATION

for example:

btc/btc_price_tests.py:8:80: E501 line too long (648 > 79 characters)
btc/btc_price_tests.py:11:1: E302 expected 2 blank lines, found 1

There is another tool called flake8, which is installed the same way and checks for problems in your code that will cause runtime problems, as well as the pep8 checking.

I recommend you configure your editor to use flake8

Please see http://blog.sideci.com/2015/12/14/style-guide-of-python-and-lint-tool/ for more information on linting

Datetime

see https://docs.python.org/3/library/datetime.html

from datetime import datetime

# convert a timestamp to python native datetime object
timestamp = 1488430906
d = datetime.fromtimestamp(timestamp)

TASK 1

Print the titles of all the frontpage articles on reddit, with the time in normal format (i.e 11:23) next to it.

resource: https://www.reddit.com/.json
example output

11:23 Sessions spoke twice with Russian ambassador during Trump\u2019s presidential campaign, Justice officials say \/\/ CAN WE HAVE AN INDEPENDENT INVESTIGATION NOW? Call your Representative and get them on the record, Country or party?

NOTE

reddit has rate limiting and does not give consistent responses!
download the json data as a json file and use the following code

import json

json_file = open('frontpage.json')
data = json.load(json_file)
json_file.close()

Solution

import argparse
import json

from datetime import datetime


def get_time_with_title(article):
    timestamp = article['data']['created_utc']
    d = datetime.fromtimestamp(timestamp)
    time = d.strftime('%H:%M')
    title = article['data']['title']
    result = '{time} {title}'.format(time=time, title=title)
    return result


def print_headlines(path):
    with open(path) as json_file:
        data = json.load(json_file)
    articles = data['data']['children']
    for article in articles:
        line = get_time_with_title(article)
        print(line)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('file_name')
    args = parser.parse_args()
    print_headlines(args.file_name)


if __name__ == '__main__':
    main()

Classes part 2

see "6. Classes" section of https://learnxinyminutes.com/docs/python3/

lamdbas

Lamdbas are like functions, but are not necessarily defined with a name. You can assign a lamdba expression to a variable, but if you do this, then you should define a function.

# do this
def plus_one(x):
    return x + 1

# do not do this
plus_one_lambda = lamdba x: x + 1

plus_one(1)  # 2
plus_one_lambda(1)  # 2

Lamdba expressions are used when a short function is needed as an argument for another function.

Function that take lambda expression often work on some iterable and need to be called on each iteration. For example map is a function found in many programming languages. It take an iterable and returns an iterable of equal dimension (i.e. length), but with each element modified in a some way. In python, the first argument of the map function is a function, which is called on each element in the iterable.

def square(x):
    return x**2

# map returns a special map type that must be converted to a list to print
print(list(map(square, range(4))))
print(list(map(lambda x: x**2, range(4))))

prints:

[0, 1, 4, 9]
[0, 1, 4, 9]

list comprehension

in modern python, the map function is rarely used. The preferred syntax is the list comprehension. it is like a for loop.
the syntax is the following:

[x + 1 for x in iterable]

The first part, x + 1 in this example, can be anything. Whatever this evaluates to, becomes an element in the resulting list. The rest of the comprehension is like a for loop, but the x variable is used in the first part.

All of the following print the same values

# Non-functional way, generate a new list
squares = []
for x in range(4):
    squares.append(x**2)
print(squares)

# map() functional way
squares = map(lambda x: x**2, range(4))
print(list(squares))

# modern way
squares = [x**2 for x in range(4)]
print(squares)