Skip to content

Instantly share code, notes, and snippets.

@jonwhittlestone
Last active July 31, 2023 12:43
Show Gist options
  • Save jonwhittlestone/8d682d42fc5bc6ca66a7413eb0a713d6 to your computer and use it in GitHub Desktop.
Save jonwhittlestone/8d682d42fc5bc6ca66a7413eb0a713d6 to your computer and use it in GitHub Desktop.
real-python-interesting-resources.md
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Path: Python Interviews\n",
"\n",
"Ace your Python Interview\n",
"\n",
"- https://realpython.com/learning-paths/python-interview/\n",
"- Videos to the interview questions\n",
" - https://www.dropbox.com/scl/fo/cf23zb6iasqifwod2rbuo/h?rlkey=obsfqzjnyxavtj5ijpwvwoj0a&dl=0"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[32, 1, 3, 6, 31]\n"
]
}
],
"source": [
"# from: https://stackoverflow.com/a/694180\n",
"# Python snippets I like:\n",
"def pred(x):\n",
" return x % 1 == 0\n",
"\n",
"if any(pred(x) for x in [0, 30, -3, 59]):\n",
" ...\n",
"\n",
"# instead of:\n",
"\n",
"found = False\n",
"for x in [0, 30, -3, 59]:\n",
" if pred(x):\n",
" found = True\n",
"if found:\n",
" ...\n",
"# similar is `any()` where return True if any of the values are True\n",
"\n",
"# or, `all()` where return True when *all* of the values are True\n",
"\n",
"\n",
"# then there's removing duplicates from a list\n",
"de_duped = list(set([32, 32, 31, 31, 1, 3, 6,6]))\n",
"print(de_duped)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Tips & Best Practices\n",
"https://realpython.com/courses/python-coding-interviews-tips-best-practices/\n",
"\n",
"How to stand out in a Python coding interview\n",
"### Video chapters\n",
"\n",
"#### 01. Built ins\n",
"\n",
"like enumerate and list comprehensions\n",
"\n",
"print vs. breakpoint\n",
"\n",
"`sorted()`\n",
"\n",
"#### 02. Leveraging data structures (Built-in and std library)\n",
"\n",
"sets\n",
"\n",
"dictionaries and `defaultdict()`\n",
"\n",
"`collections.Counter`\n",
"\n",
"`collections.deque`\n",
"\n",
"`collections.NamedTuple`\n",
"\n",
"#### 03. Python built-in library\n",
"\n",
"`string` module\n",
"\n",
"`itertools` module\n",
"\n",
"`functools` module\n",
"\n",
"`doctest` and `assert` in testing\n",
"\n",
"#### 04. Real-world interview questions\n",
"\n",
"easy, medium and hard questions\n",
"\n",
"`PriorityQueue` data structure to get the minimum value in logarythmic time\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Part 1: Introduction & Pythonic Built-Ins"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### `range()` vs. `enumerate()` in fizzbuzz\n",
"\n",
"Can run with `doctest` to see if output matches what's in the docstring"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TestResults(failed=0, attempted=18)"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def fizz_buzz(numbers):\n",
" '''\n",
" Given a list of integers\n",
" 1. Replace all integers that are evenly divisible by 3 with 'fizz'\n",
" 2. Replace all integers divisible by 5 with 'buzz'\n",
" 3. Replace all integers divisible by 3 and 5 with 'fizzbuzz'\n",
" >>> numbers = [45, 22, 14, 65, 97, 72]\n",
" >>> fizz_buzz(numbers)\n",
" >>> numbers\n",
" ['fizzbuzz', 22, 14, 'buzz', 97, 'fizz']\n",
" '''\n",
" for i, num in enumerate(numbers):\n",
" if num % 5 == 0 and num % 3 == 0:\n",
" numbers[i] = \"fizzbuzz\"\n",
" elif num % 3 == 0:\n",
" numbers[i] = \"fizz\"\n",
" elif num % 5 == 0:\n",
" numbers[i] = \"buzz\"\n",
" \n",
"# fizz_buzz([45, 22, 14, 65, 97, 72])\n",
"numbers = fizz_buzz([45, 22, 14, 65, 97, 72])\n",
"numbers\n",
"\n",
"import doctest\n",
"doctest.testmod()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 01. List Comprehensions and Built-in functions on lists"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 4, 25, 16]"
]
},
"execution_count": 50,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"lst = [1, 2, -5, 4]\n",
"\n",
"def square(x):\n",
" return x*x\n",
"\n",
"# apply the square function to each element in a list\n",
"list(map(square, lst)) # can also do `[square(x) for x in lst]`"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, -5]"
]
},
"execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# filter the elements from a list that are odd\n",
"\n",
"def is_odd(x):\n",
" return x % 2 != 0\n",
"\n",
"list(filter(is_odd, lst)) # can also do `[x for x in lst if is_odd(x)]`"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[[0, 0, 0], [0, 0, 0]]"
]
},
"execution_count": 52,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Many questions involve some sort of grid or matrix, like a 2x3 grid\n",
"grid = [\n",
" [0, 0, 0],\n",
" [0, 0, 0],\n",
"]\n",
"\n",
"# how to build dynamically..\n",
"num_rows = 2\n",
"num_cols = 3\n",
"grid = []\n",
"for _ in range(num_rows):\n",
" curr_row = []\n",
" for _ in range(num_cols):\n",
" curr_row.append(0)\n",
" grid.append(curr_row)\n",
"grid"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[[0, 0, 0], [0, 0, 0]]"
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# or with list comp\n",
"grid = [[0 for _ in range(num_cols)] for _ in range(num_rows)]\n",
"grid"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4\n"
]
},
{
"data": {
"text/plain": [
"-5"
]
},
"execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# using max with a lambda\n",
"\n",
"print(max(lst))\n",
"\n",
"max(lst, key=lambda x: x*x)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"#### Different ways to debug in Python (`print` and `breakpoint`)"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4\n"
]
}
],
"source": [
"def max(lst):\n",
" max_num = 0\n",
" for num in lst:\n",
" # print(num, max_ num)\n",
" breakpoint() \n",
" if num > max_num:\n",
" max_num = num\n",
" return max_num\n",
"print(max([1, -2, 4]))"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0\n"
]
}
],
"source": [
"print(max([-1,-2,-4]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 01: F-Strings"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 01.06 Sorting"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['cat', 'cat', 'dog', 'dog', 'fish']"
]
},
"execution_count": 57,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"animals = ['cat', 'dog', 'fish', 'cat', 'dog']\n",
"sorted(animals)"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['fish', 'dog', 'dog', 'cat', 'cat']"
]
},
"execution_count": 58,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sorted(animals, reverse=True)"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'type': 'cat', 'name': 'Stephanie', 'age': 8}"
]
},
"execution_count": 59,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"animals = [\n",
" {'type': 'cat', 'name': 'Stephanie', 'age': 8},\n",
" {'type': 'dog', 'name': 'Devon', 'age': 3},\n",
" {'type': 'fish', 'name': 'Frank', 'age': 5},\n",
"]\n",
"sorted(animals, key=lambda animal: animal['age'], reverse=True)[0] # Get the oldest animal"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Section Two: Leveraging Data Structures (Built-in and Standard Library)\n",
"\n",
"#### 02.01 Sets"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TestResults(failed=0, attempted=20)"
]
},
"execution_count": 60,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def count_unique(s):\n",
" '''\n",
" Given a string of characters, return the number of unique characters \n",
" >>> count_unique('aabb')\n",
" 2\n",
" >>> count_unique('abcdef')\n",
" 6\n",
" '''\n",
" # BigO analysis\n",
" seen_c = [] # O(1) - constant time\n",
" for c in s: # O(n) - \"O of n time\" where n is the length of s: linear time\n",
" if c not in seen_c: # O(n) - where n is the length of seen_c: linear time\n",
" seen_c.append(c) # O(1) - constant time\n",
" return len(seen_c) # 0(n^2) - something that takens \"O of n time\", n-times, is \"Of of n times squared\"\n",
"\n",
"import doctest\n",
"doctest.testmod()"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TestResults(failed=0, attempted=20)"
]
},
"execution_count": 61,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# The above is O(n^2) time complexity, which is not great.\n",
"# We can do better with a set, which is a data structure that only stores unique values\n",
"def count_unique(s):\n",
" '''\n",
" Given a string of characters, return the number of unique characters \n",
" >>> count_unique('aabb')\n",
" 2\n",
" >>> count_unique('abcdef')\n",
" 6\n",
" '''\n",
"\n",
" # BigO analysis\n",
" seen_c = set() # O(1) - constant time \n",
" for c in s: # O(n) - \"O of n time\" where n is the length of s: linear time\n",
" if c not in seen_c: # 0(1) \n",
" seen_c.add(c) # 0(1) - \"This changed because to check membership of a set will be similar to dict because it uses a hash table\"\n",
" return len(seen_c) # 0(n) - 'The run time will always be 0 of n'\n",
"\n",
"import doctest\n",
"doctest.testmod()"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TestResults(failed=0, attempted=20)"
]
},
"execution_count": 62,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Set comprehensions will remove duplicates\n",
"\n",
"def count_unique(s):\n",
" '''\n",
" Given a string of characters, return the number of unique characters \n",
" >>> count_unique('aabb')\n",
" 2\n",
" >>> count_unique('abcdef')\n",
" 6\n",
" '''\n",
" # set comprehension\n",
" # return len({c for c in s})\n",
" \n",
" # .. or set takes an iterable\n",
" return len(set(s)) # 0(n)\n",
"\n",
"\n",
"import doctest\n",
"doctest.testmod()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 02.02 Generators\n",
"\n",
"Iterate over a sequence of values that are lazily evaluated (only evaluate values when you need them)"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<generator object <genexpr> at 0x7fb67c347e00>"
]
},
"execution_count": 63,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"g = (i for i in range(6))\n",
"\n",
"g"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 64,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"next(g)"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"next(g)"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"500500"
]
},
"execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sum([i for i in range(1,1001)])"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"500500"
]
},
"execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# the same thing with a generator..\n",
"\n",
"sum((i for i in range(1,1001)))\n"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"8856"
]
},
"execution_count": 68,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Why use generators? Memory consumption.\n",
"lst = [i for i in range(1, 1001)]\n",
"import sys\n",
"sys.getsizeof(lst) "
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"200"
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"gen = (i for i in range(1, 1001))\n",
"sys.getsizeof(gen)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"8000 bytes versus 200 bytes.\n",
"\n",
"This means, in an interview, if you're looping through lots of values, USE A GENERATOR. \n",
"\n",
"Or, if you don't need to evaluate values, all at once.\n",
"\n",
"For example:\n",
"\n",
"```python\n",
"g = (slow_func(i) for i in range(0,1001)) # only eval `slow_func` when you need to\n",
"```\n",
"\n",
"##### Generator Function\n",
"\n",
"A function when called, returns a generator\n",
"\n",
"Any function can be a generator function if it contains the word `yield`\n",
"\n",
"When you call `next()` on this generator, it will resume where it left off\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [],
"source": [
"def some_func():\n",
" yield 1\n",
" yield 2\n",
" yield 3\n",
"\n",
"f = some_func()"
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 71,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"next(f)"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 72,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"next(f)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 02.03 Dictionaries and `collections.defaultdict`\n",
"\n",
"```python\n",
"student_grades = {\n",
" \"Jack\": [],\n",
" \"Jill\": []\n",
"}\n",
"\n",
"student_grades = defaultdict(list, student_grades)\n",
"```\n",
"\n",
"Useful in an interview instead of writing 5 lines of code. You can access values and it will bind them to the default values."
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {},
"outputs": [],
"source": [
"student_grades = {\n",
" \"Jack\": [85, 90],\n",
" \"Jill\": [80, 95],\n",
"}\n",
"\n",
"def get_grades_naive(name):\n",
" if name in student_grades:\n",
" return student_grades[name]\n",
" else:\n",
" return []\n",
"\n",
"def get_grades_v2(name):\n",
" return student_grades.get(name, [])\n",
"\n",
"get_grades_v2(\"Jack\")\n",
"\n",
"def get_grades_with_assignment(name):\n",
" if name not in student_grades:\n",
" student_grades[name] = []\n",
" return student_grades[name]\n"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{'Jack': [85, 90], 'Jill': [80, 95], 'Joe': []}"
]
},
"execution_count": 74,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"get_grades_with_assignment('Joe')\n",
"\n",
"student_grades"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### `collections.Counter`\n",
"\n",
"Let's try to solve a question, **not** using the counter class\n"
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TestResults(failed=0, attempted=20)"
]
},
"execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from collections import defaultdict\n",
"def top_three_letters(string):\n",
" ''' Given a string, return the three most common letters\n",
" This method should return a list of tuples,\n",
" where the tuple contains the character and the count\n",
"\n",
" >>> top_three_letters(\"abbccc\")\n",
" [('c', 3), ('b', 2), ('a', 1)]\n",
" >>> top_three_letters(\"aabbccd\")\n",
" [('a', 2), ('b', 2), ('c', 2)]\n",
" '''\n",
" LIMIT = 3\n",
" counter = defaultdict(int)\n",
" # loop through the string and store the count\n",
" # for each letter\n",
" for c in string:\n",
" counter[c] += 1\n",
"\n",
" # sort the dictionary by the count to find 3 most frequent\n",
" res = sorted(counter, key=lambda k: counter[k], reverse=True)[:(LIMIT)] # ['b', 'g', 'j', 'a', 'c', 'f']\n",
" #print(res)\n",
"\n",
" # return a formatted list to match the output\n",
" return [(r, counter[r]) for r in res]\n",
"\n",
"\n",
"# print(top_three_letters('abbbcfgggjj'))\n",
"\n",
"import doctest\n",
"doctest.testmod()"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TestResults(failed=0, attempted=20)"
]
},
"execution_count": 76,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# This could be done with a Counter object\n",
"# in one line\n",
"\n",
"from collections import Counter\n",
"\n",
"def top_three_letters(string):\n",
" ''' Given a string, return the three most common letters\n",
" This method should return a list of tuples,\n",
" where the tuple contains the character and the count\n",
"\n",
" >>> top_three_letters(\"abbccc\")\n",
" [('c', 3), ('b', 2), ('a', 1)]\n",
" >>> top_three_letters(\"aabbccd\")\n",
" [('a', 2), ('b', 2), ('c', 2)]\n",
" '''\n",
" return Counter(string).most_common(3)\n",
"\n",
"import doctest\n",
"doctest.testmod()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 02.04 `collections.deque`\n",
"\n",
"`deque` you can `append()` and `pop()` on both sides in constant time.\n",
"\n",
"In the commented out class, bypassing the queue is not constant time, because you have to shift over all the elements in the list\n",
"\n",
"```python\n",
" ...\n",
" def bypass_queue(self, name):\n",
" ...\n",
" self.lst.insert(0, name) # will run O(n) time where n is the length of our list\n",
" print(f\"{name} has bypassed the queue\")\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 77,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TestResults(failed=0, attempted=20)"
]
},
"execution_count": 77,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from collections import deque\n",
"\n",
"# class TicketQueue(object):\n",
"# def __init__(self) -> None:\n",
"# ...\n",
"# self.lst = []\n",
"\n",
"# def add_person(self, name):\n",
"# \"\"\"\n",
"# Add a person to the queue\n",
"\n",
"# >>> queue = TicketQueue()\n",
"# >>> queue.add_person('Jack')\n",
"# Jack has been added to the queue\n",
"# \"\"\"\n",
"# self.lst.append(name)\n",
"# print(f\"{name} has been added to the queue\")\n",
" \n",
"# def service_person(self, name):\n",
"# \"\"\"\n",
"# >>> queue = TicketQueue()\n",
"# >>> queue.add_person('Jack')\n",
"# Jack has been added to the queue\n",
"# >>> queue.service_person('Jack')\n",
"# Jack has been serviced\n",
"# \"\"\"\n",
"# ...\n",
"# name = self.lst.pop(0)\n",
"# print(f\"{name} has been serviced\")\n",
"\n",
"# def bypass_queue(self, name):\n",
"# \"\"\"\n",
"# >>> queue = TicketQueue()\n",
"# >>> queue.add_person('Jack')\n",
"# Jack has been added to the queue\n",
"# >>> queue.bypass_queue('Jill')\n",
"# Jill has bypassed the queue\n",
"# \"\"\"\n",
"# self.lst.insert(0, name)\n",
"# print(f\"{name} has bypassed the queue\")\n",
"\n",
"class TicketQueue(object):\n",
" def __init__(self) -> None:\n",
" ...\n",
" self.deque = deque()\n",
"\n",
" def add_person(self, name):\n",
" \"\"\"\n",
" Add a person to the queue\n",
"\n",
" >>> queue = TicketQueue()\n",
" >>> queue.add_person('Jack')\n",
" Jack has been added to the queue\n",
" \"\"\"\n",
" self.deque.append(name)\n",
" print(f\"{name} has been added to the queue\")\n",
" \n",
" def service_person(self, name):\n",
" \"\"\"\n",
" >>> queue = TicketQueue()\n",
" >>> queue.add_person('Jack')\n",
" Jack has been added to the queue\n",
" >>> queue.service_person('Jack')\n",
" Jack has been serviced\n",
" \"\"\"\n",
" ...\n",
" name = self.deque.popleft()\n",
" print(f\"{name} has been serviced\")\n",
"\n",
" def bypass_queue(self, name):\n",
" \"\"\"\n",
" >>> queue = TicketQueue()\n",
" >>> queue.add_person('Jack')\n",
" Jack has been added to the queue\n",
" >>> queue.bypass_queue('Jill')\n",
" Jill has bypassed the queue\n",
" \"\"\"\n",
" self.deque.appendleft(name)\n",
" print(f\"{name} has bypassed the queue\")\n",
"\n",
"\n",
"import doctest\n",
"doctest.testmod()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 02.05 `collections.NamedTuple`\n",
"\n",
"Making classes immutable."
]
},
{
"cell_type": "code",
"execution_count": 78,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Car(color='Grey', make='VW', model='Tiguan', year=2020)"
]
},
"execution_count": 78,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"class Car:\n",
" def __init__(self, color, make, model, year:int) -> None:\n",
" pass\n",
"\n",
"from collections import namedtuple\n",
"Car = namedtuple('Car', 'color make model year')\n",
"\n",
"our_car = Car(color='Grey', make='VW', model='Tiguan', year=2020)\n",
"our_car"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"... and it can't be mutated"
]
},
{
"cell_type": "code",
"execution_count": 79,
"metadata": {},
"outputs": [
{
"ename": "AttributeError",
"evalue": "can't set attribute",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[79], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m our_car\u001b[39m.\u001b[39;49mcolor \u001b[39m=\u001b[39m \u001b[39m'\u001b[39m\u001b[39mDark Blue\u001b[39m\u001b[39m'\u001b[39m\n",
"\u001b[0;31mAttributeError\u001b[0m: can't set attribute"
]
}
],
"source": [
"our_car.color = 'Dark Blue'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Section Three: Python Built-in Library\n",
"\n",
"#### 03.01 `string` module\n",
"ASCII code for capital A is 65\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"65"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ord('A')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"`%timeit` is a magic function in Jupyter Notebook that times how long it takes to run a line of code"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"13.7 µs ± 238 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n"
]
}
],
"source": [
"%timeit [i for i in range(1000)]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TestResults(failed=0, attempted=2)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import string\n",
"def is_upper(s):\n",
" for letter in s:\n",
" if letter not in string.ascii_uppercase:\n",
" return False\n",
" return True\n",
"\n",
"def is_upper_cleaner(s):\n",
" '''\n",
" Detects if a string is uppercase\n",
" Will return False if it includes a whitespace ' '\n",
"\n",
" >>> is_upper_cleaner('HELLO')\n",
" True\n",
"\n",
" >>> is_upper_cleaner('HELLO WORLD')\n",
" False\n",
" '''\n",
" ...\n",
" uppercase_set = set('ABCDEFGHIJKLMNOPQRSTUVWXYZ')\n",
" # because it's running all on a generator, it will run on each letter\n",
" # and return False if it doesn't find it\n",
" return all(letter in uppercase_set for letter in s)\n",
"\n",
"\n",
"import doctest\n",
"doctest.testmod()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"238 ns ± 3.35 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)\n"
]
}
],
"source": [
"%timeit is_upper('HELLO WORLD')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"... versus ..."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"733 ns ± 1.17 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)\n"
]
}
],
"source": [
"%timeit is_upper_cleaner('HELLO WORLD')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 03.02 `itertools` module\n",
"\n",
"Contains a lot of useful functions that return iterators"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import itertools as it\n",
"\n",
"five_ones = it.repeat(1, times=5) # use `times` param to have a finite generator"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[1, 1, 1, 1, 1]"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(five_ones)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"next(five_ones)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"next(five_ones)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"next(five_ones)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"next(five_ones)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"ename": "StopIteration",
"evalue": "",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mStopIteration\u001b[0m Traceback (most recent call last)",
"Cell \u001b[0;32mIn[22], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[39mnext\u001b[39;49m(five_ones)\n",
"\u001b[0;31mStopIteration\u001b[0m: "
]
}
],
"source": [
"next(five_ones)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[]"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(five_ones)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### How to create a list of 0-10 and square each number\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# instead of using a list comprehension, use the built-in `map` function\n",
"\n",
"nums = map(pow, range(10), it.repeat(2))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"list(nums)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### How to create a list of 0-10 and cube (^3) each number\n",
"\n",
"An easy way to have a stream of numbers that you need to access over and over"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[0, 1, 8, 27, 64, 125, 216, 343, 512, 729]"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"nums = map(pow, range(10), it.repeat(3))\n",
"list(nums)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#itertools.cycle\n",
"#it.cycle # infinite loop\n",
"alternating_ones = it.cycle([1, -1])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"next(alternating_ones) # an infinite sequence"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"An interview question or coding challenge, a question may be to have an alternating sequence of numbers until some condition happens"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[('jon', 'lisa'),\n",
" ('jon', 'joseph'),\n",
" ('jon', 'alice'),\n",
" ('lisa', 'jon'),\n",
" ('lisa', 'joseph'),\n",
" ('lisa', 'alice'),\n",
" ('joseph', 'jon'),\n",
" ('joseph', 'lisa'),\n",
" ('joseph', 'alice'),\n",
" ('alice', 'jon'),\n",
" ('alice', 'lisa'),\n",
" ('alice', 'joseph')]"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# it.permutations\n",
"\n",
"family = ['jon','lisa', 'joseph', 'alice']\n",
"list(it.permutations(family, r=2))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[('jon', 'lisa'),\n",
" ('jon', 'joseph'),\n",
" ('jon', 'alice'),\n",
" ('lisa', 'joseph'),\n",
" ('lisa', 'alice'),\n",
" ('joseph', 'alice')]"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# if you don't care about order\n",
"\n",
"list(it.combinations(family, r=2))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n",
"#### 03.02 `functools` module\n",
"\n",
"##### `reduce` \n",
"\n",
"is a function that reduces an iterable into one value"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"15"
]
},
"execution_count": 49,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from functools import reduce\n",
"\n",
"# the same as ((((1 + 2) + 3)) + 4) + 5\n",
"reduce(lambda x, y: x+y, [1,2,3,4,5])\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"45"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"reduce(lambda x, y: x+y, range(10))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"362880"
]
},
"execution_count": 50,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"\n",
"reduce(lambda x, y: x*y, range(1,10))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Decorators\n",
"\n",
"A decorator is a function that takes a function as an argument and returns a function"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from functools import cached_property\n",
"class Data:\n",
"\n",
" def __init__(self, n):\n",
" self.n = n\n",
" \n",
" @cached_property\n",
" def f(self):\n",
" total = 0\n",
" for i in range(self.n):\n",
" for j in range(self.n):\n",
" for k in range(self.n):\n",
" total += i + j + k\n",
" return total"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"93562500000"
]
},
"execution_count": 65,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"d = Data(500)\n",
"d.f"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"93562500000"
]
},
"execution_count": 67,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"d.f # this is now instant, since the property is cached"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Fibonacci Sequence\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def fib(n):\n",
" '''\n",
" 0, 1, 1, 3, 3, 5...\n",
" '''\n",
" if n <= 1:\n",
" return n\n",
" return fib(n - 1) + fib(n - 2)\n",
" \n",
" "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"5"
]
},
"execution_count": 69,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fib(5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"55"
]
},
"execution_count": 70,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fib(10)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# executing fib(100) will take exponentially longer\n",
"\n",
"# instead, use a cache\n",
"\n",
"from functools import lru_cache\n",
"\n",
"@lru_cache\n",
"def fib(n):\n",
" '''\n",
" 0, 1, 1, 3, 3, 5...\n",
" '''\n",
" if n <= 1:\n",
" return n\n",
" return fib(n - 1) + fib(n - 2)\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"5"
]
},
"execution_count": 73,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fib(5)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"75025"
]
},
"execution_count": 74,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fib(25)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"354224848179261915075"
]
},
"execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fib(100)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### 03.04 `doctest` and `assert` to test your code in an interview\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Run `python3 -m doctest filename.py`\n",
"\n",
"or has we have been doing in the notebook:\n",
"\n",
"```python\n",
"\n",
"import doctest\n",
"doctest.testmod()\n",
"```\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TestResults(failed=0, attempted=2)"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# If you get an interview question saying: write a function that tests for a positive number from user input\n",
"# and how would you test from an exception thrown?\n",
"\n",
"class User:\n",
"\n",
" def __init__(self, starting_balance):\n",
" self.balance = starting_balance\n",
"\n",
" def process_deposit(self, input):\n",
" '''\n",
" Asks for a positive amount to add to balance\n",
" \n",
" >>> User(100).process_deposit(50)\n",
" Thank-you. Your balance is now 150.\n",
"\n",
" >>> User(100).process_deposit(-50)\n",
" Traceback (most recent call last):\n",
" ...\n",
" ValueError: The number must be positive.\n",
" '''\n",
" if input <= 0:\n",
" raise ValueError('The number must be positive.')\n",
" balance = self.balance + input\n",
" print(f'Thank-you. Your balance is now {balance}.')\n",
"\n",
"import doctest\n",
"doctest.testmod()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"An `assert` statement is the opposite.\n",
"\n",
"You can put it in program flow and if the assert is `True`, then program flow continues.\n",
"\n",
"`assert` in your code makes it easy to perform automatic checks as part of the program flow rather than just \"eyeballing it\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Section Four: Real-World Interview Questions\n",
"\n",
"#### 04.01 Easier Interview Question\n"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"TestResults(failed=0, attempted=4)"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from math import floor\n",
"def majority_element_indexes(lst):\n",
" '''\n",
" Return a list of the indexes of the majority element.\n",
" Majority element is the element that appears more than\n",
" floor(n / 2) times.\n",
" If there is no majority element, return []\n",
" >>> majority_element_indexes([1, 1, 2])\n",
" [0, 1]\n",
" >>> majority_element_indexes([1, 2])\n",
" []\n",
" >>> majority_element_indexes([])\n",
" []\n",
" >>> majority_element_indexes([3, 3, 3, 3, 3, 3, 3, 2, 1])\n",
" [0, 1, 2, 3, 4, 5, 6]\n",
" '''\n",
"\n",
" indexes = {}\n",
" for i, num in enumerate(lst):\n",
" if num in indexes.keys():\n",
" indexes[num].append(i)\n",
" else:\n",
" indexes[num] = [i]\n",
"\n",
" try:\n",
" num = list(indexes.keys())[0]\n",
" positions = list(indexes.items())[0][1]\n",
" if len(positions) >= floor(2*num):\n",
" return positions\n",
" else:\n",
" return []\n",
" except IndexError:\n",
" return []\n",
"\n",
"import doctest as dtst\n",
"dtst.testmod()\n",
"# print(majority_element_indexes([3, 3, 3, 3, 3, 3, 3, 2, 1]))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
},
"orig_nbformat": 4
},
"nbformat": 4,
"nbformat_minor": 2
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment