From 226d721608ebd62bc704e5c5fc9266f83914418c Mon Sep 17 00:00:00 2001 From: 100gle <569590461@qq.com> Date: Thu, 20 Oct 2022 08:57:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=8A=80=E8=83=BD?= =?UTF-8?q?=E6=89=A9=E5=B1=95=20N3=20=E4=B8=80=E7=AB=A0=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E7=A4=BA=E4=BE=8B=E6=BA=90=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/newsletter/N3/collections.ipynb | 330 +++++++++++++++++ code/newsletter/N3/functools.ipynb | 409 ++++++++++++++++++++++ code/newsletter/N3/futures_example.py | 53 +++ code/newsletter/N3/futures_map_example.py | 19 + code/newsletter/N3/itertools.ipynb | 304 ++++++++++++++++ code/newsletter/N3/pathlib.ipynb | 169 +++++++++ code/newsletter/N3/threading_example.py | 58 +++ 7 files changed, 1342 insertions(+) create mode 100644 code/newsletter/N3/collections.ipynb create mode 100644 code/newsletter/N3/functools.ipynb create mode 100644 code/newsletter/N3/futures_example.py create mode 100644 code/newsletter/N3/futures_map_example.py create mode 100644 code/newsletter/N3/itertools.ipynb create mode 100644 code/newsletter/N3/pathlib.ipynb create mode 100644 code/newsletter/N3/threading_example.py diff --git a/code/newsletter/N3/collections.ipynb b/code/newsletter/N3/collections.ipynb new file mode 100644 index 0000000..fd0c4f5 --- /dev/null +++ b/code/newsletter/N3/collections.ipynb @@ -0,0 +1,330 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# namedtuple" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## namedtuple 使用示例" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Point 1: Point(x=1, y=1), Point 2: Point(x=2, y=3)\n" + ] + } + ], + "source": [ + "from collections import namedtuple\n", + "\n", + "Point = namedtuple(\"Point\", [\"x\", \"y\"])\n", + "p1 = Point(x=1, y=1)\n", + "p2 = Point(2, 3)\n", + "print(f\"Point 1: {p1}, Point 2: {p2}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'x': 3, 'y': 4}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "p3 = Point(p1.x + p2.x, p1.y + p2.y)\n", + "p3._asdict()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 自定义 `Point` 类" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Point:\n", + " def __init__(self, x: int, y: int):\n", + " self.x = x\n", + " self.y = y\n", + "\n", + " def __repr__(self):\n", + " return f\"{self.__class__.__name__}(x={self.x}, y={self.y})\"\n", + "\n", + "\n", + "p = Point(x=3, y=4)\n", + "p\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 使用 `NamedTuple` 类" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Point(x=0, y=0)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from typing import NamedTuple\n", + "\n", + "\n", + "class Point(NamedTuple):\n", + " x: int = 0\n", + " y: int = 0\n", + "\n", + " def __repr__(self):\n", + " return f\"{self.__class__.__name__}(x={self.x}, y={self.y})\"\n", + "\n", + "\n", + "p = Point()\n", + "p" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Counter" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[('is', 10),\n", + " ('better', 8),\n", + " ('than', 8),\n", + " ('to', 5),\n", + " ('the', 5),\n", + " ('of', 3),\n", + " ('Although', 3),\n", + " ('be', 3),\n", + " ('should', 2),\n", + " ('never', 2)]" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from collections import Counter\n", + "from itertools import chain\n", + "\n", + "poem = \"\"\"\n", + "The Zen of Python, by Tim Peters\n", + "\n", + "Beautiful is better than ugly.\n", + "Explicit is better than implicit.\n", + "Simple is better than complex.\n", + "Complex is better than complicated.\n", + "Flat is better than nested.\n", + "Sparse is better than dense.\n", + "Readability counts.\n", + "Special cases aren't special enough to break the rules.\n", + "Although practicality beats purity.\n", + "Errors should never pass silently.\n", + "Unless explicitly silenced.\n", + "In the face of ambiguity, refuse the temptation to guess.\n", + "There should be one-- and preferably only one --obvious way to do it.\n", + "Although that way may not be obvious at first unless you're Dutch.\n", + "Now is better than never.\n", + "Although never is often better than *right* now.\n", + "If the implementation is hard to explain, it's a bad idea.\n", + "If the implementation is easy to explain, it may be a good idea.\n", + "Namespaces are one honking great idea -- let's do more of those!\n", + "\"\"\"\n", + "split = [line.split() for line in poem.splitlines()]\n", + "words = list(chain(*[elem for elem in split if elem]))\n", + "words[1:10]\n", + "\n", + "counter = Counter(words)\n", + "counter.most_common(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# deque " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "deque([])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from collections import deque\n", + "\n", + "queue = deque()\n", + "queue" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "deque(['foo'])" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "queue.append(\"foo\")\n", + "queue" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "deque(['bar', 'bar', 'foo'])" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "queue.appendleft(\"bar\")\n", + "queue" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "queue.extendleft([\"zoo\", \"fuzz\"])\n", + "queue" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "deque(['foo', 'bar', 'baz'])" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "queue.rotate(1)\n", + "queue" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.0 ('pandas-startup')", + "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.9.0" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "13977d4cc82dee5f9d9535ceb495bd0ab12a43c33c664e5f0d53c24cf634b67f" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/code/newsletter/N3/functools.ipynb b/code/newsletter/N3/functools.ipynb new file mode 100644 index 0000000..47b6428 --- /dev/null +++ b/code/newsletter/N3/functools.ipynb @@ -0,0 +1,409 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# reduce" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from functools import reduce\n", + "\n", + "numbers = list(range(1, 6))\n", + "numbers" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "15" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "int(reduce(lambda x, y: x + y, numbers))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "120" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "int(reduce(lambda x, y: x * y, numbers))" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "15" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def accumulate(sequence):\n", + " result = sequence[0]\n", + " for index, _ in enumerate(sequence[1:], start=1):\n", + " right = sequence[index]\n", + " result += right\n", + "\n", + " return result\n", + "\n", + "accumulate(numbers)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "25" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "int(reduce(lambda x, y: x+y, numbers, 10))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# partial" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [], + "source": [ + "from functools import partial\n", + "from math import log\n", + "\n", + "def custom_log(x, base):\n", + " return log(x, base)\n", + "\n", + "log2 = partial(custom_log, base=2)\n", + "log10 = partial(custom_log, base=10)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2.0" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "log2(4)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2.0" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "log10(100)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2.0" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "log2(9, base=3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# wraps" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### without wraps function" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Monitoring request...\n", + "request https://sspai.com using GET method...\n" + ] + } + ], + "source": [ + "def monitor(func):\n", + " print(f\"Monitoring {func.__name__}...\") \n", + " def wrapper(*args, **kwargs):\n", + " return func(*args, **kwargs)\n", + " return wrapper\n", + "\n", + "@monitor\n", + "def request(url, method=\"GET\"):\n", + " \"\"\"Request from target url\n", + " :param url: string, the target url.\n", + " :param method: string, the request method, default is GET.\n", + " \"\"\"\n", + " print(f\"request {url} using {method} method...\")\n", + "\n", + "request(\"https://sspai.com\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + ".wrapper(*args, **kwargs)>" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "request" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "wrapper\n", + "None\n" + ] + } + ], + "source": [ + "print(request.__name__)\n", + "print(request.__doc__)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### with wraps function" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Monitoring request...\n", + "request https://sspai.com using GET method...\n" + ] + } + ], + "source": [ + "from functools import wraps\n", + "\n", + "def monitor(func):\n", + " print(f\"Monitoring {func.__name__}...\")\n", + "\n", + " @wraps(func)\n", + " def wrapper(*args, **kwargs):\n", + " return func(*args, **kwargs)\n", + " return wrapper\n", + "\n", + "@monitor\n", + "def request(url, method=\"GET\"):\n", + " \"\"\"Request from target url\n", + " :param url: string, the target url.\n", + " :param method: string, the request method, default is GET.\n", + " \"\"\"\n", + " print(f\"request {url} using {method} method...\")\n", + "\n", + "request(\"https://sspai.com\")" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "request" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "request\n", + "Request from target url\n", + " :param url: string, the target url.\n", + " :param method: string, the request method, default is GET.\n", + " \n" + ] + } + ], + "source": [ + "print(request.__name__)\n", + "print(request.__doc__)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.0 ('pandas-startup')", + "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.9.0" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "13977d4cc82dee5f9d9535ceb495bd0ab12a43c33c664e5f0d53c24cf634b67f" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/code/newsletter/N3/futures_example.py b/code/newsletter/N3/futures_example.py new file mode 100644 index 0000000..e7f640d --- /dev/null +++ b/code/newsletter/N3/futures_example.py @@ -0,0 +1,53 @@ +import time +from concurrent.futures import ThreadPoolExecutor + +import requests + + +def timer(func): + def wrapper(*args, **kwargs): + start = time.perf_counter() + func(*args, **kwargs) + usage = time.perf_counter() - start + return usage + + return wrapper + + +def fetch(url, method="GET"): + resp = requests.request(method=method, url=url) + resp.raise_for_status() + data = resp.json() + return data + + +@timer +def hacking(urls, methods, workers=2): + with ThreadPoolExecutor(max_workers=workers) as pool: + futures = [ + pool.submit(fetch, url=url, method=method) + for url, method in zip(urls, methods) + ] + _ = [future.result() for future in futures] + + +@timer +def normal(urls, methods): + for url, method in zip(urls, methods): + fetch(url=url, method=method) + + +def main(): + base = "https://httpbin.org/" + methods = ["GET", "POST", "PATCH", "DELETE"] + urls = [base + method.lower() for method in methods] + + normal_usage = normal(urls, methods) + hacking_usage = hacking(urls, methods) + + print(f"normal usage: {normal_usage: .2f}s") + print(f"hacking usage: {hacking_usage: .2f}s") + + +if __name__ == '__main__': + main() diff --git a/code/newsletter/N3/futures_map_example.py b/code/newsletter/N3/futures_map_example.py new file mode 100644 index 0000000..2ff3302 --- /dev/null +++ b/code/newsletter/N3/futures_map_example.py @@ -0,0 +1,19 @@ +from concurrent.futures import ProcessPoolExecutor + + +def fib(n): + if n <= 1: + return n + return fib(n - 1) + fib(n - 2) + + +def main(): + n = [1, 3, 5, 10, 20] + + with ProcessPoolExecutor(max_workers=4) as pool: + result = pool.map(fib, n) + print(list(result)) + + +if __name__ == '__main__': + main() diff --git a/code/newsletter/N3/itertools.ipynb b/code/newsletter/N3/itertools.ipynb new file mode 100644 index 0000000..ff5cfbf --- /dev/null +++ b/code/newsletter/N3/itertools.ipynb @@ -0,0 +1,304 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# chain" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[['The', 'Zen', 'of', 'Python,', 'by', 'Tim', 'Peters'],\n", + " ['Beautiful', 'is', 'better', 'than', 'ugly.'],\n", + " ['Explicit', 'is', 'better', 'than', 'implicit.'],\n", + " ['Simple', 'is', 'better', 'than', 'complex.'],\n", + " ['Complex', 'is', 'better', 'than', 'complicated.'],\n", + " ['Flat', 'is', 'better', 'than', 'nested.'],\n", + " ['Sparse', 'is', 'better', 'than', 'dense.'],\n", + " ['Readability', 'counts.'],\n", + " ['Special',\n", + " 'cases',\n", + " \"aren't\",\n", + " 'special',\n", + " 'enough',\n", + " 'to',\n", + " 'break',\n", + " 'the',\n", + " 'rules.']]" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from itertools import chain\n", + "poem = \"\"\"\n", + "The Zen of Python, by Tim Peters\n", + "Beautiful is better than ugly.\n", + "Explicit is better than implicit.\n", + "Simple is better than complex.\n", + "Complex is better than complicated.\n", + "Flat is better than nested.\n", + "Sparse is better than dense.\n", + "Readability counts.\n", + "Special cases aren't special enough to break the rules.\n", + "Although practicality beats purity.\n", + "Errors should never pass silently.\n", + "Unless explicitly silenced.\n", + "In the face of ambiguity, refuse the temptation to guess.\n", + "There should be one-- and preferably only one --obvious way to do it.\n", + "Although that way may not be obvious at first unless you're Dutch.\n", + "Now is better than never.\n", + "Although never is often better than *right* now.\n", + "If the implementation is hard to explain, it's a bad idea.\n", + "If the implementation is easy to explain, it may be a good idea.\n", + "Namespaces are one honking great idea -- let's do more of those!\n", + "\"\"\"\n", + "\n", + "split = [line.split() for line in poem.splitlines()]\n", + "split[1:10]" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Zen', 'of', 'Python,', 'by', 'Tim', 'Peters', 'Beautiful', 'is', 'better']" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "words = list(chain(*[elem for elem in split if elem]))\n", + "words[1:10]" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['Zen', 'of', 'Python,', 'by', 'Tim', 'Peters', 'Beautiful', 'is', 'better']" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "words = list(chain.from_iterable(split))\n", + "words[1:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# permutations、product" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1320" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from itertools import permutations\n", + "uppers = \"ABCD\"\n", + "lowers = uppers.lower()\n", + "numbers = \"1234\"\n", + "elements = [*uppers, *lowers, *numbers]\n", + "\n", + "pairs = list(permutations(elements, 3))\n", + "len(pairs)" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[('A', 'B', 'D'),\n", + " ('A', 'B', 'a'),\n", + " ('A', 'B', 'b'),\n", + " ('A', 'B', 'c'),\n", + " ('A', 'B', 'd'),\n", + " ('A', 'B', '1'),\n", + " ('A', 'B', '2'),\n", + " ('A', 'B', '3'),\n", + " ('A', 'B', '4')]" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pairs[1:10]" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[('A', 'b'),\n", + " ('A', 'c'),\n", + " ('A', 'd'),\n", + " ('B', 'a'),\n", + " ('B', 'b'),\n", + " ('B', 'c'),\n", + " ('B', 'd'),\n", + " ('C', 'a'),\n", + " ('C', 'b')]" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from itertools import product\n", + "\n", + "pairs = list(product(uppers, lowers))\n", + "pairs[1:10]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## repeat、cycle" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['ABCD', 'ABCD', 'ABCD']" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from itertools import repeat\n", + "uppers = \"ABCD\"\n", + "\n", + "more = list(repeat(uppers, times=3))\n", + "more" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['A', 'B', 'C', 'D', 'A', 'B']\n" + ] + } + ], + "source": [ + "from itertools import cycle\n", + "\n", + "uppers = \"ABCD\"\n", + "more = cycle(uppers)\n", + "counter = 0\n", + "result = []\n", + "\n", + "for letter in more:\n", + " if counter <= 5:\n", + " result.append(letter)\n", + " counter += 1\n", + " continue\n", + " break\n", + "\n", + "print(result)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.0 ('pandas-startup')", + "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.9.0" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "13977d4cc82dee5f9d9535ceb495bd0ab12a43c33c664e5f0d53c24cf634b67f" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/code/newsletter/N3/pathlib.ipynb b/code/newsletter/N3/pathlib.ipynb new file mode 100644 index 0000000..e2a132b --- /dev/null +++ b/code/newsletter/N3/pathlib.ipynb @@ -0,0 +1,169 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pathlib\n", + "path = pathlib.Path(\"~/Desktop/faker.py\").expanduser()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "PosixPath('/Users/Bobot/Desktop')" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "path.parent" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'.py'" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "path.suffix" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'faker.py'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "path.name" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# os version\n", + "\n", + "# import os\n", + "\n", + "# ROOT = os.path.expanduser(\"~/Desktop/test\")\n", + "# file = os.path.join(str(ROOT), \"prime.txt\")\n", + "\n", + "# if not os.path.exists(file):\n", + "# os.mkdir(ROOT)\n", + "# with open(file, mode=\"w+\", encoding=\"utf-8\") as f:\n", + "# f.write(\"Hello, World!\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "import pathlib\n", + "\n", + "file = pathlib.Path(\"~/Desktop/test\").expanduser().joinpath(\"prime.txt\")\n", + "if not file.exists():\n", + " file.parent.mkdir(parents=True, exist_ok=True)\n", + " file.write_text(\"Hello, World!\", encoding=\"utf-8\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "PosixPath('/Users/Bobot/Desktop/test/echo.md')" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "file = (\n", + " pathlib.Path(\"~/Desktop/test\")\n", + " .expanduser()\n", + " .joinpath(\"prime.txt\")\n", + " .with_stem(\"echo\")\n", + " .with_suffix(\".md\")\n", + ")\n", + "\n", + "file\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.0 ('pandas-startup')", + "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.9.0" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "13977d4cc82dee5f9d9535ceb495bd0ab12a43c33c664e5f0d53c24cf634b67f" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/code/newsletter/N3/threading_example.py b/code/newsletter/N3/threading_example.py new file mode 100644 index 0000000..774a5b3 --- /dev/null +++ b/code/newsletter/N3/threading_example.py @@ -0,0 +1,58 @@ +import threading +import time + +import requests + + +def timer(func): + def wrapper(*args, **kwargs): + start = time.perf_counter() + func(*args, **kwargs) + usage = time.perf_counter() - start + return usage + + return wrapper + + +def fetch(url, method="GET"): + resp = requests.request(method=method, url=url) + resp.raise_for_status() + data = resp.json() + return data + + +@timer +def hacking(urls, methods): + threads = [] + for url, method in zip(urls, methods): + thread = threading.Thread( + target=fetch, + kwargs=dict(url=url, method=method), + ) + threads.append(thread) + thread.start() + + for thread in threads: + thread.join() + + +@timer +def normal(urls, methods): + for url, method in zip(urls, methods): + fetch(url=url, method=method) + + +def main(): + base = "https://httpbin.org/" + methods = ["GET", "POST", "PATCH", "DELETE"] + urls = [base + method.lower() for method in methods] + + normal_usage = normal(urls, methods) + hacking_usage = hacking(urls, methods) + + print(f"normal usage: {normal_usage: .2f}s") + print(f"hacking usage: {hacking_usage: .2f}s") + + +if __name__ == '__main__': + main()