Quickstart: install Jupyter Lab into a virtual environment
- Create "envs" directory for virtual environments in your home directory and cd into it:
mkdir envs
cd envs
- Create a virtual environment named "labs" inside the "envs" directory:
python3 -m venv labs
or, if the above command does not work:
python -m venv labs
- Activate your virtual environment
On Linux: source labs/bin/activate
On Windows: labs\Scripts\activate.bat
- Install the "jupyterlab" package into the "labs" virtual environment using pip package manager:
pip install jupyterlab
- Run Jupyter Lab in your home directory:
cd ..
jupyter lab
1. Slices
- Given a string s = 'Hello World!', take the slice 'World'
- Given a list
a = list(range(100))
take a slice of it that lists all numbers that are multiple of 5 in reverse order:
[95, 90, 85, 80, 75, 70, 65, 60, 55, 50, 45, 40, 35, 30, 25, 20, 15, 10, 5, 0]
- For the above task, create a named slice and use it on another list
b = list(range(50))
Make sure it returns correct results (from 45 to 0)
2. Sorting
- Given a list of numbers, sort them descending in-place
- Given a tuple of strings, sort them (case insensitive)
- Given a set of strings, sort them by last letter
- Given a sequence of strings, sort them by length
3. List comprehensions
Each task should be done using a single (possibly nested) list comprehension (just one line of code).
- Produce a list of squares of numbers from 0 to 10
- Create a new list out of a given list of numbers, which contains only the positive numbers from the list
- Given a sentence, produce a list of last letters of every word
- Given two lists (a = [a1, a2]; b = [b1, b2, b3]), produce a list of all possible pairs of their elements:
[(a1, b1), (a1, b2), (a1, b3), (a2, b1), (a2, b2), (a2, b3)]
- Build a list of lists of 5 random numbers ranging from 1 to 6
4. Dict comprehensions
Each task should be done using a single (possibly nested) dict comprehension (just one line of code).
- Map the numbers from 0 to 10 to their cubes
- Given two lists of the same length, build a dictionary where keys are elements of the first list, and values are elements of the second list
- Given two dicts with overlapping keys and values of type list, build a dict containing all keys by concatenating value lists
d1, d2 = dict(k1=[v11, v12], k2=[v21]), dict(k2=[v22], k3=[v31, v32])
Expected result:
dict(k1=[v11, v12], k2=[v21, v22], k3=[v31, v32])
5. Generators
- Write a generator function that returns the Fibonacci series
- Write a generator of a geometric progression (with an argument)
- Write a countdown(n) generator function that yields numbers from a positive n down to 0
6. Iterators
- Write an iterator class that iterates over the Fibonacci series
- Write an iterator for a geometric progression (with an argument)
- Write a Countdown iterator class that returns numbers from a positive n down to 0
- Make it possible to use reversed() on your Countdown iterator
7. Files and I/O
- Write a function
count_word(filename, word) that returns how many times word appears in a large file filename
Don't read the entire file into memory
- Given a list of heterogeneous values, write its content to a file, splitting values by a newline character
8. Decorators
- Write a @timeit decorator that measures and prints the time spent by a decorated function
import time
@timeit
def slow_sum(a, b, *, delay):
time.sleep(delay)
return a + b
slow_sum(2, 2, delay=1)
Example output:
1.015 seconds
4
- Add a min_seconds argument to the @timeit decorator so it only print the time if it is greater than the value of the argument
@timeit(min_seconds=1)
def slow_sum(a, b, *, delay):
time.sleep(delay)
return a + b
@timeit(min_seconds=2)
def slow_mul(a, b, *, delay):
time.sleep(delay)
return a * b
print(slow_sum(1, 1, delay=1))
print(slow_mul(3, 3, delay=1))
Output:
1.002 seconds
2
9
- Make sure the @timeit decorator works with and without parentheses (it should still be possible to pass the min_seconds argument)
@timeit
def slow_sum(a, b, *, delay):
time.sleep(delay)
return a + b
@timeit(min_seconds=2)
def slow_mul(a, b, *, delay):
time.sleep(delay)
return a * b
@timeit()
def slow_div(a, b, *, delay):
time.sleep(delay)
return a / b
print(slow_sum(1, 1, delay=1))
print(slow_mul(3, 3, delay=1))
print(slow_div(4, 2, delay=1))
Output:
1.001 seconds
2
9
1.001 seconds
2.0
- Decorate a function with a docstring and ensure that your decorator keeps it
@timeit
def slow_sum(a, b, *, delay):
"""Return a sum of a and b with a delay"""
time.sleep(delay)
return a + b
help(slow_sum)
Output:
Help on function slow_sum in module __main__:
slow_sum(a, b, *, delay)
Return a sum of a and b with a delay
- Make you decorator add an extra argument debug to decorated function; it should only print time if debug=True is passed to the function
@timeit(min_seconds=1)
def slow_sum(a, b, *, delay):
time.sleep(delay)
return a + b
print(slow_sum(1, 2, delay=1))
print()
print(slow_sum(2, 3, delay=1, debug=True))
Output:
3
1.010 seconds
5
- Create a timeit context manager that can be used as a decorator
@timeit()
def slow_sum(a, b, *, delay):
time.sleep(delay)
return a + b
print(slow_sum(2, 2, delay=1))
with timeit():
time.sleep(1)
Output:
1.001 seconds
4
1.013 seconds
9. Descriptors
- Implement ShowAccess descriptor that prints message when an attribute is accessed
- Make sure it also prints the name of attribute
- Make sure the ShowAccess descriptor does not require specifying the name of attribute manually so the following code works:
import math
class Circle(DebugObject):
radius = ShowAccess()
def __init__(self, radius):
self.radius = radius
@property
def area(self):
return math.pi * self.radius ** 2
c = Circle(100)
c.area
del c.radius
Output:
Set radius = 100
Get radius = 100
Delete radius = 100
- Make sure the descriptor works correctly with multiple attributes:
class Rectangle(DebugObject):
a = ShowAccess()
b = ShowAccess()
def __init__(self, a, b):
self.a = a
self.b = b
@property
def area(self):
return self.a * self.b
@property
def perimeter(self):
return 2 * (self.a + self.b)
r = Rectangle(10, 20)
print('Area:', r.area)
print('Perimeter:', r.perimeter)
del r.a
Output:
Set a = 10
Set b = 20
Get a = 10
Get b = 20
Area: 200
Get a = 10
Get b = 20
Perimeter: 60
Delete a = 10
- Make sure the descriptor works correctly when subclassing the Rectangle class:
class Square(Rectangle):
def __init__(self, a):
self.a = self.b = a
s = Square(10)
print('Area:', s.area)
print('Perimeter:', s.perimeter)
del s.a
Output:
Set a = 10
Set b = 10
Get a = 10
Get b = 10
Area: 100
Get a = 10
Get b = 10
Perimeter: 40
Delete a = 10
10. Modules and packages
- Create a package named mypackage with modules named generators, iterators, decorators and descriptors
- Put the generators, iterators, decorators and descriptors you wrote in previous labs to respective modules
- Make all modules executable as scripts, e.g.:
python mypackage/generators.py
- Make the entire package runnable as script:
python mypackage
- Create a source distribution of your package suitable for uploading to PyPI
11. Unit testing
- Create unit tests for your package and put them in the mypackage.tests module
- Install the coverage package and generate a coverage report for your tests
- Create a config file for coverage to exclude if __name__ == "__main__": blocks from coverage
- Install the flake8 package and check the code of your package using the flake8 command
- Create a config file for flake8 to allow lines of length up to 120 characters
- Fix all other flake8 warnings
- Bonus: write tests with pytest and run them with pytest-cov
12. NumPy
- Create a random vector of size 10 and sort it
- Create a random vector of size 20 and find the mean value
- Create a 2x2x2 array with random values
- Create a 4x4 matrix with random values ranging from 0 to 9
- Find common values between two arrays
- Find the nearest value from a given value in an array
13. Exploratory data analysis with Pandas
Download the file athlete_events.csv from here. The dataset has the following features:
- ID - Unique number for each athlete
- Name - Athlete's name
- Sex - M or F
- Age - Integer
- Height - In centimeters
- Weight - In kilograms
- Team - Team name
- NOC - National Olympic Committee 3-letter code
- Games - Year and season
- Year - Integer
- Season - Summer or Winter
- City - Host city
- Sport - Sport
- Event - Event
- Medal - Gold, Silver, Bronze, or NA
Answer the following questions about this dataset
- How old were the youngest male and female participants of the 1992 Olympics?
- What are the mean and standard deviation of height for female tennis players who participated in the 2000 Olympics?
- Find a sportsman who participated in the 2006 Olympics, with the highest weight among other participants of the same Olympics. What sport did he or she do?
- How many times did John Aalberg participate in the Olympics held in different years?
- How many gold medals in tennis did sportspeople from the Switzerland team win at the 2008 Olympics? Count every medal from every sportsperson.
- Is it true that Spain won fewer medals than Italy at the 2016 Olympics?
- Is it true that there were Summer Olympics held in Atlanta? Is it true that there were Winter Olympics held in Squaw Valley?
- What is the absolute difference between the number of unique sports at the 1986 Olympics and 2002 Olympics?
14. Django (optional)
- Create a minimal Django project for an arbitrary purpose
- Create at least 4 models
- Add migrations
- Create usable admin pages.
- Create the requirements.txt file
- Configure flake8 by creating a configuration file for it and fix all warnings
|