From 674cd5d9b6c94fac777ceb9a5a6644a8202e413c Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Tue, 5 Jun 2018 19:42:10 -0700 Subject: [PATCH 01/15] commit lesson01 --- ...-Programming-A-Simple-Calculator (1).ipynb | 208 ++++++ .../Concept-3-Truth-Table (1).ipynb | 230 ++++++ ...Concept-5-Comprehensions-Example (1).ipynb | 470 +++++++++++++ .../Py220_lesson01/Concept-6-Lambda (1).ipynb | 145 ++++ ...t-7-Iterables-Iter-Iterators-Etc (1).ipynb | 652 ++++++++++++++++++ .../Py220_lesson01/comprehensions_lesson01.py | 41 ++ .../Py220_lesson01/featuresdf.csv | 101 +++ .../tammyd_Py220/Py220_lesson01/generator.py | 88 +++ .../Py220_lesson01/iterator_1_lesson01.py | 91 +++ .../Py220_lesson01/test_generator.py | 62 ++ 10 files changed, 2088 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson01/Concept-1-Procedural-vs-Functional-Programming-A-Simple-Calculator (1).ipynb create mode 100644 Student/tammyd_Py220/Py220_lesson01/Concept-3-Truth-Table (1).ipynb create mode 100644 Student/tammyd_Py220/Py220_lesson01/Concept-5-Comprehensions-Example (1).ipynb create mode 100644 Student/tammyd_Py220/Py220_lesson01/Concept-6-Lambda (1).ipynb create mode 100644 Student/tammyd_Py220/Py220_lesson01/Concept-7-Iterables-Iter-Iterators-Etc (1).ipynb create mode 100644 Student/tammyd_Py220/Py220_lesson01/comprehensions_lesson01.py create mode 100644 Student/tammyd_Py220/Py220_lesson01/featuresdf.csv create mode 100644 Student/tammyd_Py220/Py220_lesson01/generator.py create mode 100644 Student/tammyd_Py220/Py220_lesson01/iterator_1_lesson01.py create mode 100644 Student/tammyd_Py220/Py220_lesson01/test_generator.py diff --git a/Student/tammyd_Py220/Py220_lesson01/Concept-1-Procedural-vs-Functional-Programming-A-Simple-Calculator (1).ipynb b/Student/tammyd_Py220/Py220_lesson01/Concept-1-Procedural-vs-Functional-Programming-A-Simple-Calculator (1).ipynb new file mode 100644 index 0000000..06f365c --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson01/Concept-1-Procedural-vs-Functional-Programming-A-Simple-Calculator (1).ipynb @@ -0,0 +1,208 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pure Function\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "def m(n: int) -> int:\n", + " return 2**n-1\n", + "\n", + "## This result depends only on the parameter, n. \n", + "## There are no changes to global variables and the function doesn't update any mutable data structures." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## A procedural approach!\n", + "\n", + "- Functions generally consist of multiple statements\n", + " - Assignments\n", + " - If-statements\n", + " - While loops\n", + " - Etc." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Welcome to the barely functional calculator!\n", + "Enter an integer: a\n", + "That is not an integer!\n", + "Enter an integer: a\n", + "That is not an integer!\n", + "Enter an integer: a\n", + "That is not an integer!\n", + "Enter an integer: 8\n", + "Enter an operator (+, -, *, or /): &\n", + "That is not an operator!\n", + "Enter an operator (+, -, *, or /): /\n", + "Enter an integer: 9\n", + "The result is: 0.8888888888888888\n" + ] + } + ], + "source": [ + "OPERATORS = '+', '-', '*', '/'\n", + "\n", + "\n", + "def p_main():\n", + " \n", + " \"\"\"The main flow.\"\"\"\n", + "\n", + " print('Welcome to the barely functional calculator!')\n", + " number1 = p_get_number()\n", + " operator = p_get_operator()\n", + " number2 = p_get_number()\n", + " result = p_calculate(number1, operator, number2)\n", + " print('The result is: %s' % result)\n", + "\n", + "\n", + "def p_get_number():\n", + " \n", + " \"\"\"Reads an integer from the standard input and returns it.\n", + " If a non-integer value is entered, a warning is printed,\n", + " and a new value is read.\"\"\"\n", + " \n", + " while True:\n", + " s = input('Enter an integer: ')\n", + " try:\n", + " return int(s)\n", + " except ValueError:\n", + " print('That is not an integer!')\n", + " \n", + "\n", + "def p_get_operator():\n", + " \n", + " \"\"\"Reads an operator from the standard input and returns it.\n", + " Valid operators are: +, -, *, and /. If an invalid operator\n", + " is entered, a warning is printed, and a new value is read.\"\"\" \n", + " \n", + " while True:\n", + " s = input('Enter an operator (+, -, *, or /): ')\n", + " if s in OPERATORS:\n", + " return s\n", + " print('That is not an operator!')\n", + " \n", + " \n", + "def p_calculate(number1, operator, number2):\n", + " \n", + " \"\"\"Performs a calculation with two numbers and an operator,\n", + " and returns the result.\"\"\"\n", + " \n", + " if operator == '+':\n", + " return number1 + number2\n", + " if operator == '-':\n", + " return number1 - number2\n", + " if operator == '*':\n", + " return number1 * number2\n", + " if operator == '/':\n", + " return number1 / number2\n", + " raise Exception('Invalid operator!')\n", + "\n", + " \n", + "p_main()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## A functional approach!\n", + "\n", + "- Functions consist of only one expression\n", + "- How can we validate input? (One of the many things we will learn later!)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Enter and integer: 8\n", + "Enter an operator(+, -, *, /): *\n", + "Enter and integer: 8\n", + "The result is: 64\n" + ] + } + ], + "source": [ + "OPERATORS = '+', '-', '*', '/'\n", + "\n", + "\n", + "def f_get_number():\n", + " return int(input(\"Enter and integer: \"))\n", + "\n", + "\n", + "def f_get_operator():\n", + " return input(\"Enter an operator(+, -, *, /): \")\n", + "\n", + "\n", + "def f_calculate(number1, operator, number2):\n", + " return number1 + number2 if operator == \"+\"\\\n", + " else number1 * number2 if operator == \"*\"\\\n", + " else number1 - number2 if operator == '-'\\\n", + " else number1 / number2 if operator == '/'\\\n", + " else None\n", + "\n", + "def f_main():\n", + " return f_calculate(\n", + " f_get_number(),\n", + " f_get_operator(),\n", + " f_get_number()\n", + " )\n", + " \n", + " \n", + "print('The result is: %s' % f_main())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Student/tammyd_Py220/Py220_lesson01/Concept-3-Truth-Table (1).ipynb b/Student/tammyd_Py220/Py220_lesson01/Concept-3-Truth-Table (1).ipynb new file mode 100644 index 0000000..348f279 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson01/Concept-3-Truth-Table (1).ipynb @@ -0,0 +1,230 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-2" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "-2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "not True" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "not False" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "x=False\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "not x" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "x,y=True, False" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "not (x or y)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "not x or y\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x and y" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "not (x and y)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "not x and y" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Student/tammyd_Py220/Py220_lesson01/Concept-5-Comprehensions-Example (1).ipynb b/Student/tammyd_Py220/Py220_lesson01/Concept-5-Comprehensions-Example (1).ipynb new file mode 100644 index 0000000..6f2e827 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson01/Concept-5-Comprehensions-Example (1).ipynb @@ -0,0 +1,470 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(range(10))" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0\n", + "1\n", + "2\n", + "3\n", + "4\n", + "5\n", + "6\n", + "7\n", + "8\n", + "9\n" + ] + } + ], + "source": [ + "for x in range(10):\n", + " print (x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## MAP" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 4, 9, 16, 25]\n" + ] + } + ], + "source": [ + "items = [1, 2, 3, 4, 5]\n", + "squared = list(map(lambda x: x**2, items))\n", + "print(squared)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Filter\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1]\n" + ] + } + ], + "source": [ + "number_list = range(-10, 10)\n", + "less_than_zero = list(filter(lambda x: x < 0, number_list))\n", + "print(less_than_zero)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[2, 4, 6, 8, 10, 12]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "l = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]\n", + "list(filter(lambda x: not x%2, l))" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3, 4, 5, 6, 7, 8, 9]\n" + ] + } + ], + "source": [ + "number_list = range(-10, 10)\n", + "less_than_zero = list(filter(lambda x: x > 0, number_list))\n", + "print(less_than_zero)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Reduce" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "6\n" + ] + } + ], + "source": [ + "from functools import reduce\n", + "product = reduce((lambda x, y: x * y), [1, 2, 3])\n", + "print(product)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## List Comprehension\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]\n" + ] + } + ], + "source": [ + "multiples = [i for i in range(30) if i % 3 == 0]\n", + "print(multiples)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]\n" + ] + } + ], + "source": [ + "squared = [x**2 for x in range(10)]\n", + "print(squared)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Dict Comprehension\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{5: 'a', 3: 'b', 7: 'A', 6: 'Z'}" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mcase = {'a': 5, 'b': 3, 'A': 7, 'Z': 6}\n", + "{v: k for k, v in mcase.items()}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Set Comprehension" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{0, 1, 4}\n" + ] + } + ], + "source": [ + "squared = {x**2 for x in [0,1,1,2]}\n", + "print(squared)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## In the previous set example, can you explain the output?" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def add_one(x):\n", + " return x + 1" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(map(add_one, range(10)))" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[add_one(x) for x in range(10)]" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "2\n", + "3\n", + "4\n", + "5\n", + "6\n", + "7\n", + "8\n", + "9\n", + "10\n" + ] + } + ], + "source": [ + "for x in range(10):\n", + " print(x + 1)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def filter_odds(x):\n", + " return x % 2" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n", + "3\n", + "5\n", + "7\n", + "9\n" + ] + } + ], + "source": [ + "for x in range(10):\n", + " if filter_odds(x):\n", + " print(x)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 3, 5, 7, 9, 11, 13, 15, 17, 19]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[x for x in range(20) if filter_odds(x)]" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 3, 5, 7, 9]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(filter(filter_odds, range(10)))" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "25" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sum(filter(filter_odds, range(10)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Student/tammyd_Py220/Py220_lesson01/Concept-6-Lambda (1).ipynb b/Student/tammyd_Py220/Py220_lesson01/Concept-6-Lambda (1).ipynb new file mode 100644 index 0000000..1e684b5 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson01/Concept-6-Lambda (1).ipynb @@ -0,0 +1,145 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(x)>" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lambda x: x*2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(x)>" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "lambda x:x*2" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "8" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(lambda x:x*2)(4)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "l = [lambda x, y: x+y]" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "function" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(l[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "129.7748" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "leg = ((27.154167, -80.195663), (29.195168, -81.002998), 129.7748)\n", + "start= lambda x: x[0]\n", + "end = lambda x: x[1]\n", + "dist = lambda x: x[2]\n", + "dist(leg)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Student/tammyd_Py220/Py220_lesson01/Concept-7-Iterables-Iter-Iterators-Etc (1).ipynb b/Student/tammyd_Py220/Py220_lesson01/Concept-7-Iterables-Iter-Iterators-Etc (1).ipynb new file mode 100644 index 0000000..6d272cb --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson01/Concept-7-Iterables-Iter-Iterators-Etc (1).ipynb @@ -0,0 +1,652 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Iter() Operation\n", + "\n", + "Examples of Iter - lists, dictionaries etc ....\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "iter([2,3,4])" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "iter({1:2, 3:4, 5:8})" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "'int' object is not iterable", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m## is this iterable? Try ....\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0miter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m104\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: 'int' object is not iterable" + ] + } + ], + "source": [ + "## is this iterable? Try ....\n", + "\n", + "iter(104)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "##Lets start with user defined String class\n", + "class String(object):\n", + " def __init__(self, val):\n", + " self.val = val\n", + " def __str__(self):\n", + " return self.val" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "st = String('sample string')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Is the above string iterable? lets test it. \n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "ename": "TypeError", + "evalue": "'String' object is not iterable", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0miter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mst\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: 'String' object is not iterable" + ] + } + ], + "source": [ + "iter(st)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Why didn't this work? \n", + "## What's missing?\n", + "\n", + "the magic - an_iterator.__iter__()\n", + "\n", + "## Then, how should we make user defined type iterable? \n", + "This can be done by extending our String class with iter constructor\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "class String(object):\n", + " def __init__(self, val):\n", + " self.val = val\n", + " def __str__(self):\n", + " return self.val\n", + " def __iter__(self):\n", + " print (\"This is __iter__ method of String class\")\n", + " return iter(self.val) #self.val is python string so iter() will return it's iterator" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "st = String('Sample String')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This is __iter__ method of String class\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "iter(st)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# We added an __iter__ method in our String class to make String type an iterable. That means iter(iterable) calls iterable.__iter__() internally.\n", + "\n", + "You could also do this using getitem" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "class String(object):\n", + " def __init__(self, val):\n", + " self.val = val\n", + " def __str__(self):\n", + " return self.val\n", + " def __getitem__(self, index):\n", + " return self.val[index]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "st = String('Sample String')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "iter(st)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## We added __getitem__ method and user defined String type becomes iterable. So iter(iterable) look for iterable.__getitem__() also." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Iterator\n", + "\n", + "1. Iterator object produces values of iterable during iteration. next() or __next__() is applied on iterator for producing next value\n", + "2. It raises StopIteration exception at the end of iteration\n", + "3. iter() function return iterator object for an iterable\n", + "4. If iter() function is applied on iterator object, it returns same object" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "## List as an iterator\n", + "\n", + "a_list = [1,2,3]\n", + "list_iter = a_list.__iter__()\n", + "\n", + "## before python 2.6 I think - list_iter.next()\n", + "list_iter.__next__()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list_iter.__next__()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "## see what happens after 2 more times?\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "3" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list_iter.__next__()" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "ename": "StopIteration", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mStopIteration\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mlist_iter\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__next__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mStopIteration\u001b[0m: " + ] + } + ], + "source": [ + "list_iter.__next__()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## IterTools\n", + "\n", + "\n", + "itertools is a collection of utilities that make it easy to build an iterator that iterates over sequences in various common ways\n", + "\n", + "http://docs.python.org/library/itertools.html\n", + "\n", + "NOTE:\n", + "\n", + "iterators are not only for for\n", + "\n", + "They can be used with anything that expects an iterator:\n", + "\n", + "sum, tuple, sorted, and list\n", + "\n", + "For example.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "import itertools\n", + "\n", + "letters = ['a', 'b', 'c', 'd', 'e', 'f']\n", + "booleans = [1, 0, 1, 0, 0, 1]\n", + "numbers = [23, 20, 44, 32, 7, 12]\n", + "decimals = [0.1, 0.7, 0.4, 0.4, 0.5]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Chain\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['a', 'b', 'c', 'd', 'e', 'f', 1, 0, 1, 0, 0, 1, 0.1, 0.7, 0.4, 0.4, 0.5]\n" + ] + } + ], + "source": [ + "print (list(itertools.chain(letters, booleans, decimals)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## compress()\n", + "\n", + "compress(): given two lists a and b, return the elements of a for which the corresponding elements of b are True.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['a', 'c', 'f']\n" + ] + } + ], + "source": [ + "print (list(itertools.compress(letters, booleans)))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Zip ()\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "xi= [1.47, 1.50, 1.52, 1.55, 1.57, 1.60, 1.63, 1.65]\n", + "yi= [52.21, 53.12, 54.48, 55.84, 57.20, 58.57, 59.93, 61.29]\n", + "zip( xi, yi )\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(1.47, 52.21),\n", + " (1.5, 53.12),\n", + " (1.52, 54.48),\n", + " (1.55, 55.84),\n", + " (1.57, 57.2),\n", + " (1.6, 58.57),\n", + " (1.63, 59.93),\n", + " (1.65, 61.29)]" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(zip( xi, yi ))" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "zip( xi, yi )" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(1.47, 52.21),\n", + " (1.5, 53.12),\n", + " (1.52, 54.48),\n", + " (1.55, 55.84),\n", + " (1.57, 57.2),\n", + " (1.6, 58.57),\n", + " (1.63, 59.93),\n", + " (1.65, 61.29)]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(_)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## We can see that the zip() function with no arguments is a generator function, but there won't be any items. This fits the requirement that the output is iterable.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "zip( (1,2,3) )" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(1,), (2,), (3,)]" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(_)\n", + "\n", + "## In this case, the zip() function emitted one tuple from each input value. This too makes considerable sense." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Student/tammyd_Py220/Py220_lesson01/comprehensions_lesson01.py b/Student/tammyd_Py220/Py220_lesson01/comprehensions_lesson01.py new file mode 100644 index 0000000..4219629 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson01/comprehensions_lesson01.py @@ -0,0 +1,41 @@ +#!usr/local/bin/python3 + +""" + +Py220: Advanced Programming in Python +Lesson 01 Activity and Assignment + +Comprehensions +Use Pandas library to find music that you can dance to and is not too loud. + +""" + +import pandas as pd + +music = pd.read_csv("featuresdf.csv") +# print(music) + +# print("File head: \n", music.head()) +# print("Description: \n", music.describe()) + +# use a comprehension to get danceability scores over 0.8 +#dance_level = sorted([x for x in music.danceability if x > 0.8], reverse= True) +#print(dance_level) + + +# Now, get artists and song names for tracks with danceability scores over 0.8 and loudness scores below -5.0. +# Sort tracks in descending order by danceability +# While you could use Pandas features along the way, you don’t need to. +# Handy library functions include zip() and sorted(). + + +quiet_and_dance = [x for x in zip(music.artists, music.name, music.danceability, music.loudness) + if x[2] > 0.8 and x[3] < -5.0] + +# print(quiet_and_dance) + +top5 = sorted(quiet_and_dance, key=lambda x: x[2], reverse = True) + +print("The top 5 danceable and quiet songs:") +for x in top5[:5]: + print(" -{}, {}".format(x[0], x[1])) \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson01/featuresdf.csv b/Student/tammyd_Py220/Py220_lesson01/featuresdf.csv new file mode 100644 index 0000000..ece51ea --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson01/featuresdf.csv @@ -0,0 +1,101 @@ +id,name,artists,danceability,energy,key,loudness,mode,speechiness,acousticness,instrumentalness,liveness,valence,tempo,duration_ms,time_signature +7qiZfU4dY1lWllzX7mPBI,Shape of You,Ed Sheeran,0.825,0.652,1.0,-3.183,0.0,0.0802,0.581,0.0,0.0931,0.931,95.977,233713.0,4.0 +5CtI0qwDJkDQGwXD1H1cL,Despacito - Remix,Luis Fonsi,0.694,0.815,2.0,-4.328,1.0,0.12,0.229,0.0,0.0924,0.813,88.931,228827.0,4.0 +4aWmUDTfIPGksMNLV2rQP,Despacito (Featuring Daddy Yankee),Luis Fonsi,0.66,0.786,2.0,-4.757,1.0,0.17,0.209,0.0,0.112,0.846,177.833,228200.0,4.0 +6RUKPb4LETWmmr3iAEQkt,Something Just Like This,The Chainsmokers,0.617,0.635,11.0,-6.769,0.0,0.0317,0.0498,1.44e-05,0.164,0.446,103.019,247160.0,4.0 +3DXncPQOG4VBw3QHh3S81,I'm the One,DJ Khaled,0.609,0.668,7.0,-4.284,1.0,0.0367,0.0552,0.0,0.167,0.811,80.924,288600.0,4.0 +7KXjTSCq5nL1LoYtL7XAw,HUMBLE.,Kendrick Lamar,0.904,0.611,1.0,-6.842,0.0,0.0888,0.000259,2.03e-05,0.0976,0.4,150.02,177000.0,4.0 +3eR23VReFzcdmS7TYCrhC,It Ain't Me (with Selena Gomez),Kygo,0.64,0.533,0.0,-6.596,1.0,0.0706,0.119,0.0,0.0864,0.515,99.968,220781.0,4.0 +3B54sVLJ402zGa6Xm4YGN,Unforgettable,French Montana,0.726,0.769,6.0,-5.043,1.0,0.123,0.0293,0.0101,0.104,0.733,97.985,233902.0,4.0 +0KKkJNfGyhkQ5aFogxQAP,That's What I Like,Bruno Mars,0.853,0.56,1.0,-4.961,1.0,0.0406,0.013,0.0,0.0944,0.86,134.066,206693.0,4.0 +3NdDpSvN911VPGivFlV5d,"I Don’t Wanna Live Forever (Fifty Shades Darker) - From ""Fifty Shades Darker (Original Motion Picture Soundtrack)""",ZAYN,0.735,0.451,0.0,-8.374,1.0,0.0585,0.0631,1.3e-05,0.325,0.0862,117.973,245200.0,4.0 +7GX5flRQZVHRAGd6B4TmD,XO TOUR Llif3,Lil Uzi Vert,0.732,0.75,11.0,-6.366,0.0,0.231,0.00264,0.0,0.109,0.401,155.096,182707.0,4.0 +72jbDTw1piOOj770jWNea,Paris,The Chainsmokers,0.653,0.658,2.0,-6.428,1.0,0.0304,0.0215,1.66e-06,0.0939,0.219,99.99,221507.0,4.0 +0dA2Mk56wEzDgegdC6R17,Stay (with Alessia Cara),Zedd,0.679,0.634,5.0,-5.024,0.0,0.0654,0.232,0.0,0.115,0.498,102.013,210091.0,4.0 +4iLqG9SeJSnt0cSPICSjx,Attention,Charlie Puth,0.774,0.626,3.0,-4.432,0.0,0.0432,0.0969,3.12e-05,0.0848,0.777,100.041,211475.0,4.0 +0VgkVdmE4gld66l8iyGjg,Mask Off,Future,0.833,0.434,2.0,-8.795,1.0,0.431,0.0102,0.0219,0.165,0.281,150.062,204600.0,4.0 +3a1lNhkSLSkpJE4MSHpDu,Congratulations,Post Malone,0.627,0.812,6.0,-4.215,1.0,0.0358,0.198,0.0,0.212,0.504,123.071,220293.0,4.0 +6kex4EBAj0WHXDKZMEJaa,Swalla (feat. Nicki Minaj & Ty Dolla $ign),Jason Derulo,0.696,0.817,1.0,-3.862,1.0,0.109,0.075,0.0,0.187,0.782,98.064,216409.0,4.0 +6PCUP3dWmTjcTtXY02oFd,Castle on the Hill,Ed Sheeran,0.461,0.834,2.0,-4.868,1.0,0.0989,0.0232,1.14e-05,0.14,0.471,135.007,261154.0,4.0 +5knuzwU65gJK7IF5yJsua,Rockabye (feat. Sean Paul & Anne-Marie),Clean Bandit,0.72,0.763,9.0,-4.068,0.0,0.0523,0.406,0.0,0.18,0.742,101.965,251088.0,4.0 +0CcQNd8CINkwQfe1RDtGV,Believer,Imagine Dragons,0.779,0.787,10.0,-4.305,0.0,0.108,0.0524,0.0,0.14,0.708,124.982,204347.0,4.0 +2rb5MvYT7ZIxbKW5hfcHx,Mi Gente,J Balvin,0.543,0.677,11.0,-4.915,0.0,0.0993,0.0148,6.21e-06,0.13,0.294,103.809,189440.0,4.0 +0tKcYR2II1VCQWT79i5Nr,Thunder,Imagine Dragons,0.6,0.81,0.0,-4.749,1.0,0.0479,0.00683,0.21,0.155,0.298,167.88,187147.0,4.0 +5uCax9HTNlzGybIStD3vD,Say You Won't Let Go,James Arthur,0.358,0.557,10.0,-7.398,1.0,0.059,0.695,0.0,0.0902,0.494,85.043,211467.0,4.0 +79cuOz3SPQTuFrp8WgftA,There's Nothing Holdin' Me Back,Shawn Mendes,0.857,0.8,2.0,-4.035,1.0,0.0583,0.381,0.0,0.0913,0.966,121.996,199440.0,4.0 +6De0lHrwBfPfrhorm9q1X,Me Rehúso,Danny Ocean,0.744,0.804,1.0,-6.327,1.0,0.0677,0.0231,0.0,0.0494,0.426,104.823,205715.0,4.0 +6D0b04NJIKfEMg040WioJ,Issues,Julia Michaels,0.706,0.427,8.0,-6.864,1.0,0.0879,0.413,0.0,0.0609,0.42,113.804,176320.0,4.0 +0afhq8XCExXpqazXczTSv,Galway Girl,Ed Sheeran,0.624,0.876,9.0,-3.374,1.0,0.1,0.0735,0.0,0.327,0.781,99.943,170827.0,4.0 +3ebXMykcMXOcLeJ9xZ17X,Scared to Be Lonely,Martin Garrix,0.584,0.54,1.0,-7.786,0.0,0.0576,0.0895,0.0,0.261,0.195,137.972,220883.0,4.0 +7BKLCZ1jbUBVqRi2FVlTV,Closer,The Chainsmokers,0.748,0.524,8.0,-5.599,1.0,0.0338,0.414,0.0,0.111,0.661,95.01,244960.0,4.0 +1x5sYLZiu9r5E43kMlt9f,Symphony (feat. Zara Larsson),Clean Bandit,0.707,0.629,0.0,-4.581,0.0,0.0563,0.259,1.6e-05,0.138,0.457,122.863,212459.0,4.0 +5GXAXm5YOmYT0kL5jHvYB,I Feel It Coming,The Weeknd,0.768,0.813,0.0,-5.94,0.0,0.128,0.427,0.0,0.102,0.579,92.994,269187.0,4.0 +5aAx2yezTd8zXrkmtKl66,Starboy,The Weeknd,0.681,0.594,7.0,-7.028,1.0,0.282,0.165,3.49e-06,0.134,0.535,186.054,230453.0,4.0 +1OAh8uOEOvTDqkKFsKksC,Wild Thoughts,DJ Khaled,0.671,0.672,0.0,-3.094,0.0,0.0688,0.0329,0.0,0.118,0.632,97.98,204173.0,4.0 +7tr2za8SQg2CI8EDgrdtN,Slide,Calvin Harris,0.736,0.795,1.0,-3.299,0.0,0.0545,0.498,1.21e-06,0.254,0.511,104.066,230813.0,4.0 +2ekn2ttSfGqwhhate0LSR,New Rules,Dua Lipa,0.771,0.696,9.0,-6.258,0.0,0.0755,0.00256,9.71e-06,0.179,0.656,116.054,208827.0,4.0 +5tz69p7tJuGPeMGwNTxYu,1-800-273-8255,Logic,0.629,0.572,5.0,-7.733,0.0,0.0387,0.57,0.0,0.192,0.386,100.015,250173.0,4.0 +7hDc8b7IXETo14hHIHdnh,Passionfruit,Drake,0.809,0.463,11.0,-11.377,1.0,0.0396,0.256,0.085,0.109,0.364,111.98,298941.0,4.0 +7wGoVu4Dady5GV0Sv4UIs,rockstar,Post Malone,0.577,0.522,5.0,-6.594,0.0,0.0984,0.13,9.03e-05,0.142,0.119,159.772,218320.0,4.0 +6EpRaXYhGOB3fj4V2uDkM,Strip That Down,Liam Payne,0.869,0.485,6.0,-5.595,1.0,0.0545,0.246,0.0,0.0765,0.527,106.028,204502.0,4.0 +3A7qX2QjDlPnazUsRk5y0,2U (feat. Justin Bieber),David Guetta,0.548,0.65,8.0,-5.827,0.0,0.0591,0.219,0.0,0.225,0.557,144.937,194897.0,4.0 +0tgVpDi06FyKpA1z0VMD4,Perfect,Ed Sheeran,0.599,0.448,8.0,-6.312,1.0,0.0232,0.163,0.0,0.106,0.168,95.05,263400.0,3.0 +78rIJddV4X0HkNAInEcYd,Call On Me - Ryan Riback Extended Remix,Starley,0.676,0.843,0.0,-4.068,1.0,0.0367,0.0623,0.000752,0.181,0.718,105.003,222041.0,4.0 +5bcTCxgc7xVfSaMV3RuVk,Feels,Calvin Harris,0.893,0.745,11.0,-3.105,0.0,0.0571,0.0642,0.0,0.0943,0.872,101.018,223413.0,4.0 +0NiXXAI876aGImAd6rTj8,Mama,Jonas Blue,0.746,0.793,11.0,-4.209,0.0,0.0412,0.11,0.0,0.0528,0.557,104.027,181615.0,4.0 +0qYTZCo5Bwh1nsUFGZP3z,Felices los 4,Maluma,0.755,0.789,5.0,-4.502,1.0,0.146,0.231,0.0,0.351,0.737,93.973,229849.0,4.0 +2EEeOnHehOozLq4aS0n6S,iSpy (feat. Lil Yachty),KYLE,0.746,0.653,7.0,-6.745,1.0,0.289,0.378,0.0,0.229,0.672,75.016,253107.0,4.0 +152lZdxL1OR0ZMW6KquMi,Location,Khalid,0.736,0.449,1.0,-11.462,0.0,0.425,0.33,0.000162,0.0898,0.326,80.126,219080.0,4.0 +6mICuAdrwEjh6Y6lroV2K,Chantaje,Shakira,0.852,0.773,8.0,-2.921,0.0,0.0776,0.187,3.05e-05,0.159,0.907,102.034,195840.0,4.0 +4Km5HrUvYTaSUfiSGPJeQ,Bad and Boujee (feat. Lil Uzi Vert),Migos,0.927,0.665,11.0,-5.313,1.0,0.244,0.061,0.0,0.123,0.175,127.076,343150.0,4.0 +0ofbQMrRDsUaVKq2mGLEA,Havana,Camila Cabello,0.768,0.517,7.0,-4.323,0.0,0.0312,0.186,3.8e-05,0.104,0.418,104.992,216897.0,4.0 +6HUnnBwYZqcED1eQztxMB,Solo Dance,Martin Jensen,0.744,0.836,6.0,-2.396,0.0,0.0507,0.0435,0.0,0.194,0.36,114.965,174933.0,4.0 +343YBumqHu19cGoGARUTs,Fake Love,Drake,0.927,0.488,9.0,-9.433,0.0,0.42,0.108,0.0,0.196,0.605,133.987,210937.0,4.0 +4pdPtRcBmOSQDlJ3Fk945,Let Me Love You,DJ Snake,0.476,0.718,8.0,-5.309,1.0,0.0576,0.0784,1.02e-05,0.122,0.142,199.864,205947.0,4.0 +3PEgB3fkiojxms35ntsTg,More Than You Know,Axwell /\ Ingrosso,0.644,0.743,5.0,-5.002,0.0,0.0355,0.034,0.0,0.257,0.544,123.074,203000.0,4.0 +1xznGGDReH1oQq0xzbwXa,One Dance,Drake,0.791,0.619,1.0,-5.886,1.0,0.0532,0.00784,0.00423,0.351,0.371,103.989,173987.0,4.0 +7nKBxz47S9SD79N086fuh,SUBEME LA RADIO,Enrique Iglesias,0.684,0.823,9.0,-3.297,0.0,0.0773,0.0744,0.0,0.111,0.647,91.048,208163.0,4.0 +1NDxZ7cFAo481dtYWdrUn,Pretty Girl - Cheat Codes X CADE Remix,Maggie Lindemann,0.703,0.868,7.0,-4.661,0.0,0.0291,0.15,0.132,0.104,0.733,121.03,193613.0,4.0 +3m660poUr1chesgkkjQM7,Sorry Not Sorry,Demi Lovato,0.704,0.633,11.0,-6.923,0.0,0.241,0.0214,0.0,0.29,0.863,144.021,203760.0,4.0 +3kxfsdsCpFgN412fpnW85,Redbone,Childish Gambino,0.743,0.359,1.0,-10.401,1.0,0.0794,0.199,0.00611,0.137,0.587,160.083,326933.0,4.0 +6b8Be6ljOzmkOmFslEb23,24K Magic,Bruno Mars,0.818,0.803,1.0,-4.282,1.0,0.0797,0.034,0.0,0.153,0.632,106.97,225983.0,4.0 +6HZILIRieu8S0iqY8kIKh,DNA.,Kendrick Lamar,0.637,0.514,1.0,-6.763,1.0,0.365,0.0047,0.0,0.094,0.402,139.931,185947.0,4.0 +3umS4y3uQDkqekNjVpiRU,El Amante,Nicky Jam,0.683,0.691,8.0,-5.535,1.0,0.0432,0.243,0.0,0.14,0.732,179.91,219507.0,4.0 +00lNx0OcTJrS3MKHcB80H,You Don't Know Me - Radio Edit,Jax Jones,0.876,0.669,11.0,-6.054,0.0,0.138,0.163,0.0,0.185,0.682,124.007,213947.0,4.0 +6520aj0B4FSKGVuKNsOCO,Chained To The Rhythm,Katy Perry,0.448,0.801,0.0,-5.363,1.0,0.165,0.0733,0.0,0.146,0.462,189.798,237734.0,4.0 +1louJpMmzEicAn7lzDalP,No Promises (feat. Demi Lovato),Cheat Codes,0.741,0.667,10.0,-5.445,1.0,0.134,0.0575,0.0,0.106,0.595,112.956,223504.0,4.0 +2QbFClFyhMMtiurUjuQlA,Don't Wanna Know (feat. Kendrick Lamar),Maroon 5,0.775,0.617,7.0,-6.166,1.0,0.0701,0.341,0.0,0.0985,0.485,100.048,214265.0,4.0 +5hYTyyh2odQKphUbMqc5g,"How Far I'll Go - From ""Moana""",Alessia Cara,0.314,0.555,9.0,-9.601,1.0,0.37,0.157,0.000108,0.067,0.159,179.666,175517.0,4.0 +38yBBH2jacvDxrznF7h08,Slow Hands,Niall Horan,0.734,0.418,0.0,-6.678,1.0,0.0425,0.0129,0.0,0.0579,0.868,85.909,188174.0,4.0 +2cnKEkpVUSV4wnjQiTWfH,Escápate Conmigo,Wisin,0.747,0.864,8.0,-3.181,0.0,0.0599,0.0245,4.46e-05,0.0853,0.754,92.028,232787.0,4.0 +0SGkqnVQo9KPytSri1H6c,Bounce Back,Big Sean,0.77,0.567,2.0,-5.698,1.0,0.175,0.105,0.0,0.125,0.26,81.477,222360.0,4.0 +5Ohxk2dO5COHF1krpoPig,Sign of the Times,Harry Styles,0.516,0.595,5.0,-4.63,1.0,0.0313,0.0275,0.0,0.109,0.222,119.972,340707.0,4.0 +6gBFPUFcJLzWGx4lenP6h,goosebumps,Travis Scott,0.841,0.728,7.0,-3.37,1.0,0.0484,0.0847,0.0,0.149,0.43,130.049,243837.0,4.0 +5Z3GHaZ6ec9bsiI5Benrb,Young Dumb & Broke,Khalid,0.798,0.539,1.0,-6.351,1.0,0.0421,0.199,1.66e-05,0.165,0.394,136.949,202547.0,4.0 +6jA8HL9i4QGzsj6fjoxp8,There for You,Martin Garrix,0.611,0.644,6.0,-7.607,0.0,0.0553,0.124,0.0,0.124,0.13,105.969,221904.0,4.0 +21TdkDRXuAB3k90ujRU1e,Cold (feat. Future),Maroon 5,0.697,0.716,9.0,-6.288,0.0,0.113,0.118,0.0,0.0424,0.506,99.905,234308.0,4.0 +7vGuf3Y35N4wmASOKLUVV,Silence,Marshmello,0.52,0.761,4.0,-3.093,1.0,0.0853,0.256,4.96e-06,0.17,0.286,141.971,180823.0,4.0 +1mXVgsBdtIVeCLJnSnmtd,Too Good At Goodbyes,Sam Smith,0.698,0.375,5.0,-8.279,1.0,0.0491,0.652,0.0,0.173,0.534,91.92,201000.0,4.0 +3EmmCZoqpWOTY1g2GBwJo,Just Hold On,Steve Aoki,0.647,0.932,11.0,-3.515,1.0,0.0824,0.00383,1.5e-06,0.0574,0.374,114.991,198774.0,4.0 +6uFsE1JgZ20EXyU0JQZbU,Look What You Made Me Do,Taylor Swift,0.773,0.68,9.0,-6.378,0.0,0.141,0.213,1.57e-05,0.122,0.497,128.062,211859.0,4.0 +0CokSRCu5hZgPxcZBaEzV,Glorious (feat. Skylar Grey),Macklemore,0.731,0.794,0.0,-5.126,0.0,0.0522,0.0323,2.59e-05,0.112,0.356,139.994,220454.0,4.0 +6875MeXyCW0wLyT72Eetm,Starving,Hailee Steinfeld,0.721,0.626,4.0,-4.2,1.0,0.123,0.402,0.0,0.102,0.558,99.914,181933.0,4.0 +3AEZUABDXNtecAOSC1qTf,Reggaetón Lento (Bailemos),CNCO,0.761,0.838,4.0,-3.073,0.0,0.0502,0.4,0.0,0.176,0.71,93.974,222560.0,4.0 +3E2Zh20GDCR9B1EYjfXWy,Weak,AJR,0.673,0.637,5.0,-4.518,1.0,0.0429,0.137,0.0,0.184,0.678,123.98,201160.0,4.0 +4pLwZjInHj3SimIyN9SnO,Side To Side,Ariana Grande,0.648,0.738,6.0,-5.883,0.0,0.247,0.0408,0.0,0.292,0.603,159.145,226160.0,4.0 +3QwBODjSEzelZyVjxPOHd,Otra Vez (feat. J Balvin),Zion & Lennox,0.832,0.772,10.0,-5.429,1.0,0.1,0.0559,0.000486,0.44,0.704,96.016,209453.0,4.0 +1wjzFQodRWrPcQ0AnYnvQ,I Like Me Better,Lauv,0.752,0.505,9.0,-7.621,1.0,0.253,0.535,2.55e-06,0.104,0.419,91.97,197437.0,4.0 +04DwTuZ2VBdJCCC5TROn7,In the Name of Love,Martin Garrix,0.49,0.485,4.0,-6.237,0.0,0.0406,0.0592,0.0,0.337,0.196,133.889,195840.0,4.0 +6DNtNfH8hXkqOX1sjqmI7,Cold Water (feat. Justin Bieber & MØ),Major Lazer,0.608,0.798,6.0,-5.092,0.0,0.0432,0.0736,0.0,0.156,0.501,92.943,185352.0,4.0 +1UZOjK1BwmwWU14Erba9C,Malibu,Miley Cyrus,0.573,0.781,8.0,-6.406,1.0,0.0555,0.0767,2.64e-05,0.0813,0.343,139.934,231907.0,4.0 +4b4KcovePX8Ke2cLIQTLM,All Night,The Vamps,0.544,0.809,8.0,-5.098,1.0,0.0363,0.0038,0.0,0.323,0.448,145.017,197640.0,4.0 +1a5Yu5L18qNxVhXx38njO,Hear Me Now,Alok,0.789,0.442,11.0,-7.844,1.0,0.0421,0.586,0.00366,0.0927,0.45,121.971,192846.0,4.0 +4c2W3VKsOFoIg2SFaO6DY,Your Song,Rita Ora,0.855,0.624,1.0,-4.093,1.0,0.0488,0.158,0.0,0.0513,0.962,117.959,180757.0,4.0 +22eADXu8DfOAUEDw4vU8q,Ahora Dice,Chris Jeday,0.708,0.693,6.0,-5.516,1.0,0.138,0.246,0.0,0.129,0.427,143.965,271080.0,4.0 +7nZmah2llfvLDiUjm0kiy,Friends (with BloodPop®),Justin Bieber,0.744,0.739,8.0,-5.35,1.0,0.0387,0.00459,0.0,0.306,0.649,104.99,189467.0,4.0 +2fQrGHiQOvpL9UgPvtYy6,Bank Account,21 Savage,0.884,0.346,8.0,-8.228,0.0,0.351,0.0151,7.04e-06,0.0871,0.376,75.016,220307.0,4.0 +1PSBzsahR2AKwLJgx8ehB,Bad Things (with Camila Cabello),Machine Gun Kelly,0.675,0.69,2.0,-4.761,1.0,0.132,0.21,0.0,0.287,0.272,137.817,239293.0,4.0 +0QsvXIfqM0zZoerQfsI9l,Don't Let Me Down,The Chainsmokers,0.542,0.859,11.0,-5.651,1.0,0.197,0.16,0.00466,0.137,0.403,159.797,208053.0,4.0 +7mldq42yDuxiUNn08nvzH,Body Like A Back Road,Sam Hunt,0.731,0.469,5.0,-7.226,1.0,0.0326,0.463,1.04e-06,0.103,0.631,98.963,165387.0,4.0 +7i2DJ88J7jQ8K7zqFX2fW,Now Or Never,Halsey,0.658,0.588,6.0,-4.902,0.0,0.0367,0.105,1.28e-06,0.125,0.434,110.075,214802.0,4.0 +1j4kHkkpqZRBwE0A4CN4Y,Dusk Till Dawn - Radio Edit,ZAYN,0.258,0.437,11.0,-6.593,0.0,0.039,0.101,1.27e-06,0.106,0.0967,180.043,239000.0,4.0 diff --git a/Student/tammyd_Py220/Py220_lesson01/generator.py b/Student/tammyd_Py220/Py220_lesson01/generator.py new file mode 100644 index 0000000..8daf86e --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson01/generator.py @@ -0,0 +1,88 @@ +#!/usr/local/bin/python3 + +""" +Py220: Advanced Python +Lesson 01 + +Generators +""" + + +# Write a few generators: +# generator format: +# def a_generator_function(params): +# some_stuff +# yield something + + +# Sum of integers +def intsum(x=0, sum=0): + while True: + sum += x + yield sum + x += 1 + +sum_int = intsum() +print(next(sum_int)) + + + + +# Doubler +def doubler(x=1): + while True: + yield x + x = x*2 + +sum_doubler = doubler() +print(next(sum_doubler)) + + + + +# Fibonacci sequence +def fib(a=1, b=1): + while True: + yield a + a, b = b, a+b + +fib_num = fib() +print(next(fib_num)) + +print() + + + +# # Prime numbers +def prime(x=2): + while True: + if not [val for val in range(2, x) if x % val == 0]: + yield x + x += 1 + +# My incorrect try. Yielding all odds. How can I edit to yield just primes? + +# def prime(x=1): +# if x == 2: +# yield x +# while True: +# if x % 2 != 0: +# yield x +# x += 1 +# else: +# x += 1 + +prime_num = prime() +print(next(prime_num)) +print(next(prime_num)) +print(next(prime_num)) +print(next(prime_num)) +print(next(prime_num)) +print(next(prime_num)) +print(next(prime_num)) + + + + + + diff --git a/Student/tammyd_Py220/Py220_lesson01/iterator_1_lesson01.py b/Student/tammyd_Py220/Py220_lesson01/iterator_1_lesson01.py new file mode 100644 index 0000000..834a68d --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson01/iterator_1_lesson01.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python + +""" +Simple iterator examples +""" + + +class IterateMe_1: + """ + About as simple an iterator as you can get: + + returns the sequence of numbers from zero to 4 + ( like range(4) ) + """ + + def __init__(self, stop=5): + self.current = -1 + self.stop = stop + + def __iter__(self): + return self + + def __next__(self): + self.current += 1 + if self.current < self.stop: + return self.current + else: + raise StopIteration + +# Extend (iterator_1.py ) to be more like range() – +# add three input parameters: iterator_2(start, stop, step=1) +class IterateMe_2(IterateMe_1): + def __init__(self, start, stop, step=1): + self.start = start - step + self.stop = stop + self.step = step + + def __iter__(self): + return self + + def __next__(self): + self.start += self.step + if self.start < self.stop: + return self.start + else: + raise StopIteration + + +if __name__ == "__main__": + print("Testing the iterator") + for i in IterateMe_2(2, 20, 2): + print(i) + + # Out: + # Testing the iterator + # 2 + # 4 + # 6 + # 8 + # 10 + # 12 + # 14 + # 16 + # 18 + + print("\nUsing a break keyword:") + # What happens if you break from a loop and try to pick it up again: + it = IterateMe_2(2, 20, 2) + for i in it: + if i > 10: break + print(i) + + # Out: + # Testing the iterator + # 2 + # 4 + # 6 + # 8 + # 10 + + for i in it: + print(i) + # Out: + # 14 + # 16 + # 18 + +# Does range() behave the same? +# make yours match range() +# is range an iterator or an iteratable? + # Range is an iterable diff --git a/Student/tammyd_Py220/Py220_lesson01/test_generator.py b/Student/tammyd_Py220/Py220_lesson01/test_generator.py new file mode 100644 index 0000000..a6a4690 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson01/test_generator.py @@ -0,0 +1,62 @@ +""" +test_generator.py + +tests the solution to the generator lab + +can be run with py.test or nosetests + +""" + +import generator as gen + + +def test_intsum(): + + g = gen.intsum() + + assert next(g) == 0 + assert next(g) == 1 + assert next(g) == 3 + assert next(g) == 6 + assert next(g) == 10 + assert next(g) == 15 + + +# def test_intsum2(): + +# g = gen.intsum2() + +# assert next(g) == 0 +# assert next(g) == 1 +# assert next(g) == 3 +# assert next(g) == 6 +# assert next(g) == 10 +# assert next(g) == 15 + + +def test_doubler(): + + g = gen.doubler() + + assert next(g) == 1 + assert next(g) == 2 + assert next(g) == 4 + assert next(g) == 8 + assert next(g) == 16 + assert next(g) == 32 + + for i in range(10): + j = next(g) + + assert j == 2**15 + + +def test_fib(): + g = gen.fib() + assert [next(g) for i in range(9)] == [1, 1, 2, 3, 5, 8, 13, 21, 34] + + +def test_prime(): + g = gen.prime() + for val in [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]: + assert next(g) == val From 11fa7dc7733f0f1d89eb0967235e045bee15e070 Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Wed, 6 Jun 2018 01:57:55 -0700 Subject: [PATCH 02/15] commit lesson02 --- .../Py220_lesson02/lesson02.ipynb | 478 ++++++++++++++++++ 1 file changed, 478 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson02/lesson02.ipynb diff --git a/Student/tammyd_Py220/Py220_lesson02/lesson02.ipynb b/Student/tammyd_Py220/Py220_lesson02/lesson02.ipynb new file mode 100644 index 0000000..f7c5baa --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson02/lesson02.ipynb @@ -0,0 +1,478 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "class Primes:\n", + " def __init__(self, max):\n", + " self.max = max\n", + " self.number = 1\n", + " def __iter__(self):\n", + " return self\n", + " def __next__(self):\n", + " self.number += 1\n", + " if self.number >= self.max:\n", + " raise StopIteration\n", + " elif check_prime(self.number):\n", + " return self.number\n", + " else:\n", + " return self.__next__()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "def check_prime(number):\n", + " for divisor in range(2, int(number ** 0.5) + 1):\n", + " if number % divisor == 0:\n", + " return False\n", + " return True" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "<__main__.Primes object at 0x10491a5c0>\n", + "2\n", + "3\n", + "5\n", + "7\n", + "11\n", + "13\n", + "17\n", + "19\n", + "23\n", + "29\n", + "31\n", + "37\n", + "41\n", + "43\n", + "47\n", + "53\n", + "59\n", + "61\n", + "67\n", + "71\n", + "73\n", + "79\n", + "83\n", + "89\n", + "97\n" + ] + } + ], + "source": [ + "primes = Primes(100)\n", + "print(primes)\n", + "for x in primes:\n", + " print(x)" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "## Generator Intro\n", + "\n", + "A generator must have a yield\n", + "It can yield many number of times\n", + "Yield is two way - you can input and output\n", + "It saves state\n", + "It is a better version than Iterator or regulat function" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "285" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "## Generator Expressions\n", + "\n", + "sum([x*x for x in range(10)])" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# variable = [out_exp for out_exp in input_list if out_exp == 2]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "2\n", + "3\n", + "5\n", + "7\n", + "11\n", + "13\n", + "17\n", + "19\n", + "23\n", + "29\n", + "31\n", + "37\n", + "41\n", + "43\n", + "47\n", + "53\n", + "59\n", + "61\n", + "67\n", + "71\n", + "73\n", + "79\n", + "83\n", + "89\n", + "97\n" + ] + } + ], + "source": [ + "def Primes(max):\n", + " number = 1\n", + " while number < max:\n", + " number += 1\n", + " if check_prime(number):\n", + " yield number\n", + " \n", + "primes = Primes(100)\n", + "print(primes)\n", + "for x in primes:\n", + " print(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## Non local vs Global" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Inner: Hey!\n" + ] + } + ], + "source": [ + "def outerFunction(text):\n", + " text = text\n", + " \n", + " def innerFunction():\n", + " print(\"Inner:\", text)\n", + " \n", + " return innerFunction # Note we are returning function WITHOUT parenthesis\n", + " \n", + "if __name__ == '__main__':\n", + " myFunction = outerFunction('Hey!')\n", + " myFunction()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'outside': 1, 'inside': 2}\n", + "{'outside': 1, 'inside': 2}\n" + ] + } + ], + "source": [ + "def outside():\n", + " d = {\"outside\": 1}\n", + " def inside():\n", + " d[\"inside\"] = 2\n", + " print(d)\n", + " inside()\n", + " print(d)\n", + " \n", + "outside()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'inside': 2}\n", + "Outside\n", + "{'outside': 1}\n" + ] + } + ], + "source": [ + "def outside():\n", + " d = {\"outside\": 1}\n", + " def inside():\n", + " #nonlocal d\n", + " d = {\"inside\":2}\n", + " print(d)\n", + " inside()\n", + " print(\"Outside\")\n", + " print(d)\n", + " \n", + "outside()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# HeapQ Code Example 0-\n", + "\n", + "import heapq" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 4, 6]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "heap =[]\n", + "heapq.heappush(heap,1)\n", + "heapq.heappush(heap,2)\n", + "heapq.heappush(heap,4)\n", + "heapq.heappush(heap,6)\n", + "heapq.heappush(heap,7)\n", + "heapq.heappush(heap,9)\n", + "heapq.heappush(heap,10)\n", + "heapq.heappush(heap,12) \n", + "heapq.nsmallest(4, heap)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "# With Partial code" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 3, 4, 5, 6, 8]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import functools\n", + "import heapq\n", + "heap =[]\n", + "push = functools.partial(heapq.heappush, heap)\n", + "smallest = functools.partial(heapq.nsmallest, iterable=heap)\n", + "push(1)\n", + "push(3)\n", + "push(5)\n", + "push(6)\n", + "push(8)\n", + "push(11)\n", + "push(4)\n", + "push(16)\n", + "push(17)\n", + "smallest(6)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 4, 6]" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "heap = []\n", + "heapq.heappush(heap,1)\n", + "heapq.heappush(heap,2)\n", + "heapq.heappush(heap,4)\n", + "heapq.heappush(heap,6)\n", + "heapq.heappush(heap,7)\n", + "heapq.heappush(heap,9)\n", + "heapq.heappush(heap,10)\n", + "heapq.heappush(heap,12) \n", + "heapq.nsmallest(4, heap)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "# see if you can get izip to work ...." + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "ename": "ImportError", + "evalue": "cannot import name 'izip'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mitertools\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mizip\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mizip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'a'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'b'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'c'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mImportError\u001b[0m: cannot import name 'izip'" + ] + } + ], + "source": [ + "from itertools import izip\n", + "for i in izip([1, 2, 3], ['a', 'b', 'c']):\n", + " print(i)\n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "from itertools import islice\n", + "\n", + "slice = islice(\"ABCDEGF\", 2, None)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "C\n", + "D\n", + "E\n", + "G\n", + "F\n" + ] + } + ], + "source": [ + "for x in slice:\n", + " print(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 50baaeb672ed47cb69d1536b03ea0d2ab19f6301 Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Sun, 10 Jun 2018 16:57:54 -0700 Subject: [PATCH 03/15] commit lesson02 --- .../generators_closures_lesson02.py | 47 ++++++++++++ .../Py220_lesson02/lesson02.ipynb | 71 +++++++++---------- 2 files changed, 79 insertions(+), 39 deletions(-) create mode 100644 Student/tammyd_Py220/Py220_lesson02/generators_closures_lesson02.py diff --git a/Student/tammyd_Py220/Py220_lesson02/generators_closures_lesson02.py b/Student/tammyd_Py220/Py220_lesson02/generators_closures_lesson02.py new file mode 100644 index 0000000..6ec079f --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson02/generators_closures_lesson02.py @@ -0,0 +1,47 @@ +#!usr/local/bin/python3 + +""" + +Py220: Advanced Programming in Python +Lesson 02 Assignment: Generators and Closures + +Generators and Closures + +""" + + +import pandas as pd + +music = pd.read_csv("featuresdf.csv") + +# write a generator to print all of Ed Sheeran’s tracks +music_data = [x for x in zip(music.artists, music.name)] + +def track_generator(music_data): + for data in music_data: + if data[0] == "Ed Sheeran": + yield "{}: {}".format(data[0], data[1]) + +ed_sheeran = track_generator(music_data) +print(next(ed_sheeran)) +print(next(ed_sheeran)) +print(next(ed_sheeran)) +print(next(ed_sheeran)) +print() + + + +# Write a closure to capture high energy tracks over 8.0. +music_data2 = [x for x in zip(music.artists, music.name, music.energy) + if x[2] > 0.8] + +def high_energy_closure(): + def return_high_energy(music_data2): + return sorted(music_data2, key=lambda x: x[2], reverse=True) + return return_high_energy(music_data2) + + +# Submit your code and the tracks it finds, artist name, track name and energy value. +energy_data = high_energy_closure() +for data in energy_data: + print(data[0], data[1], data[2]) diff --git a/Student/tammyd_Py220/Py220_lesson02/lesson02.ipynb b/Student/tammyd_Py220/Py220_lesson02/lesson02.ipynb index f7c5baa..55c9535 100644 --- a/Student/tammyd_Py220/Py220_lesson02/lesson02.ipynb +++ b/Student/tammyd_Py220/Py220_lesson02/lesson02.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 51, "metadata": {}, "outputs": [], "source": [ @@ -24,7 +24,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 52, "metadata": {}, "outputs": [], "source": [ @@ -37,14 +37,14 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 53, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "<__main__.Primes object at 0x10491a5c0>\n", + "<__main__.Primes object at 0x1049ca6a0>\n", "2\n", "3\n", "5\n", @@ -95,7 +95,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 54, "metadata": {}, "outputs": [ { @@ -104,7 +104,7 @@ "285" ] }, - "execution_count": 4, + "execution_count": 54, "metadata": {}, "output_type": "execute_result" } @@ -117,7 +117,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 55, "metadata": {}, "outputs": [], "source": [ @@ -126,14 +126,14 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 56, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\n", + "\n", "2\n", "3\n", "5\n", @@ -178,7 +178,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 57, "metadata": {}, "outputs": [], "source": [ @@ -187,7 +187,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 58, "metadata": {}, "outputs": [ { @@ -214,7 +214,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 59, "metadata": {}, "outputs": [ { @@ -240,7 +240,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 60, "metadata": {}, "outputs": [ { @@ -269,7 +269,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 61, "metadata": {}, "outputs": [], "source": [ @@ -280,7 +280,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 62, "metadata": {}, "outputs": [ { @@ -289,7 +289,7 @@ "[1, 2, 4, 6]" ] }, - "execution_count": 18, + "execution_count": 62, "metadata": {}, "output_type": "execute_result" } @@ -309,7 +309,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 63, "metadata": {}, "outputs": [], "source": [ @@ -318,16 +318,16 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[1, 3, 4, 5, 6, 8]" + "[1, 3, 4, 5, 6, 8, 11, 16, 17]" ] }, - "execution_count": 21, + "execution_count": 64, "metadata": {}, "output_type": "execute_result" } @@ -347,21 +347,21 @@ "push(4)\n", "push(16)\n", "push(17)\n", - "smallest(6)" + "smallest(10)" ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[1, 2, 4, 6]" + "[1, 2, 4, 6, 7, 9, 10, 12]" ] }, - "execution_count": 24, + "execution_count": 65, "metadata": {}, "output_type": "execute_result" } @@ -376,12 +376,12 @@ "heapq.heappush(heap,9)\n", "heapq.heappush(heap,10)\n", "heapq.heappush(heap,12) \n", - "heapq.nsmallest(4, heap)" + "heapq.nsmallest(8, heap)" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 66, "metadata": {}, "outputs": [], "source": [ @@ -390,26 +390,19 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 75, "metadata": {}, "outputs": [ { - "ename": "ImportError", - "evalue": "cannot import name 'izip'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mfrom\u001b[0m \u001b[0mitertools\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mizip\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mizip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'a'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'b'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'c'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mImportError\u001b[0m: cannot import name 'izip'" + "name": "stdout", + "output_type": "stream", + "text": [ + "(1, 2) (2, 3) (4, 5) (6, 7) (7, 11) (9, 13)\n" ] } ], "source": [ - "from itertools import izip\n", - "for i in izip([1, 2, 3], ['a', 'b', 'c']):\n", - " print(i)\n", - " \n", + "print(*zip(heap, Primes(13)))\n", " " ] }, From 91b8d33bc075f23132927db8f7c9293bd66dc854 Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Wed, 13 Jun 2018 16:16:29 -0700 Subject: [PATCH 04/15] commit lesson03 --- .../tammyd_Py220/Py220_lesson03/Lesson3.ipynb | 3681 +++++++++++++++++ .../context_managers_lesson03.py | 65 + .../Py220_lesson03/decorators.ipynb | 196 + .../lesson03_context_manager.py | 27 + .../Py220_lesson03/lesson03_logging.ipynb | 47 + .../Py220_lesson03/recursion_lesson03.py | 26 + 6 files changed, 4042 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson03/Lesson3.ipynb create mode 100644 Student/tammyd_Py220/Py220_lesson03/context_managers_lesson03.py create mode 100644 Student/tammyd_Py220/Py220_lesson03/decorators.ipynb create mode 100644 Student/tammyd_Py220/Py220_lesson03/lesson03_context_manager.py create mode 100644 Student/tammyd_Py220/Py220_lesson03/lesson03_logging.ipynb create mode 100644 Student/tammyd_Py220/Py220_lesson03/recursion_lesson03.py diff --git a/Student/tammyd_Py220/Py220_lesson03/Lesson3.ipynb b/Student/tammyd_Py220/Py220_lesson03/Lesson3.ipynb new file mode 100644 index 0000000..01508c2 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson03/Lesson3.ipynb @@ -0,0 +1,3681 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'logged' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"add func\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mdecorators\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlogged\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdecorators\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0;31m## Same as\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mNameError\u001b[0m: name 'logged' is not defined" + ] + } + ], + "source": [ + "def add(x,y):\n", + " print(\"add func\")\n", + " return x+y\n", + "decorators.add = logged(decorators.add)\n", + " ## Same as\n", + " \n", + "\n", + "@logged\n", + "def add(x,y):\n", + " print(\"add func\")\n", + " return x+y\n", + "\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "## Decorators\n", + "\n", + "def null_decorator(func):\n", + " return func\n", + "\n", + "def greet():\n", + " return 'Hello!'\n", + "\n", + "greet = null_decorator(greet)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hello!'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "greet()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "## Above same as this ..\n", + "\n", + "@null_decorator\n", + "def greet():\n", + " return 'Hello!'\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hello!'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "greet()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "## Decorators\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "from functools import wraps\n", + "def nullable(function):\n", + " @wraps(function)\n", + " def null_wrapper(arg):\n", + " return None if arg is None else function(arg)\n", + " return null_wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "nlog = nullable(math.log)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "some_data = [10, 100, None, 50, 60]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "scaled = map(nlog, some_data) " + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[2.302585092994046,\n", + " 4.605170185988092,\n", + " None,\n", + " 3.912023005428146,\n", + " 4.0943445622221]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "list(scaled)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "## Enter Context Manager" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: 'x.txt'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m## Context Manager\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mf\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mopen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"x.txt\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: 'x.txt'" + ] + } + ], + "source": [ + "## Context Manager\n", + "\n", + "f = open(\"x.txt\")" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'f' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__enter__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'f' is not defined" + ] + } + ], + "source": [ + "f.__enter__()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'f' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'f' is not defined" + ] + } + ], + "source": [ + "f.read(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'f' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m## now lets run exit to the close the file\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__exit__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'f' is not defined" + ] + } + ], + "source": [ + "## now lets run exit to the close the file\n", + "f.__exit__(None, None, None)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'f' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m## try to read once again\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'f' is not defined" + ] + } + ], + "source": [ + "## try to read once again\n", + "f.read(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (, line 7)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m7\u001b[0m\n\u001b[0;31m do something with data\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "## Context Manager Summary \n", + "## so to open a file, process its contents, and make sure to close it, \n", + "## you can simply do:\n", + "\n", + "with open(\"x.txt\") as f:\n", + " data = f.read()\n", + " do something with data\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "## Acquiring a lock during threading\n", + "\n", + "import threading\n", + "lock=threading.Lock()\n", + "lock.acquire()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Use the lock\n" + ] + } + ], + "source": [ + "print(\"Use the lock\")\n", + "lock.release()\n", + "\n", + "## you acquire a resource, use it and then close it. \n", + "## but it is easy to close or release the resources\n", + "## Context Manager\n" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "## Context Manager\n", + "\n", + "class Context(object):\n", + "\n", + " def __init__(self, handle_error):\n", + " print ('__init__(%s)' % handle_error)\n", + " self.handle_error = handle_error\n", + " def __enter__(self):\n", + " print ('__enter__()')\n", + " return self\n", + " def __exit__(self, exc_type, exc_val, exc_tb):\n", + " print ('__exit__(%s, %s, %s)' % (exc_type, exc_val, exc_tb))\n", + " return self.handle_error" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "__init__(True)\n", + "__enter__()\n", + "This is in the context\n", + "__exit__(None, None, None)\n" + ] + } + ], + "source": [ + "with Context(True) as foo:\n", + " print ('This is in the context')\n", + " ## run once and the uncomment following line\n", + " ##raise RuntimeError('this is the error message')" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "__init__(False)\n", + "__enter__()\n", + "This is in the context\n", + "__exit__(None, None, None)\n" + ] + } + ], + "source": [ + "## In the above example your code is bracketed by enter and exit\n", + "\n", + "## Because the exit method returns True, the raised error is ‘handled’.\n", + "## What if we try with False?\n", + "\n", + "with Context(False) as foo:\n", + " print ('This is in the context')\n", + " ## run this with and without commenting following line\n", + " ##raise RuntimeError('this is the error message')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "## contextlib.contextmanager() \n", + "## will turn a generator function into context manager." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "from contextlib import contextmanager\n", + "\n", + "@contextmanager\n", + "def context(boolean):\n", + " print (\"__init__ code here\")\n", + " try:\n", + " print (\"__enter__ code goes here\")\n", + " yield object()\n", + " except Exception as e:\n", + " print (\"errors handled here\")\n", + " if not boolean:\n", + " raise\n", + " finally:\n", + " print (\"__exit__ cleanup goes here\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "b'\\n\\n\\n Example Domain\\n\\n \\n \\n \\n \\n\\n\\n\\n
\\n

Example Domain

\\n

This domain is established to be used for illustrative examples in documents. You may use this\\n domain in examples without prior coordination or asking for permission.

\\n

More information...

\\n
\\n\\n\\n'\n" + ] + } + ], + "source": [ + "import contextlib\n", + "import http.client\n", + "with contextlib.closing(\n", + " http.client.HTTPConnection(\"www.example.com\")) as host:\n", + " host.request(\"GET\", \"/path/to/resources/12345/\")\n", + " response= host.getresponse()\n", + " print(response.read())" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Entered\n", + "Closed\n", + "Start of Function\n", + "Entered\n", + "Closed\n", + "End of Function\n", + "Entered\n", + "EOF\n" + ] + } + ], + "source": [ + "from __future__ import print_function\n", + "import contextlib\n", + "\n", + "@contextlib.contextmanager\n", + "def manager():\n", + " \"\"\"Easiest way to get a custom context manager...\"\"\"\n", + " try:\n", + " print('Entered')\n", + " yield\n", + " finally:\n", + " print('Closed')\n", + "\n", + "\n", + "def gen():\n", + " \"\"\"Just a generator with a context manager inside.\n", + "\n", + " When the context is entered, we'll see \"Entered\" on the console\n", + " and when exited, we'll see \"Closed\" on the console.\n", + " \"\"\"\n", + " man = manager()\n", + " with man:\n", + " for i in range(10):\n", + " yield i\n", + "\n", + "\n", + "# Test what happens when we consume a generator.\n", + "list(gen())\n", + "\n", + "def fn():\n", + " g = gen()\n", + " next(g)\n", + " # g.close()\n", + "\n", + "# Test what happens when the generator gets garbage collected inside\n", + "# a function\n", + "print('Start of Function')\n", + "fn()\n", + "print('End of Function')\n", + "\n", + "# Test what happens when a generator gets garbage collected outside\n", + "# a function. IIRC, this isn't _guaranteed_ to happen in all cases.\n", + "g = gen()\n", + "next(g)\n", + "# g.close()\n", + "print('EOF')" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Back to normal stdout again\n" + ] + } + ], + "source": [ + "## Context Manager Examples - Advanced Usecase. \n", + "## yield without argument is semantically equivalent to yield None\n", + "\n", + "from contextlib import contextmanager\n", + "import sys\n", + "\n", + "@contextmanager\n", + "def redirected(**kwds):\n", + " stream_names = [\"stdin\", \"stdout\", \"stderr\"]\n", + " old_streams = {}\n", + " try:\n", + " for sname in stream_names:\n", + " stream = kwds.get(sname, None)\n", + " if stream is not None and stream != getattr(sys, sname):\n", + " old_streams[sname] = getattr(sys, sname)\n", + " setattr(sys, sname, stream)\n", + " yield\n", + " finally:\n", + " for sname, stream in old_streams.items():\n", + " setattr(sys, sname, stream)\n", + "\n", + "with redirected(stdout=open(\"/tmp/uw-py220-log-context-mgr.txt\", \"w\")):\n", + " # these print statements will go to /tmp/log.txt\n", + " print (\"Test entry 1\")\n", + " print (\"Test entry 2\")\n", + "# back to the normal stdout\n", + "print (\"Back to normal stdout again\")" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (, line 3)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m3\u001b[0m\n\u001b[0;31m yield expression returns control to the whatever is using the generator.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "## Yield in Context Manager\n", + "\n", + "yield expression returns control to the whatever is using the generator. \n", + "The generator pauses at this point, which means that the @contextmanager \n", + "decorator knows that the code is done with the setup part.\n", + "\n", + "In other words, everything you want to do in the context manager __enter__ \n", + "phase has to take place before the yield.\n", + "\n", + "Once your context exits (so the block under the with statement is done), \n", + "the @contextmanager decorator is called for the __exit__ part of the \n", + "context manager protocol and will do one of two things:\n", + "\n", + "If there was no exception, it'll resume your generator. So your generator \n", + "unpauses at the yield line, and you enter the cleanup phase, the part\n", + "\n", + "If there was an exception, the decorator uses generator.throw() to raise \n", + "that exception in the generator. It'll be as if the yield line caused \n", + "that exception. Because you have a finally clause, it'll be executed \n", + "before your generator exits because of the exception." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "## Recursion\n", + "\n", + "## Recursion to use up all stack space. \n", + "## RuntimeError: maximum recursion depth exceeded\n" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello\n", + "Hello" + ] + }, + { + "ename": "RecursionError", + "evalue": "maximum recursion depth exceeded in comparison", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mRecursionError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mf\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Hello\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "... last 1 frames repeated, from the frame below ...\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mf\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Hello\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mRecursionError\u001b[0m: maximum recursion depth exceeded in comparison" + ] + } + ], + "source": [ + "def f():\n", + " print(\"Hello\")\n", + " f()\n", + "\n", + "f()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Student/tammyd_Py220/Py220_lesson03/context_managers_lesson03.py b/Student/tammyd_Py220/Py220_lesson03/context_managers_lesson03.py new file mode 100644 index 0000000..ea3cf79 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson03/context_managers_lesson03.py @@ -0,0 +1,65 @@ +#!usr/local/bin/python3 + +""" + +Py220: Advanced Programming in Python +Lesson 03 Activity & Assignment: Context Managers + +Context Managers + +""" + + + +# During initialization the context manger class accepts the locke’s capacity in number of boats. +# If someone tries to move too many boats through the locke, anything over its established capacity, raise a suitable error. + +class Locke: + + def __init__(self, boats): + self.boats = boats + + # When the locke is entered it stops the pumps, opens the doors, closes the doors, and restarts the pumps. + def __enter__(self): + return self + + # when the locke is exited it runs through the same steps: it stops the pumps, opens the doors, closes the doors, and restarts the pumps. + def __exit__(self, exc_type, exc_val, exc_tb): + print("__exit__({}, {}, {})".format(exc_type, exc_val, exc_tb)) + return self + + def move_boats_through(self, num_boats): + # If someone tries to move too many boats through the locke, anything over its established capacity, raise a suitable error. + if num_boats > self.boats: + raise ValueError("Too many boats. {} boats is more than the {} boat capacity.".format(num_boats, self.boats)) + else: + print("Moving boats through. \n" \ + "Stopping the pumps. \n" \ + "Opening the doors. \n" \ + "Closing the doors. \n" \ + "Restarting the pumps.") + + +if __name__ == '__main__': + # capacity of the small locke is 5 boats + small_locke = Locke(5) + # capacity of the large locke is 10 boats + large_locke = Locke(10) + # attempting to pass through 8 boats + # boats = 8 + + with small_locke as locke: + print("Small boat:") + locke.move_boats_through(5) + + + + with large_locke as locke: + print("\nLarge boat:") + locke.move_boats_through(8) + + with large_locke as locke: + print("\nLarge boat:") + locke.move_boats_through(18) + + diff --git a/Student/tammyd_Py220/Py220_lesson03/decorators.ipynb b/Student/tammyd_Py220/Py220_lesson03/decorators.ipynb new file mode 100644 index 0000000..1c48498 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson03/decorators.ipynb @@ -0,0 +1,196 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (, line 11)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m11\u001b[0m\n\u001b[0;31m def mul(x,y)\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "## start with this ...\n", + "\n", + "## make decorators.py file\n", + "\n", + "def add(x,y):\n", + "\treturn x+y\n", + "\n", + "def sub(x,y):\n", + "\treturn x-y\n", + "\n", + "def mul(x,y)\n", + "\treturn x*y\n", + "\n", + "### calling this in the repl\n", + "\n", + ">>> import decorators.py\n", + "\n", + "\n", + "## Add prints\n", + "\n", + "def add(x,y):\n", + "\tprint(\"Calling add\") \n", + " return x+y\n", + "\n", + "def sub(x,y):\n", + "\tprint(\"Calling sub\")\n", + " return x-y\n", + "\n", + "def mul(x,y)\n", + " print(\"Calling mul\")\n", + "\treturn x*y \n", + "\n", + "### calling this in the repl\n", + "\n", + ">>> import decorators.py\n", + "\n", + "## Now, you have to do something else or change all these edtis,\n", + "## we would have to go back and change our code in 100s of place\n", + "\n", + "## this is turning into a maintenance nightmare\n", + "## also the code is repeated - which goes against the concept of programming\n", + "\n", + "## Lets take this code and generalize this\n", + "\n", + "## You are going to give me a function and I will write a wrapper around it\n", + "\n", + "## file name logcall.py\n", + "\n", + "def logged(func):\n", + "\t# adding logging\n", + "\tdef wrapper(*args, **kwargs):\n", + "\t\tprint('Calling', func.__name__)\n", + "\t\treturn func(*args, **kwargs)\n", + "\treturn wrapper\n", + "\n", + "## Once that is done, then \n", + "## import the logcall.py\n", + "\n", + "## create decorators.py file\n", + "\n", + "from logcall import logged\n", + "\n", + "add = logged(add)\n", + "sub = logged(sub)\n", + "\n", + "## loging has been isolated in place\n", + "## but we have manually wrap the logged function\n", + "## like this\n", + "\n", + "\n", + "def add(x,y):\n", + " return x+y\n", + "add=logged(add)\n", + "\n", + "def sub(x,y):\n", + " return x-y\n", + "sub=logged(sub)\n", + "\n", + "def mul(x,y)\n", + " return x*y\n", + "mul=logged(mul)\n", + "\n", + "## this is the idea behind decoration\n", + "## go back to theory and then come to next phase - \n", + "\n", + "\n", + "## This is still not ideal as we would have to do this for all our n number \n", + "## of functions\n", + "\n", + "def add(x,y):\n", + " return x+y\n", + "add=logged(add)\n", + "\n", + "## can be turned into \n", + "\n", + "@logged\n", + "def add(x,y):\n", + " return x+y\n", + "\n", + "## we would have to add @logged for all the 500 functions ....\n", + "## These wrapper functions we create do not look anything else original \n", + "## functions - # type this\n", + "\n", + ">>> decorators.add\n", + ">>> decorators.sub\n", + ">>> help (decorators.add)\n", + "\n", + "## it doesn't show anything about the original function - just says wrapper. \n", + "\n", + "## So, when you define a wrapper, you need to get some documentation over\n", + "## from original function\n", + "\n", + "## This is done using wraps from functools. \n", + "## so in the logcall.py, add wraps at the top\n", + "\n", + "from functools import wraps\n", + "\n", + "@wraps(func)\n", + "def logged(func):\n", + " # adding logging\n", + " def wrapper(*args, **kwargs):\n", + " print('Calling', func.__name__)\n", + " return func(*args, **kwargs)\n", + "\n", + " return wrapper\n", + "\n", + "## end logcall file\n", + "\n", + "## adding wraps is equivilant to \n", + "## wraper.__name__=func.__name__\n", + "## wrapper.__doc__=func.__doc__\n", + "\n", + "## now try \n", + "\n", + ">>> decorators.add\n", + ">>> decorators.sub\n", + ">>> help (decorators.add)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def add(x, y):\n", + " print(\"add func\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Student/tammyd_Py220/Py220_lesson03/lesson03_context_manager.py b/Student/tammyd_Py220/Py220_lesson03/lesson03_context_manager.py new file mode 100644 index 0000000..bfae758 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson03/lesson03_context_manager.py @@ -0,0 +1,27 @@ +## Context Manager Examples - Advanced Usecase. +## yield without argument is semantically equivalent to yield None + +from contextlib import contextmanager +import sys + +@contextmanager +def redirected(**kwds): + stream_names = ["stdin", "stdout", "stderr"] + old_streams = {} + try: + for sname in stream_names: + stream = kwds.get(sname, None) + if stream is not None and stream != getattr(sys, sname): + old_streams[sname] = getattr(sys, sname) + setattr(sys, sname, stream) + yield + finally: + for sname, stream in old_streams.items(): + setattr(sys, sname, stream) + +with redirected(stdout=open("/tmp/uw-py220-log-context-mgr.txt", "w")): + # these print statements will go to /tmp/log.txt + print ("Test entry 1") + print ("Test entry 2") +# back to the normal stdout +print ("Back to normal stdout again") \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson03/lesson03_logging.ipynb b/Student/tammyd_Py220/Py220_lesson03/lesson03_logging.ipynb new file mode 100644 index 0000000..37e3a55 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson03/lesson03_logging.ipynb @@ -0,0 +1,47 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def add (a, b):\n", + " print(\"this is add function\")\n", + " logged(\"this is log for add\")\n", + " return a + b\n", + "\n", + "def sub(a, b):\n", + " print(\"this is add function\")\n", + " logged(\"this is log for add\")\n", + " return a - b\n", + "\n", + "def mul(a, b):\n", + " print(\"this is add function\")\n", + " logged(\"this is log for add\")\n", + " return a * b" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Student/tammyd_Py220/Py220_lesson03/recursion_lesson03.py b/Student/tammyd_Py220/Py220_lesson03/recursion_lesson03.py new file mode 100644 index 0000000..bbdb2ba --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson03/recursion_lesson03.py @@ -0,0 +1,26 @@ +#!usr/local/bin/python3 + +""" + +Py220: Advanced Programming in Python +Lesson 03 Activity & Assignment: Recursion + +Recursion + +""" + +# Write a recursive solution for the factorial function. + +def factorial(n): + if n < 0: + return -1 + elif n < 2: + return 1 + else: + return n * factorial(n-1) + +print(factorial(10)) + + +for i in range(0,10): + print("Factorial of {} equals {}.".format(i, factorial(i))) \ No newline at end of file From d00a35a121772c41a3b729e21ecf019bb6b732e7 Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Wed, 13 Jun 2018 21:53:18 -0700 Subject: [PATCH 05/15] re-commit assignment 2. converted an .ipynb file to a .py file. --- .../tammyd_Py220/Py220_lesson02/lesson02.py | 223 ++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson02/lesson02.py diff --git a/Student/tammyd_Py220/Py220_lesson02/lesson02.py b/Student/tammyd_Py220/Py220_lesson02/lesson02.py new file mode 100644 index 0000000..fcbaa90 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson02/lesson02.py @@ -0,0 +1,223 @@ +# Lesson02 Activity +# .ipynb file converted to .py file + + +# coding: utf-8 + +# In[51]: + + +class Primes: + def __init__(self, max): + self.max = max + self.number = 1 + def __iter__(self): + return self + def __next__(self): + self.number += 1 + if self.number >= self.max: + raise StopIteration + elif check_prime(self.number): + return self.number + else: + return self.__next__() + + +# In[52]: + + +def check_prime(number): + for divisor in range(2, int(number ** 0.5) + 1): + if number % divisor == 0: + return False + return True + + +# In[53]: + + +primes = Primes(100) +print(primes) +for x in primes: + print(x) + +## Generator Intro + +A generator must have a yield +It can yield many number of times +Yield is two way - you can input and output +It saves state +It is a better version than Iterator or regulat function +# In[54]: + + +## Generator Expressions + +sum([x*x for x in range(10)]) + + +# In[55]: + + +# variable = [out_exp for out_exp in input_list if out_exp == 2] + + +# In[56]: + + +def Primes(max): + number = 1 + while number < max: + number += 1 + if check_prime(number): + yield number + +primes = Primes(100) +print(primes) +for x in primes: + print(x) + + +# In[57]: + + +## Non local vs Global + + +# In[58]: + + +def outerFunction(text): + text = text + + def innerFunction(): + print("Inner:", text) + + return innerFunction # Note we are returning function WITHOUT parenthesis + +if __name__ == '__main__': + myFunction = outerFunction('Hey!') + myFunction() + + +# In[59]: + + +def outside(): + d = {"outside": 1} + def inside(): + d["inside"] = 2 + print(d) + inside() + print(d) + +outside() + + +# In[60]: + + +def outside(): + d = {"outside": 1} + def inside(): + #nonlocal d + d = {"inside":2} + print(d) + inside() + print("Outside") + print(d) + +outside() + + +# In[61]: + + +# HeapQ Code Example 0- + +import heapq + + +# In[62]: + + +heap =[] +heapq.heappush(heap,1) +heapq.heappush(heap,2) +heapq.heappush(heap,4) +heapq.heappush(heap,6) +heapq.heappush(heap,7) +heapq.heappush(heap,9) +heapq.heappush(heap,10) +heapq.heappush(heap,12) +heapq.nsmallest(4, heap) + + +# In[63]: + + +# With Partial code + + +# In[64]: + + +import functools +import heapq +heap =[] +push = functools.partial(heapq.heappush, heap) +smallest = functools.partial(heapq.nsmallest, iterable=heap) +push(1) +push(3) +push(5) +push(6) +push(8) +push(11) +push(4) +push(16) +push(17) +smallest(10) + + +# In[65]: + + +heap = [] +heapq.heappush(heap,1) +heapq.heappush(heap,2) +heapq.heappush(heap,4) +heapq.heappush(heap,6) +heapq.heappush(heap,7) +heapq.heappush(heap,9) +heapq.heappush(heap,10) +heapq.heappush(heap,12) +heapq.nsmallest(8, heap) + + +# In[66]: + + +# see if you can get izip to work .... + + +# In[75]: + + +print(*zip(heap, Primes(13))) + + + +# In[29]: + + +from itertools import islice + +slice = islice("ABCDEGF", 2, None) + + +# In[16]: + + +for x in slice: + print(x) + From 0af591ab22a4349c20398f10d20823829b0226f5 Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Sun, 17 Jun 2018 23:58:07 -0700 Subject: [PATCH 06/15] recommit lesson01. updated generator_solution.py --- .../Py220_lesson01/generator_solution.py | 88 +++++++++++++++++++ .../Py220_lesson01/test_generator.py | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 Student/tammyd_Py220/Py220_lesson01/generator_solution.py diff --git a/Student/tammyd_Py220/Py220_lesson01/generator_solution.py b/Student/tammyd_Py220/Py220_lesson01/generator_solution.py new file mode 100644 index 0000000..8daf86e --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson01/generator_solution.py @@ -0,0 +1,88 @@ +#!/usr/local/bin/python3 + +""" +Py220: Advanced Python +Lesson 01 + +Generators +""" + + +# Write a few generators: +# generator format: +# def a_generator_function(params): +# some_stuff +# yield something + + +# Sum of integers +def intsum(x=0, sum=0): + while True: + sum += x + yield sum + x += 1 + +sum_int = intsum() +print(next(sum_int)) + + + + +# Doubler +def doubler(x=1): + while True: + yield x + x = x*2 + +sum_doubler = doubler() +print(next(sum_doubler)) + + + + +# Fibonacci sequence +def fib(a=1, b=1): + while True: + yield a + a, b = b, a+b + +fib_num = fib() +print(next(fib_num)) + +print() + + + +# # Prime numbers +def prime(x=2): + while True: + if not [val for val in range(2, x) if x % val == 0]: + yield x + x += 1 + +# My incorrect try. Yielding all odds. How can I edit to yield just primes? + +# def prime(x=1): +# if x == 2: +# yield x +# while True: +# if x % 2 != 0: +# yield x +# x += 1 +# else: +# x += 1 + +prime_num = prime() +print(next(prime_num)) +print(next(prime_num)) +print(next(prime_num)) +print(next(prime_num)) +print(next(prime_num)) +print(next(prime_num)) +print(next(prime_num)) + + + + + + diff --git a/Student/tammyd_Py220/Py220_lesson01/test_generator.py b/Student/tammyd_Py220/Py220_lesson01/test_generator.py index a6a4690..7f5dc1f 100644 --- a/Student/tammyd_Py220/Py220_lesson01/test_generator.py +++ b/Student/tammyd_Py220/Py220_lesson01/test_generator.py @@ -7,7 +7,7 @@ """ -import generator as gen +import generator_solution as gen def test_intsum(): From 43118ffa57dd2547afec2085a9170c290923411c Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Mon, 9 Jul 2018 16:13:47 -0700 Subject: [PATCH 07/15] commit lesson05 and activity05 --- .../Py220_lesson05/DODebugging.txt | 251 ++++++++++++++++++ .../tammyd_Py220/Py220_lesson05/pysyslog.py | 37 +++ Student/tammyd_Py220/Py220_lesson05/simple.py | 68 +++++ Student/tammyd_Py220/Py220_lesson05/syslog.py | 23 ++ 4 files changed, 379 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson05/DODebugging.txt create mode 100644 Student/tammyd_Py220/Py220_lesson05/pysyslog.py create mode 100644 Student/tammyd_Py220/Py220_lesson05/simple.py create mode 100644 Student/tammyd_Py220/Py220_lesson05/syslog.py diff --git a/Student/tammyd_Py220/Py220_lesson05/DODebugging.txt b/Student/tammyd_Py220/Py220_lesson05/DODebugging.txt new file mode 100644 index 0000000..cfc3b8f --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson05/DODebugging.txt @@ -0,0 +1,251 @@ +recursive.py + +What is wrong with our logic? +It only effectively deals with powers of 2. n has tp reach exactly two. + +Why doesn't the function stop calling itself? +There is no False clause. It will never stop if n never is equal to 2. + + +What's happening to the value of 'n' as the function gets deeper and deeper into recursion? +n continues to be divided by 2. n will always be divisible by two and each time it is divided it will continue go deeper into the stack. + + + +import sys + +def my_fun(n): + if n == 2: + return True + + return my_fun(n/2) + +if __name__ == "__main__": + n = int(sys.argv[1]) + print(my_fun(n)) + + + + +####################################### + +Tammys-MBP:Py220_lesson05 tammydo$ python -m pdb recursive.py 16 +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(5)() +-> import sys +(Pdb) ll + 1 #recursive.py + 2 + 3 + 4 + 5 -> import sys + 6 + 7 def my_fun(n): + 8 if n == 2: + 9 return True + 10 + 11 return my_fun(n/2) + 12 + 13 if __name__ == "__main__": + 14 n = int(sys.argv[1]) + 15 print(my_fun(n)) + 16 + 17 + 18 + 19 +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(7)() +-> def my_fun(n): +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(13)() +-> if __name__ == "__main__": +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(14)() +-> n = int(sys.argv[1]) +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(15)() +-> print(my_fun(n)) +(Pdb) pp n +16 +(Pdb) ll + 1 #recursive.py + 2 + 3 + 4 + 5 import sys + 6 + 7 def my_fun(n): + 8 if n == 2: + 9 return True + 10 + 11 return my_fun(n/2) + 12 + 13 if __name__ == "__main__": + 14 n = int(sys.argv[1]) + 15 -> print(my_fun(n)) + 16 + 17 + 18 + 19 +(Pdb) s +--Call-- +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(7)my_fun() +-> def my_fun(n): +(Pdb) ll + 7 -> def my_fun(n): + 8 if n == 2: + 9 return True + 10 + 11 return my_fun(n/2) +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(8)my_fun() +-> if n == 2: +(Pdb) pp n +16 +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(11)my_fun() +-> return my_fun(n/2) +(Pdb) s +--Call-- +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(7)my_fun() +-> def my_fun(n): +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(8)my_fun() +-> if n == 2: +(Pdb) pp n +8.0 +(Pdb) ll + 7 def my_fun(n): + 8 -> if n == 2: + 9 return True + 10 + 11 return my_fun(n/2) +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(11)my_fun() +-> return my_fun(n/2) +(Pdb) s +--Call-- +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(7)my_fun() +-> def my_fun(n): +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(8)my_fun() +-> if n == 2: +(Pdb) pp n +4.0 +(Pdb) ll + 7 def my_fun(n): + 8 -> if n == 2: + 9 return True + 10 + 11 return my_fun(n/2) +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(11)my_fun() +-> return my_fun(n/2) +(Pdb) s +--Call-- +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(7)my_fun() +-> def my_fun(n): +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(8)my_fun() +-> if n == 2: +(Pdb) ll + 7 def my_fun(n): + 8 -> if n == 2: + 9 return True + 10 + 11 return my_fun(n/2) +(Pdb) pp n +2.0 +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(9)my_fun() +-> return True +(Pdb) n +--Return-- +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(9)my_fun()->True +-> return True +(Pdb) ll + 7 def my_fun(n): + 8 if n == 2: + 9 -> return True + 10 + 11 return my_fun(n/2) +(Pdb) n +--Return-- +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(11)my_fun()->True +-> return my_fun(n/2) +(Pdb) ll + 7 def my_fun(n): + 8 if n == 2: + 9 return True + 10 + 11 -> return my_fun(n/2) +(Pdb) n +--Return-- +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(11)my_fun()->True +-> return my_fun(n/2) +(Pdb) n +--Return-- +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(11)my_fun()->True +-> return my_fun(n/2) +(Pdb) n +True +--Return-- +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(15)()->None +-> print(my_fun(n)) +(Pdb) n +--Return-- +> (1)()->None +(Pdb) n +The program finished and will be restarted +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(5)() +-> import sys +(Pdb) ll + 1 #recursive.py + 2 + 3 + 4 + 5 -> import sys + 6 + 7 def my_fun(n): + 8 if n == 2: + 9 return True + 10 + 11 return my_fun(n/2) + 12 + 13 if __name__ == "__main__": + 14 n = int(sys.argv[1]) + 15 print(my_fun(n)) + 16 + 17 + 18 + 19 +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(7)() +-> def my_fun(n): +(Pdb) s +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(13)() +-> if __name__ == "__main__": +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(14)() +-> n = int(sys.argv[1]) +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(15)() +-> print(my_fun(n)) +(Pdb) n +True +--Return-- +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(15)()->None +-> print(my_fun(n)) +(Pdb) n +--Return-- +> (1)()->None +(Pdb) n +The program finished and will be restarted +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(5)() +-> import sys +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(7)() +-> def my_fun(n): +(Pdb) n +> /Users/tammydo/UW_Python_Programming/SP2018-Python220-Accelerated/Student/tammyd_Py220/Py220_lesson05/recursive.py(13)() +-> if __name__ == "__main__": +(Pdb) \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson05/pysyslog.py b/Student/tammyd_Py220/Py220_lesson05/pysyslog.py new file mode 100644 index 0000000..f4d6235 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson05/pysyslog.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +## Tiny Syslog Server in Python. +## +## This is a tiny syslog server that is able to receive UDP based syslog +## entries on a specified port and save them to a file. +## That's it... it does nothing else... +## There are a few configuration parameters. + +LOG_FILE = 'syslog.log' +HOST, PORT = "127.0.0.1", 514 + +# +# NO USER SERVICEABLE PARTS BELOW HERE... +# + +import logging +import socketserver + +logging.basicConfig(level=logging.INFO, format='%(message)s', datefmt='', filename=LOG_FILE, filemode='a') + +class SyslogUDPHandler(socketserver.BaseRequestHandler): + + def handle(self): + data = bytes.decode(self.request[0].strip()) + socket = self.request[1] + print( "%s : " % self.client_address[0], str(data)) + logging.info(str(data)) + +if __name__ == "__main__": + try: + server = socketserver.UDPServer((HOST,PORT), SyslogUDPHandler) + server.serve_forever(poll_interval=0.5) + except (IOError, SystemExit): + raise + except KeyboardInterrupt: + print ("Crtl+C Pressed. Shutting down.") \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson05/simple.py b/Student/tammyd_Py220/Py220_lesson05/simple.py new file mode 100644 index 0000000..d6ca00b --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson05/simple.py @@ -0,0 +1,68 @@ +import logging +import logging.handlers +import syslog +from datetime import datetime + +format = "%(asctime)s %(filename)s:%(lineno)-4d %(levelname)s %(message)s" # Add/modify these +# logging.basicConfig(level=logging.WARNING, format=format, filename='mylog.log') # two lines + +# Create a "formatter" using our format string +formatter_console = logging.Formatter(format) +formatter_syslog = logging.Formatter(format) + +# Create a log message handler that sends output to the file 'mylog.log' +file_handler = logging.FileHandler('{}.log'.format(datetime.now())) +# You want WARNING and higher messages logged to a file named { todays-date }.log. The format of these messages should include the current time. +file_handler.setLevel(logging.WARNING) +# Set the formatter for this log message handler to the formatter we created above. +file_handler.setFormatter(formatter_console) + + +console_handler = logging.StreamHandler() +console_handler.setLevel(logging.DEBUG) +console_handler.setFormatter(formatter_console) + +#The address and port will be '127.0.0.1' and 514, respectively +syslog_handler = logging.handlers.SysLogHandler(address = ("127.0.0.1", 514)) +syslog_handler.setFormatter(formatter_syslog) + + + +# Get the "root" logger. More on that below. +logger = logging.getLogger() +logger.setLevel(logging.DEBUG) +# Add our file_handler to the "root" logger's handlers. +logger.addHandler(file_handler) +logger.addHandler(console_handler) +logger.addHandler(syslog_handler) + + +def my_fun(n): + for i in range(0, n): + logging.debug(i) + if i == 50: + logging.warning("The value of i is 50.") + try: + i / (50 - i) + except ZeroDivisionError: + logging.error("Tried to divide by zero. Var i was {}. Recovered gracefully.".format(i)) + +if __name__ == "__main__": + my_fun(100) + + + + + + + + + + + + + + + + + diff --git a/Student/tammyd_Py220/Py220_lesson05/syslog.py b/Student/tammyd_Py220/Py220_lesson05/syslog.py new file mode 100644 index 0000000..5338339 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson05/syslog.py @@ -0,0 +1,23 @@ +#syslog.py + +import logging, sys +import logging.handlers + +log = logging.getLogger(__name__) + +log.setLevel(logging.DEBUG) + +handler = logging.handlers.SysLogHandler(address="/var/run/syslog") + +formatter = logging.Formatter('%(module)s.%(funcName)s: %(message)s') + +handler.setFormatter(formatter) + +log.addHandler(handler) + +def hello(): + log.debug('Hello from Python!!! This is a DEBUG message.') + log.critical('Hello from Python!!! This is a CRITICAL message.') + +if __name__ == "__main__": + hello() \ No newline at end of file From 3b6664b1de02fcdc23f1946706239be062844ffa Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Mon, 9 Jul 2018 16:18:39 -0700 Subject: [PATCH 08/15] commit assignment06 and activity06 --- .../roman_numerals/roman_to_int.py | 36 +++++++++++ .../roman_numerals/test_roman_to_int.py | 63 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson06/roman_numerals/roman_to_int.py create mode 100644 Student/tammyd_Py220/Py220_lesson06/roman_numerals/test_roman_to_int.py diff --git a/Student/tammyd_Py220/Py220_lesson06/roman_numerals/roman_to_int.py b/Student/tammyd_Py220/Py220_lesson06/roman_numerals/roman_to_int.py new file mode 100644 index 0000000..146e7c1 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson06/roman_numerals/roman_to_int.py @@ -0,0 +1,36 @@ +# class example +# https://github.com/JASchilz/roman-numerals-exercise/blob/master/roman_numerals/roman_to_int.py + + +class RomanToInt(object): + + @staticmethod + def value_of(c): + if c == 'I': + return 1 + elif c == 'V': + return 5 + elif c == 'X': + return 10 + elif c == 'L': + return 50 + elif c == 'C': + return 100 + elif c == 'D': + return 500 + elif c == 'M': + return 1000 + else: + raise ValueError("Provided character must be one of: I V X L C D M.") + + @classmethod + def convert(cls, s): + + result = 0 + for i, c in enumerate(s): + if (i + 1) < len(s) and cls.value_of(c) < cls.value_of(s[i + 1]): + result -= cls.value_of(c) + else: + result += cls.value_of(c) + + return result diff --git a/Student/tammyd_Py220/Py220_lesson06/roman_numerals/test_roman_to_int.py b/Student/tammyd_Py220/Py220_lesson06/roman_numerals/test_roman_to_int.py new file mode 100644 index 0000000..2a682bb --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson06/roman_numerals/test_roman_to_int.py @@ -0,0 +1,63 @@ +import unittest + +from roman_to_int import RomanToInt + + +class TestRomanToInteger(unittest.TestCase): + + # singles + def test_single_I(self): + self.assertEqual(RomanToInt.convert('I'), 1) + + def test_single_V(self): + self.assertEqual(RomanToInt.convert('V'), 5) + + def test_single_X(self): + self.assertEqual(RomanToInt.convert('X'), 10) + + def test_single_L(self): + self.assertEqual(RomanToInt.convert('L'), 50) + + def test_single_C(self): + self.assertEqual(RomanToInt.convert('C'), 100) + + def test_single_D(self): + self.assertEqual(RomanToInt.convert('D'), 500) + + def test_single_M(self): + self.assertEqual(RomanToInt.convert('M'), 1000) + + + # composite examples + def test_composite_LX(self): + self.assertEqual(RomanToInt.convert('LX'), 60) + + def test_composite_LXV(self): + self.assertEqual(RomanToInt.convert('LXV'), 65) + + def test_composite_MMMD(self): + self.assertEqual(RomanToInt.convert('MMMD'), 3500) + + + + # inputs + def test_valid(self): + self.value = ('I', 'V', 'X', 'L', 'C', 'D', 'M') + + for iv in self.value: + assert RomanToInt.value_of(iv) is not ValueError('''Provided character must be one of: I V X L C D M.''') + + + """ + + All tests passed: + + Tammys-MBP:roman_numerals tammydo$ python -m unittest test_roman_to_int.py + ........... + ---------------------------------------------------------------------- + Ran 11 tests in 0.003s + + OK + Tammys-MBP:roman_numerals tammydo$ + + """ From f396d3642800996b831386ab578c38def4374ef7 Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Mon, 9 Jul 2018 16:23:33 -0700 Subject: [PATCH 09/15] commit assignment07 and activity07 --- .../use_these/personjob.db | 0 .../use_these/personjob_learning_v3_p1.py | 64 + .../use_these/personjob_learning_v5_p1.py | 66 + .../use_these/personjob_model.py | 57 + .../Py220_lesson07/assignment7/mailroom.db | Bin 0 -> 20480 bytes .../assignment7/mailroom_model.py | 60 + .../Py220_lesson07/assignment7/mailroom_oo.py | 312 ++++ .../Py220_lesson07/assignment7/populate_db.py | 118 ++ .../lesson_seven_relational_databases.ipynb | 1293 +++++++++++++++++ 9 files changed, 1970 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob.db create mode 100755 Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_learning_v3_p1.py create mode 100755 Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_learning_v5_p1.py create mode 100755 Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_model.py create mode 100644 Student/tammyd_Py220/Py220_lesson07/assignment7/mailroom.db create mode 100644 Student/tammyd_Py220/Py220_lesson07/assignment7/mailroom_model.py create mode 100644 Student/tammyd_Py220/Py220_lesson07/assignment7/mailroom_oo.py create mode 100644 Student/tammyd_Py220/Py220_lesson07/assignment7/populate_db.py create mode 100644 Student/tammyd_Py220/Py220_lesson07/lesson_seven_relational_databases.ipynb diff --git a/Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob.db b/Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob.db new file mode 100644 index 0000000..e69de29 diff --git a/Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_learning_v3_p1.py b/Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_learning_v3_p1.py new file mode 100755 index 0000000..f2c4fff --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_learning_v3_p1.py @@ -0,0 +1,64 @@ +""" + Learning persistence with Peewee and sqlite + delete the database to start over + (but running this program does not require it) +""" +import logging +from personjob_model import * + +def populate_db(): + """ + add person data to database + """ + + logging.basicConfig(level=logging.INFO) + logger = logging.getLogger(__name__) + + database = SqliteDatabase('personjob.db') + + logger.info('Working with Person class') + logger.info('Note how I use constants and a list of tuples as a simple schema') + logger.info('Normally you probably will have prompted for this from a user') + + dept_number = 0 + dept_name = 1 + dept_manager = 2 + + department = [ + ('A001', 'Comms', 'Andy'), + ('B002', 'Marketing', 'Tammy'), + ('C003', 'Fancy', 'Beannie'), + ] + + logger.info('Creating Person records: iterate through the list of tuples') + logger.info('Prepare to explain any errors with exceptions') + logger.info('and the transaction tells the database to fail on error') + + try: + database.connect() + database.execute_sql('PRAGMA foreign_keys = ON;') + for department in department: + with database.transaction(): + new_dept = Department.create( + dept_number = department[dept_number], + dept_name = department[dept_name], + dept_manager = department[dept_manager]) + new_dept.save() + logger.info('Database add successful') + + logger.info('Print the Department records we saved...') + for saved_dept in Department: + logger.info(f'{saved_dept.dept_number} department is for {saved_dept.dept_name} ' +\ + f'and likes to be known as {saved_dept.dept_manager}') + + except Exception as e: + logger.info(f'Error creating = {department[dept_number]}') + logger.info(e) + logger.info('See how the database protects our data') + + finally: + logger.info('database closes') + database.close() + +if __name__ == '__main__': + populate_db() \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_learning_v5_p1.py b/Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_learning_v5_p1.py new file mode 100755 index 0000000..cb7e11b --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_learning_v5_p1.py @@ -0,0 +1,66 @@ +""" + Learning persistence with Peewee and sqlite + delete the database to start over + (but running this program does not require it) +""" + +from personjob_model import * + +import logging + +def populate_db(): + """ + add job data to database + """ + + logging.basicConfig(level=logging.INFO) + logger = logging.getLogger(__name__) + + database = SqliteDatabase('personjob.db') + + logger.info('Working with Job class') + logger.info('Creating Job records: just like Person. We use the foreign key') + + JOB_NAME = 0 + START_DATE = 1 + END_DATE = 2 + SALARY = 3 + PERSON_EMPLOYED = 4 + DEPT_NUMBER = 5 + + jobs = [ + ('Analyst', '2001-09-22', '2003-01-30',65500, 'Andrew', 'A001'), + ('Senior analyst', '2003-02-01', '2006-10-22', 70000, 'Andrew', 'A001'), + ('Senior business analyst', '2006-10-23', '2016-12-24', 80000, 'Andrew', 'A001'), + ('Admin supervisor', '2012-10-01', '2014-11,10', 45900, 'Peter', 'B002'), + ('Admin manager', '2014-11-14', '2018-01,05', 45900, 'Peter', 'B002') + ] + + try: + database.connect() + database.execute_sql('PRAGMA foreign_keys = ON;') + for job in jobs: + with database.transaction(): + new_job = Job.create( + job_name = job[JOB_NAME], + start_date = job[START_DATE], + end_date = job[END_DATE], + salary = job[SALARY], + person_employed = job[PERSON_EMPLOYED], + dept_number = job[DEPT_NUMBER]) + new_job.save() + + logger.info('Reading and print all Job rows (note the value of person)...') + for job in Job: + logger.info(f'{job.job_name} : {job.start_date} to {job.end_date} for {job.person_employed}') + + except Exception as e: + logger.info(f'Error creating = {job[JOB_NAME]}') + logger.info(e) + + finally: + logger.info('database closes') + database.close() + +if __name__ == '__main__': + populate_db() \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_model.py b/Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_model.py new file mode 100755 index 0000000..b3cf07a --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson07/RDBMS-example-master/use_these/personjob_model.py @@ -0,0 +1,57 @@ +""" + Simple database examle with Peewee ORM, sqlite and Python + Here we define the schema + +""" + +from peewee import * + +database = SqliteDatabase('personjob.db') +database.connect() +database.execute_sql('PRAGMA foreign_keys = ON;') + +class BaseModel(Model): + class Meta: + database = database + + +class Person(BaseModel): + """ + This class defines Person, which maintains details of someone + for whom we want to research career to date. + """ + person_name = CharField(primary_key = True, max_length = 30) + lives_in_town = CharField(max_length = 40) + nickname = CharField(max_length = 20, null = True) + + +class Dept(BaseModel): + """ + This class defines department. + """ + dept_number = CharField(primary_key = True, max_length = 4) + dept_name = CharField(max_length = 30) + dept_manager = CharField(max_length = 30) + + +class Job(BaseModel): + """ + This class defines Job, which maintains details of past Jobs + held by a Person. + """ + job_name = CharField(primary_key = True, max_length = 30) + start_date = DateField(formats = 'YYYY-MM-DD') + end_date = DateField(formats = 'YYYY-MM-DD') + salary = DecimalField(max_digits = 7, decimal_places = 2) + person_employed = ForeignKeyField(Person, related_name='was_filled_by', null = False) + +class PersonNumKey(BaseModel): + """ + This class defines Person, which maintains details of someone + for whom we want to research career to date. + + *** I am implemented with a numeric PK that is generated by the system *** + """ + person_name = CharField(max_length = 30) + lives_in_town = CharField(max_length = 40) + nickname = CharField(max_length = 20, null = True) diff --git a/Student/tammyd_Py220/Py220_lesson07/assignment7/mailroom.db b/Student/tammyd_Py220/Py220_lesson07/assignment7/mailroom.db new file mode 100644 index 0000000000000000000000000000000000000000..11e3641228f1966c27f41ee98682089dd8b47934 GIT binary patch literal 20480 zcmeI%!EVzq7{GC7?I=Pj-7TtwR4b=OOlV^dFhb{ziYx`MAa)@NY7r4@BAQI%T6iJe zgFDZ{5hrW1z!)b^)!$N*&xxJS{y7&bXD|IYpUd~@auMb7KKQQLbS}WZH}rG z^>$S;SE~`<7PiEr2j9BApQ7FUA$lKs-|v4g0R;gB5I_I{1Q0*~0R#|0;6DkhdhL#V zIxj)?B+m(;qx?8iU$$f3$$k(18J@fSNV6WNyc%s$# zBq-ASV|r4nW2IFvQfK8@(q*>RSZ8ot_pQ~j`+aL=R|2L{IfQKM#@uiA|LgFY2=2qJ zJN9AU66KO-pDxV4K8!B&w5(sPM;7j1Wi0mccZ-j$Tby=^69oYT5I_I{1Q0*~0R#|0 z009IxRp4GRG4}tPy1dK_0R#|0009ILKmY**5I_KdQh@*ed ''')) + return action.strip() + + +def send_thank_you(): + """ + Record a donation and generate a thank you message. + """ + # Read a valid donor to send a thank you from, handling special commands to + # let the user navigate as defined. + while True: + name = input("Enter a donor's name" + "(or 'list' to see all donors or 'menu' to exit)> ").strip() + if name == "list": + print(db.list_donors()) + elif name == "menu": + return + else: + break + + # Now prompt the user for a donation amount to apply. Since this is + # also an exit point to the main menu, we want to make sure this is + # done before mutating the db. + while True: + amount_str = input("Enter a donation amount (or 'menu' to exit)> ").strip() + if amount_str == "menu": + return + # Make sure amount is a valid amount before leaving the input loop + try: + amount = float(amount_str) + # extra check here -- unlikely that someone will type "NaN", but + # it IS possible, and it is a valid floating point number: + # http://en.wikipedia.org/wiki/NaN + if math.isnan(amount) or math.isinf(amount) or round(amount, 2) == 0.00: + raise ValueError + # in this case, the ValueError could be raised by the float() call, or by the NaN-check + except ValueError: + print("error: donation amount is invalid\n") + else: + break + + # If this is a new user, ensure that the database has the necessary + # data structure. + donor = db.find_donor(name) + if donor is None: + donor = db.add_donor(name) + + # Record the donation + donor.add_donation(amount) + print(db.gen_letter(donor)) + + +def print_donor_report(): + print(db.generate_donor_report()) + + +def quit(): + sys.exit(0) + + +def main(): + selection_dict = {"1": send_thank_you, + "2": print_donor_report, + "3": db.save_letters_to_disk, + "4": quit} + + while True: + selection = main_menu_selection() + try: + selection_dict[selection]() + except KeyError: + print("error: menu selection is invalid!") + +if __name__ == "__main__": + + main() \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson07/assignment7/populate_db.py b/Student/tammyd_Py220/Py220_lesson07/assignment7/populate_db.py new file mode 100644 index 0000000..bc04ab0 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson07/assignment7/populate_db.py @@ -0,0 +1,118 @@ +#populate_db.py + +""" +Create, read, and delete data from the database, using the Donors class and Donations class + +""" + + + +import logging +from peewee import * +from mailroom_model import * +# can't figure out why Donors class is not being imported. I tried renaming the file, importing classes individually, and importing mailroom on it's own first (followed by "from mailroom_model import Donors"). +# Only "from mailroom_model import *" does not give traceback. +# from mailroom_model import Donors, Donations +# Even though it is not importing, the try/except successfully handles the error + +def populate_donors_db(): + logging.basicConfig(level=logging.INFO) + logger = logging.getLogger(__name__) + + # tell peewee what database we'll use + database = SqliteDatabase('mailroom.db') + + + + D_ID = 0 # donor_id + D_NAME = 1 # donor_name + D_CITY = 2 # donor_city + D_PHONE = 3 # donor_phone + + + people = [ + ("D001", "Britney Spears", "Los Angeles", "222-222-2222"), + ("D002", "Mandy Moore", "Portland", "333-333-3333"), + ("D003", "Christina Aguilera", "Miami", "444-444-4444"), + ("D004", "Queen Bey", "Houston", "555-555-5555") + ] + + logger.info('Populating Donor Class') + + + try: + database.connect() + database.execute_sql('PRAGMA foreign_keys = ON;') + for person in people: + with database.transaction(): + new_donor = Donors.create( + donor_id = person[D_ID], + donor_name = person[D_NAME], + donor_city = person[D_CITY], + donor_phone = person[D_PHONE] + ) + new_donor.save() + logger.info('Database add successful') + + logger.info('Print the Person records we saved...') + for saved_person in Donors: + logger.info(f'{saved_person.donor_name} lives in {saved_person.donor_city}' +\ + f'and has the phone number {saved_person.donor_phone}') + + except Exception as e: + logger.info(f'Error creating = {person[D_NAME]}') + logger.info(e) + logger.info('The database is protecting data') + + finally: + logger.info('database closes') + database.close() + + +def populate_donations_db(): + + logging.basicConfig(level=logging.INFO) + logger = logging.getLogger(__name__) + + database = SqliteDatabase('mailroom.db') + + donations = [ + (653772.32, '2018-01-01', 'D001'), + (877.33, '2018-02-02', 'D002'), + (663.23, '2018-03-03','D003'), + (1663.23, '2018-04-04', 'D004') + ] + + logger.info('Donations add successful') + + DONATION_AMOUNT = 0 + DONATION_DATE = 1 + DONATION_DONOR_ID = 2 + + + try: + database.connect() + database.execute_sql('PRAGMA foreign_keys = ON;') + for donation in donations: + with database.transaction(): + new_donation = Donations.create( + donation_amount = donation[DONATION_AMOUNT], + donation_donor_name = donation[DONATION_DATE], + donation_donor_id =[DONATION_DONOR_ID] + ) + new_donation.save() + logger.info('Database add successful') + + + except Exception as e: + logger.info(f'Error creating = {donation[DONATION_AMOUNT]} at donation date of {donation[DONATION_DATE]}.') + logger.info(e) + logger.info('The database is protecting data') + + finally: + logger.info('database closes') + database.close() + + +#if __name__ == "__main__": +# populate_donors_db() \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson07/lesson_seven_relational_databases.ipynb b/Student/tammyd_Py220/Py220_lesson07/lesson_seven_relational_databases.ipynb new file mode 100644 index 0000000..cc59fce --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson07/lesson_seven_relational_databases.ipynb @@ -0,0 +1,1293 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Preface: ORM or not?\n", + "\n", + "https://www.quora.com/What-are-the-pros-and-cons-of-using-raw-SQL-versus-ORM-for-database-development\n", + "\n", + "https://www.quora.com/Which-is-better-ORM-or-Plain-SQL\n", + "\n", + "http://mikehadlow.blogspot.com/2012/06/when-should-i-use-orm.html\n", + "\n", + "https://enterprisecraftsmanship.com/2015/11/30/do-you-need-an-orm/\n", + "\n", + "https://medium.com/@mithunsasidharan/should-i-or-should-i-not-use-orm-4c3742a639ce\n", + "\n", + "https://xkcd.com/1409/\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
🐍
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "

Relational Databases

\n", + "
\n", + "

Introduction

\n", + "

In this lesson we are going to look at how to use a relational database with Python. Using relational databases is a massive subject in its own right, but we are going to concentrate on how to use these technologies simply and effectively.

\n", + "

What we learn here will be a foundation on which you can build as your database needs increase in volume and complexity.

\n", + "

Learning Objectives

\n", + "

Upon successful completion of this lesson, you will be able to:

\n", + "
    \n", + "
  • Apply data definition techniques to help assure the quality of the data your Python programs use.
  • \n", + "
  • Store and retrieve single and multiple sets of records in a database from your Python programs so that you can leverage data management services from a database.
  • \n", + "
  • Use simple techniques to help model data correctly in a relational database, and recognize the tradeoffs between different options for this. 
  • \n", + "
\n", + "

New Words, Concepts, and Tools

\n", + "
    \n", + "
  • We are going to learn about relational databases, data definition and management, and SQL. We will cover object relational mapping and relational database design, but all aligned to simplicity of use with Python. 
  • \n", + "
\n", + "

Required Reading

\n", + "\n", + "

Optional Reading

\n", + "
    \n", + "
  • How to interact with sqlite from Python (does not use Peewee)
  • \n", + "
  • How to interact with PostgreSQL from Python.
  • \n", + "
  • A great reference book for SQL that shows details of SQL for several databases is \"SQL in a Nutshell: A Desktop Quick Reference Guide\"
  • \n", + "
  • \n", + "

    If you really want to understand the details of SQL, then this is an excellent book: \"Joe Celko's SQL Programming Style (The Morgan Kaufmann Series in Data Management Systems)\"

    \n", + "
  • \n", + "
  • Data model design is a complex topic that requires lots of knowledge. If you do a lot of database work then the three books in the series \"The Data Model Resource Book\" (Vol. 1, 2 and 3) are invaluable (the links are the numbers).
  • \n", + "
\n", + "

\n", + "\n", + "\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "

Relational Databases

\n", + "
\n", + "

Here we are going to cover the background to why we use databases, and set the stage for later, when we will start to\n", + " develop a Python database application.

\n", + "

You will probably wish to clone the repository you can find on\n", + " GitHub. For this first video, the files are in the \"stuff\" directory. These are the files we refer to, and they\n", + " are included here, below the video:

\n", + "\n", + "

 

\n", + "

Video 1: Relational Databases with Python

\n", + "\n", + "\n", + "

simple_data_write.py

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "\"\"\"\n", + "write a csv file\n", + "data is \"anonymous\" (no schema)\n", + "\n", + "Creates a file that looks like this:\n", + "\n", + "John,502-77-3056,2/27/1985,117.45\n", + "\n", + "\"\"\"\n", + "\n", + "import csv\n", + "\n", + "peopledata = ['John', '502-77-3056', '2/27/1985', 117.45]\n", + "\n", + "with open('simple_data_write.csv', 'w') as people:\n", + " peoplewriter = csv.writer(people, quotechar=\"'\", quoting=csv.QUOTE_ALL)\n", + " peoplewriter.writerow(peopledata)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```\n", + "'John','502-77-3056','2/27/1985','117.45'\n", + "```\n", + "

\n", + "

simple_data_write_headers.py

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "\"\"\"\n", + "write a csv file\n", + "data is \"anonymous\" (no schema)\n", + "\n", + "Creates a file that looks like this:\n", + "\n", + "John,502-77-3056,2/27/1985,117.45\n", + "\n", + "\"\"\"\n", + "\n", + "import csv\n", + "\n", + "people_headers = ['Person Name','SSN','BirthDate','Account Balance']\n", + "people_data = [ \n", + " ['John', '502-77-3056', '2/27/1985', 117.45],\n", + " ['Jane', '756-01-5323', '12/01/1983', 120.9], \n", + "]\n", + "\n", + "with open('simple_data_write_headers.tsv', 'w') as people:\n", + " peoplewriter = csv.writer(people, delimiter='|', quoting=csv.QUOTE_NONNUMERIC)\n", + " peoplewriter.writerow(people_headers)\n", + " for person in people_data:\n", + " peoplewriter.writerow(person)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "```\n", + "\"Person Name\"|\"SSN\"|\"BirthDate\"|\"Account Balance\"\n", + "\"John\"|\"502-77-3056\"|\"2/27/1985\"|\"117.45\"\n", + "\"Jane\"|\"756-01-5323\"|\"12/01/1983\"|\"120.9\"\n", + "\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

 

\n", + "

We have covered the basis of data definition, and why it is important. We now know what a schema is and why it is important.\n", + " Now we can start to write a Python program that uses a database.

\n", + "

 

\n", + "

\n", + " Be sure you cloned the repository we mentioned prior to video 1 from \n", + " GitHub\n", + " . In this video we will be using the modules in the \"src\" directory We start with \n", + " v00_personjob_model.py\n", + "

\n", + "

Key fragments are included here too, below the video.

\n", + "\n", + "\n", + "

Video 2: Using the Model, Using the Person Class, Using the Job Class

\n", + "\n", + "

 Here is the model code:

\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\"\n", + " Simple database example with Peewee ORM, sqlite and Python\n", + " Here we define the schema\n", + " Use logging for messages so they can be turned off\n", + "\"\"\"\n", + "\n", + "import logging\n", + "from peewee import *\n", + "\n", + "logging.basicConfig(level=logging.INFO)\n", + "logger = logging.getLogger(__name__)\n", + "\n", + "logger.info('One off program to build the classes from the model in the database')\n", + "\n", + "logger.info('Here we define our data (the schema)')\n", + "logger.info('First name and connect to a database (sqlite here)')\n", + "\n", + "logger.info('The next 3 lines of code are the only database specific code')\n", + "\n", + "database = SqliteDatabase('personjob.db')\n", + "database.connect()\n", + "database.execute_sql('PRAGMA foreign_keys = ON;') # needed for sqlite only\n", + "\n", + "logger.info('This means we can easily switch to a different database')\n", + "logger.info('Enable the Peewee magic! This base class does it all')\n", + "logger.info('By inheritance only we keep our model (almost) technology neutral')\n", + "\n", + "class BaseModel(Model):\n", + " class Meta:\n", + " database = database\n", + "\n", + "class Person(BaseModel):\n", + " \"\"\"\n", + " This class defines Person, which maintains details of someone\n", + " for whom we want to research career to date.\n", + " \"\"\"\n", + "\n", + " logger.info('Note how we defined the class')\n", + "\n", + " logger.info('Specify the fields in our model, their lengths and if mandatory')\n", + " logger.info('Must be a unique identifier for each person')\n", + "\n", + " person_name = CharField(primary_key = True, max_length = 30)\n", + " lives_in_town = CharField(max_length = 40)\n", + " nickname = CharField(max_length = 20, null = True)\n", + "\n", + "class Job(BaseModel):\n", + " \"\"\"\n", + " This class defines Job, which maintains details of past Jobs\n", + " held by a Person.\n", + " \"\"\"\n", + "\n", + " logger.info('Now the Job class with a simlar approach')\n", + " job_name = CharField(primary_key = True, max_length = 30)\n", + " logger.info('Dates')\n", + " start_date = DateField(formats = 'YYYY-MM-DD')\n", + " end_date = DateField(formats = 'YYYY-MM-DD')\n", + " logger.info('Number')\n", + "\n", + " salary = DecimalField(max_digits = 7, decimal_places = 2)\n", + " logger.info('Which person had the Job')\n", + " person_employed = ForeignKeyField(Person, related_name='was_filled_by', null = False)\n", + "\n", + "class PersonNumKey(BaseModel):\n", + " \"\"\"\n", + " This class defines Person, which maintains details of someone\n", + " for whom we want to research career to date.\n", + " \"\"\"\n", + "\n", + " logger.info('An alternate Person class')\n", + " logger.info(\"Note: no primary key so we're give one 'for free'\")\n", + "\n", + " person_name = CharField(max_length = 30)\n", + " lives_in_town = CharField(max_length = 40)\n", + " nickname = CharField(max_length = 20, null = True)\n", + "\n", + "database.create_tables([\n", + " Job,\n", + " Person,\n", + " PersonNumKey\n", + " ])\n", + "\n", + "database.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "

 

\n", + "

Now we have looked at the model, lets look at how we create, read, and delete data from the database, using the Person class. Here\n", + " we use the following code:\n", + "  \n", + " v3_p1_populate_db.py, then \n", + " v3_p1_populate_db.py and finally \n", + " v3_p3_add_and_delete.py\n", + " .

\n", + "

Video 3: Using the Person class

\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# https://raw.githubusercontent.com/milesak60/RDBMS-example/master/personjob_learning_v3_p1.py\n", + "\"\"\"\n", + " Learning persistence with Peewee and sqlite\n", + " delete the database to start over\n", + " (but running this program does not require it)\n", + "\"\"\"\n", + "import logging\n", + "# from personjob_model import *\n", + "\n", + "def populate_db():\n", + " \"\"\"\n", + " add person data to database\n", + " \"\"\"\n", + "\n", + " logging.basicConfig(level=logging.INFO)\n", + " logger = logging.getLogger(__name__)\n", + "\n", + " database = SqliteDatabase('personjob.db')\n", + "\n", + " logger.info('Working with Person class')\n", + " logger.info('Note how I use constants and a list of tuples as a simple schema')\n", + " logger.info('Normally you probably will have prompted for this from a user')\n", + "\n", + " PERSON_NAME = 0\n", + " LIVES_IN_TOWN = 1\n", + " NICKNAME = 2\n", + "\n", + " people = [\n", + " ('Andrew', 'Sumner', 'Andy'),\n", + " ('Peter', 'Seattle', None),\n", + " ('Susan', 'Boston', 'Beannie'),\n", + " ('Pam', 'Coventry', 'PJ'),\n", + " ('Steven', 'Colchester', None),\n", + " ]\n", + "\n", + " logger.info('Creating Person records: iterate through the list of tuples')\n", + " logger.info('Prepare to explain any errors with exceptions')\n", + " logger.info('and the transaction tells the database to fail on error')\n", + "\n", + " try:\n", + " database.connect()\n", + " database.execute_sql('PRAGMA foreign_keys = ON;')\n", + " for person in people:\n", + " with database.transaction():\n", + " new_person = Person.create(\n", + " person_name = person[PERSON_NAME],\n", + " lives_in_town = person[LIVES_IN_TOWN],\n", + " nickname = person[NICKNAME])\n", + " new_person.save()\n", + " logger.info('Database add successful')\n", + "\n", + " logger.info('Print the Person records we saved...')\n", + " for saved_person in Person:\n", + " logger.info(f'{saved_person.person_name} lives in {saved_person.lives_in_town} ' +\\\n", + " f'and likes to be known as {saved_person.nickname}')\n", + "\n", + " except Exception as e:\n", + " logger.info(f'Error creating = {person[PERSON_NAME]}')\n", + " logger.info(e)\n", + " logger.info('See how the database protects our data')\n", + "\n", + " finally:\n", + " logger.info('database closes')\n", + " database.close()\n", + "\n", + "populate_db()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# https://raw.githubusercontent.com/milesak60/RDBMS-example/master/personjob_learning_v3_p2.py\n", + "\"\"\"\n", + " Learning persistence with Peewee and sqlite\n", + " delete the database to start over\n", + " (but running this program does not require it)\n", + "\"\"\"\n", + "\n", + "# from personjob_model import *\n", + "\n", + "import logging\n", + "\n", + "def select_and_update():\n", + " \"\"\"\"\n", + " show how we can select a specific record, and then search and read through several records\n", + " \"\"\"\n", + "\n", + " logging.basicConfig(level=logging.INFO)\n", + " logger = logging.getLogger(__name__)\n", + "\n", + " database = SqliteDatabase('personjob.db')\n", + "\n", + " try:\n", + " database.connect()\n", + " database.execute_sql('PRAGMA foreign_keys = ON;')\n", + "\n", + " logger.info('Find and display by selecting a spcific Person name...')\n", + " aperson = Person.get(Person.person_name == 'Susan')\n", + "\n", + " logger.info(f'{aperson.person_name} lives in {aperson.lives_in_town} ' + \\\n", + " f' and likes to be known as {aperson.nickname}')\n", + "\n", + " logger.info('Search and display all Person with missing nicknames')\n", + " logger.info('Our person class inherits select(). Specify search with .where()')\n", + " logger.info('Peter gets a nickname but noone else')\n", + "\n", + " for person in Person.select().where(Person.nickname == None):\n", + " logger.info(f'{person.person_name} does not have a nickname; see: {person.nickname}')\n", + " if person.person_name == 'Peter':\n", + " logger.info('Changing nickname for Peter')\n", + " logger.info('Update the database')\n", + " person.nickname = 'Painter'\n", + " person.save()\n", + " else:\n", + " logger.info(f'Not giving a nickname to {person.person_name}')\n", + "\n", + " logger.info('And here is where we prove it by finding Peter and displaying')\n", + " aperson = Person.get(Person.person_name == 'Peter')\n", + " logger.info(f'{aperson.person_name} now has a nickname of {aperson.nickname}')\n", + "\n", + " except Exception as e:\n", + " logger.info(e)\n", + "\n", + " finally:\n", + " database.close()\n", + "\n", + "select_and_update()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# https://raw.githubusercontent.com/milesak60/RDBMS-example/master/personjob_learning_v3_p3.py\n", + "\n", + "\"\"\"\n", + " Learning persistence with Peewee and sqlite\n", + " delete the database to start over\n", + " (but running this program does not require it)\n", + "\"\"\"\n", + "\n", + "import logging\n", + "\n", + "# from personjob_model import *\n", + "\n", + "database = SqliteDatabase('personjob.db')\n", + "\n", + "def add_and_delete():\n", + " \"\"\"\"\n", + " show how we can add a record, and delete a record\n", + " \"\"\"\n", + "\n", + " logging.basicConfig(level=logging.INFO)\n", + " logger = logging.getLogger(__name__)\n", + "\n", + " database = SqliteDatabase('personjob.db')\n", + " try:\n", + " database.connect()\n", + " database.execute_sql('PRAGMA foreign_keys = ON;')\n", + "\n", + " logger.info('Add and display a Person called Fred; then delete him...')\n", + " logger.info('Add Fred in one step')\n", + "\n", + " new_person = Person.create(\n", + " person_name = 'Fred',\n", + " lives_in_town = 'Seattle',\n", + " nickname = 'Fearless')\n", + " new_person.save()\n", + "\n", + " logger.info('Show Fred')\n", + " aperson = Person.get(Person.person_name == 'Fred')\n", + "\n", + " logger.info(f'We just created {aperson.person_name}, who lives in {aperson.lives_in_town}')\n", + " logger.info('but now we will delete him...')\n", + "\n", + " aperson.delete_instance()\n", + "\n", + " logger.info('Reading and print all Person records (but not Fred; he has been deleted)...')\n", + "\n", + " for person in Person:\n", + " logger.info(f'{person.person_name} lives in {person.lives_in_town} and likes to be known as {person.nickname}')\n", + "\n", + " except Exception as e:\n", + " logger.info(e)\n", + "\n", + " finally:\n", + " database.close()\n", + "\n", + "add_and_delete()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "

 

\n", + "

Working with one class is not typical. Usually we will have several. We'll illustrate this by working with the Job class.\n", + " He we will use all the Python modules for the repository that start with v4:

\n", + "

Video 4: Using the Job class

\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# https://github.com/milesak60/RDBMS-example/blob/master/personjob_learning_v5_p1.py\n", + "\n", + "\"\"\"\n", + " Learning persistence with Peewee and sqlite\n", + " delete the database to start over\n", + " (but running this program does not require it)\n", + "\"\"\"\n", + "\n", + "# from personjob_model import *\n", + "\n", + "import logging\n", + "\n", + "def populate_db():\n", + " \"\"\"\n", + " add job data to database\n", + " \"\"\"\n", + "\n", + " logging.basicConfig(level=logging.INFO)\n", + " logger = logging.getLogger(__name__)\n", + "\n", + " database = SqliteDatabase('personjob.db')\n", + "\n", + " logger.info('Working with Job class')\n", + " logger.info('Creating Job records: just like Person. We use the foreign key')\n", + "\n", + " JOB_NAME = 0\n", + " START_DATE = 1\n", + " END_DATE = 2\n", + " SALARY = 3\n", + " PERSON_EMPLOYED = 4\n", + "\n", + " jobs = [\n", + " ('Analyst', '2001-09-22', '2003-01-30',65500, 'Andrew'),\n", + " ('Senior analyst', '2003-02-01', '2006-10-22', 70000, 'Andrew'),\n", + " ('Senior business analyst', '2006-10-23', '2016-12-24', 80000, 'Andrew'),\n", + " ('Admin supervisor', '2012-10-01', '2014-11,10', 45900, 'Peter'),\n", + " ('Admin manager', '2014-11-14', '2018-01,05', 45900, 'Peter')\n", + " ]\n", + "\n", + " try:\n", + " database.connect()\n", + " database.execute_sql('PRAGMA foreign_keys = ON;')\n", + " for job in jobs:\n", + " with database.transaction():\n", + " new_job = Job.create(\n", + " job_name = job[JOB_NAME],\n", + " start_date = job[START_DATE],\n", + " end_date = job[END_DATE],\n", + " salary = job[SALARY],\n", + " person_employed = job[PERSON_EMPLOYED])\n", + " new_job.save()\n", + "\n", + " logger.info('Reading and print all Job rows (note the value of person)...')\n", + " for job in Job:\n", + " logger.info(f'{job.job_name} : {job.start_date} to {job.end_date} for {job.person_employed}')\n", + "\n", + " except Exception as e:\n", + " logger.info(f'Error creating = {job[JOB_NAME]}')\n", + " logger.info(e)\n", + "\n", + " finally:\n", + " logger.info('database closes')\n", + " database.close()\n", + "\n", + "populate_db()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# https://raw.githubusercontent.com/milesak60/RDBMS-example/master/personjob_learning_v5_p2.py\n", + "\n", + "\"\"\"\n", + " Learning persistence with Peewee and sqlite\n", + " delete the database to start over\n", + " (but running this program does not require it)\n", + "\"\"\"\n", + "\n", + "def join_classes():\n", + " \"\"\"\n", + " demonstrate how to join classes together : matches\n", + " \"\"\"\n", + "\n", + " logging.basicConfig(level=logging.INFO)\n", + " logger = logging.getLogger(__name__)\n", + "\n", + " database = SqliteDatabase('personjob.db')\n", + "\n", + " logger.info('Working with Job class')\n", + "\n", + " logger.info('Now resolve the join and print (INNER shows only jobs that match person)...')\n", + " logger.info('Notice how we use a query variable in this case')\n", + " logger.info('We select the classes we need, and we join Person to Job')\n", + " logger.info('Inner join (which is the default) shows only records that match')\n", + "\n", + " try:\n", + " database.connect()\n", + " database.execute_sql('PRAGMA foreign_keys = ON;')\n", + " query = (Person\n", + " .select(Person, Job)\n", + " .join(Job, JOIN.INNER)\n", + " )\n", + "\n", + " logger.info('View matching records from both tables')\n", + " for person in query:\n", + " logger.info(f'Person {person.person_name} had job {person.job.job_name}')\n", + "\n", + " except Exception as e:\n", + " logger.info(f'Error creating = {job[JOB_NAME]}')\n", + " logger.info(e)\n", + "\n", + " finally:\n", + " logger.info('database closes')\n", + " database.close()\n", + "\n", + "join_classes()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# https://raw.githubusercontent.com/milesak60/RDBMS-example/master/personjob_learning_v5_p3.py\n", + "\n", + "\n", + "\"\"\"\n", + " Learning persistence with Peewee and sqlite\n", + " delete the database to start over\n", + " (but running this program does not require it)\n", + "\"\"\"\n", + "\n", + "def join_classes():\n", + " \"\"\"\n", + " demonstrate how to join classes together : no matches too\n", + " \"\"\"\n", + "\n", + " logging.basicConfig(level=logging.INFO)\n", + " logger = logging.getLogger(__name__)\n", + "\n", + " database = SqliteDatabase('personjob.db')\n", + "\n", + " logger.info('View matching records and Persons without Jobs (note LEFT_OUTER)')\n", + "\n", + " try:\n", + " database.connect()\n", + " database.execute_sql('PRAGMA foreign_keys = ON;')\n", + " query = (Person\n", + " .select(Person, Job)\n", + " .join(Job, JOIN.LEFT_OUTER)\n", + " )\n", + "\n", + " for person in query:\n", + " try:\n", + " logger.info(f'Person {person.person_name} had job {person.job.job_name}')\n", + "\n", + " except Exception as e:\n", + " logger.info(f'Person {person.person_name} had no job')\n", + "\n", + "\n", + " logger.info('Example of how to summarize data')\n", + " logger.info('Note select() creates a count and names it job_count')\n", + " logger.info('group_by and order_by control level and sorting')\n", + "\n", + " query = (Person\n", + " .select(Person, fn.COUNT(Job.job_name).alias('job_count'))\n", + " .join(Job, JOIN.LEFT_OUTER)\n", + " .group_by(Person)\n", + " .order_by(Person.person_name))\n", + "\n", + " for person in query:\n", + " logger.info(f'{person.person_name} had {person.job_count} jobs')\n", + "\n", + "\n", + " except Exception as e:\n", + " logger.info(e)\n", + "\n", + " finally:\n", + " database.close()\n", + "\n", + "join_classes()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# https://raw.githubusercontent.com/milesak60/RDBMS-example/master/personjob_learning_v5_p4.py\n", + "\"\"\"\n", + " Learning persistence with Peewee and sqlite\n", + " delete the database to start over\n", + " (but running this program does not require it)\n", + "\"\"\"\n", + "\n", + "def show_integrity_add():\n", + " \"\"\"\n", + " demonstrate how database protects data inegrity : add\n", + " \"\"\"\n", + "\n", + " logging.basicConfig(level=logging.INFO)\n", + " logger = logging.getLogger(__name__)\n", + "\n", + " database = SqliteDatabase('personjob.db')\n", + "\n", + " try:\n", + " database.connect()\n", + " database.execute_sql('PRAGMA foreign_keys = ON;')\n", + " with database.transaction():\n", + " logger.info('Try to add a new job where a person doesnt exist...')\n", + "\n", + " addjob = ('Sales', '2010-04-01', '2018-02-08', 80400, 'Harry')\n", + "\n", + " logger.info('Adding a sales job for Harry')\n", + " logger.info(addjob)\n", + " new_job = Job.create(\n", + " job_name = addjob[JOB_NAME],\n", + " start_date = addjob[START_DATE],\n", + " end_date = addjob[END_DATE],\n", + " salary = addjob[SALARY],\n", + " person_employed = addjob[PERSON_EMPLOYED])\n", + " new_job.save()\n", + "\n", + " except Exception as e:\n", + " logger.info('Add failed because Harry is not in Person')\n", + " logger.info(f'For Job create: {addjob[0]}')\n", + " logger.info(e)\n", + "\n", + "show_integrity_add()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# https://raw.githubusercontent.com/milesak60/RDBMS-example/master/personjob_learning_v5_p5.py\n", + "\"\"\"\n", + " Learning persistence with Peewee and sqlite\n", + " delete the database to start over\n", + " (but running this program does not require it)\n", + "\"\"\"\n", + "\n", + "def show_integrity_del():\n", + " \"\"\"\n", + " demonstrate how database protects data inegrity : delete\n", + " \"\"\"\n", + " logging.basicConfig(level=logging.INFO)\n", + " logger = logging.getLogger(__name__)\n", + "\n", + " database = SqliteDatabase('personjob.db')\n", + "\n", + " try:\n", + " database.connect()\n", + " database.execute_sql('PRAGMA foreign_keys = ON;')\n", + " logger.info('Try to Delete a person who has jobs...')\n", + " with database.transaction():\n", + " aperson = Person.get(Person.person_name == 'Andrew')\n", + " logger.info(f'Trying to delete {aperson.person_name} who lives in {aperson.lives_in_town}')\n", + " aperson.delete_instance()\n", + "\n", + " except Exception as e:\n", + " logger.info('Delete failed because Andrew has Jobs')\n", + " logger.info(f'Delete failed: {aperson.person_name}')\n", + " logger.info(e)\n", + "\n", + " finally:\n", + " database.close()\n", + " \n", + "show_integrity_del()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# https://raw.githubusercontent.com/milesak60/RDBMS-example/master/personjob_learning_v5_p6.py\n", + "\"\"\"\n", + " Learning persistence with Peewee and sqlite\n", + " delete the database to start over\n", + " (but running this program does not require it)\n", + "\"\"\"\n", + "\n", + "def add_with_without_BK():\n", + " \"\"\"\n", + " demonstrate impact of business keys\n", + " \"\"\"\n", + "\n", + " PERSON_NAME = 0\n", + " LIVES_IN_TOWN = 1\n", + " NICKNAME = 2\n", + " people = [\n", + " ('Andrew', 'Sumner', 'Andy'),\n", + " ('Peter', 'Seattle', None),\n", + " ('Susan', 'Boston', 'Beannie'),\n", + " ('Pam', 'Coventry', 'PJ'),\n", + " ('Steven', 'Colchester', None),\n", + " ]\n", + "\n", + " logging.basicConfig(level=logging.INFO)\n", + " logger = logging.getLogger(__name__)\n", + "\n", + " database = SqliteDatabase('personjob.db')\n", + "\n", + " logger.info('Try creating Person records again: it will fail')\n", + "\n", + " try:\n", + " database.connect()\n", + " database.execute_sql('PRAGMA foreign_keys = ON;')\n", + " try:\n", + " with database.transaction():\n", + " for person in people:\n", + " new_person = Person.create(\n", + " person_name = person[PERSON_NAME],\n", + " lives_in_town = person[LIVES_IN_TOWN],\n", + " nickname = person[NICKNAME])\n", + " new_person.save()\n", + " logger.info('Database add successful')\n", + "\n", + " except Exception as e:\n", + " logger.info(f'Error creating = {person[PERSON_NAME]}')\n", + " logger.info(e)\n", + "\n", + " logger.info('We make sure duplicates are not unintentionally created this way')\n", + " logger.info('BUT: how do we really identify a Person (uniquely)?')\n", + "\n", + " logger.info('Creating Person records, but in a new table with generated PK...')\n", + " try:\n", + " with database.transaction():\n", + " for person in people:\n", + " new_person = PersonNumKey.create(\n", + " person_name = person[PERSON_NAME],\n", + " lives_in_town = person[LIVES_IN_TOWN],\n", + " nickname = person[NICKNAME])\n", + " new_person.save()\n", + "\n", + " except Exception as e:\n", + " logger.info(f'Error creating = {person[0]}')\n", + " logger.info(e)\n", + "\n", + " logger.info('Watch what happens when we do it again')\n", + "\n", + " try:\n", + " with database.transaction():\n", + " for person in people:\n", + " new_person = PersonNumKey.create(\n", + " person_name = person[PERSON_NAME],\n", + " lives_in_town = person[LIVES_IN_TOWN],\n", + " nickname = person[NICKNAME])\n", + " new_person.save()\n", + "\n", + " except Exception as e:\n", + " logger.info(f'Error creating = {person[0]}')\n", + " logger.info(e)\n", + "\n", + " logger.info('Note no PK specified, no PK violation; \"duplicates\" created!')\n", + " for person in PersonNumKey.select():\n", + " logger.info(f'Name : {person.person_name} with id: {person.id}')\n", + "\n", + " except Exception as e:\n", + " logger.info(e)\n", + "\n", + " finally:\n", + " database.close()\n", + "\n", + "add_with_without_BK()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# https://raw.githubusercontent.com/milesak60/RDBMS-example/master/personjob_learning_v5_p7.py\n", + "\"\"\"\n", + " Learning persistence with Peewee and sqlite\n", + " delete the database to start over\n", + " (but running this program does not require it)\n", + "\"\"\"\n", + "\n", + "def cant_change_PK():\n", + " \"\"\"\n", + " show that PKs cant be changed (and that there is no error!)\n", + " \"\"\"\n", + "\n", + " logging.basicConfig(level=logging.INFO)\n", + " logger = logging.getLogger(__name__)\n", + "\n", + " logger.info(\"Back to Person class: try to change Peter's name\")\n", + "\n", + " aperson = Person.get(Person.person_name == 'Peter')\n", + " logger.info(f'Current value is {aperson.person_name}')\n", + "\n", + " logger.info('Update Peter to Peta, thereby trying to change the PK...')\n", + "\n", + " try:\n", + " try:\n", + " with database.transaction():\n", + " aperson = Person.get(Person.person_name == 'Peter')\n", + " aperson.person_name = 'Peta'\n", + " aperson.save()\n", + " logger.info(f'Tried to change Peter to {aperson.person_name}')\n", + "\n", + " except Exception as e:\n", + " logger.info(f'Cant change a PK and caught you trying') # not caught; no error thrown by Peewee\n", + " logger.info(e)\n", + "\n", + " aperson = Person.get(Person.person_name == 'Peter')\n", + " logger.info(f'Looked for Peter: found! -> {aperson.person_name}')\n", + "\n", + " try:\n", + " aperson = Person.get(Person.person_name == 'Peta')\n", + "\n", + " except Exception as e:\n", + " logger.info(f'Looking for Peta results in zero records. PK changes are ignored and do not throw an error!!!!')\n", + " logger.info(f'Cant change a PK')\n", + " logger.info('PK \"change\" can only be achieved with a delete and new create')\n", + "\n", + " finally:\n", + " database.close()\n", + "\n", + "cant_change_PK()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "

 

\n", + "

Now we are going to learn about the best way to design the data in our database.  We will use the digram in the \"stuff\"\n", + " directory, which is also included below, along with the SQL code:

\n", + "

 

\n", + "

Video: Behind the scenes / Database Technologies

\n", + "\n", + "

 

\n", + "

Database diagram:

\n", + "

 \n", + "  

\n", + "

Code samples from the video:

\n", + "

SQL statement

\n", + "
\n", + "
select* from person;\n",
+    "
\n", + "
\n", + "

Start sqlite3 database (from the command line):

\n", + "
\n", + "
sqlite3 personjob.db\n",
+    "
\n", + "
\n", + "

The sqlite> prompt indicates we are ready to enter sqlite commands.

\n", + "
\n", + "
sqlite> .tables\n",
+    "job person personnumkey\n",
+    "
\n", + "
\n", + "

  Here is how sqlite sees the schema:

\n", + "
\n", + "
sqlite> .schema\n",
+    "\n",
+    "CREATE TABLE IF NOT EXISTS \"person\" (\"person_name\" VARCHAR(30) NOT NULL PRIMARY KEY, \"lives_in_town\" VARCHAR(40) NOT NULL, \"nickname\" VARCHAR(20));
\n", + "CREATE TABLE IF NOT EXISTS \"job\" (\"job_name\" VARCHAR(30) NOT NULL PRIMARY KEY, \"start_date\" DATE NOT NULL, \"end_date\" DATE NOT NULL, \"salary\" DECIMAL(7, 2) NOT NULL, \"person_employed_id\" VARCHAR(30) NOT NULL, FOREIGN KEY (\"person_employed_id\") REFERENCES \"person\" (\"person_name\"));
\n", + "CREATE INDEX \"job_person_employed_id\" ON \"job\" (\"person_employed_id\");
\n", + "CREATE TABLE IF NOT EXISTS \"personnumkey\" (\"id\" INTEGER NOT NULL PRIMARY KEY, \"person_name\" VARCHAR(30) NOT NULL, \"lives_in_town\" VARCHAR(40) NOT NULL, \"nickname\" VARCHAR(20));
\n", + "
\n", + "
\n", + "

 

\n", + "

 

\n", + "
\n", + "
sqlite> .mode column\n",
+    "sqlite> .width 15 15 15 15 15\n",
+    "sqlite> .headers on\n",
+    "
\n", + "
\n", + "

 

\n", + "
\n", + "
sqlite> select * from person;\n",
+    "sqlite> select * from job;\n",
+    "
\n", + "
\n", + "

Enter .quit to leave sqlite.

\n", + "

Lesson Summary

\n", + "

In this lesson we have learned about how we define, store and retrieve data in a relational database using Python, Peewee\n", + " and sqlite.

\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

 

\n", + "

Video: Conclusion

\n", + "

 \n", + " PeeWee documentation\n", + "

\n", + "

 

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "\n", + "## Non-ORM Example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import sqlite3\n", + "import os\n", + "\n", + "database_filename = \"personjob.db\"\n", + "\n", + "try:\n", + " # remove if file exists\n", + " os.remove(database_filename)\n", + "except:\n", + " # ignore if file doesn't exist\n", + " pass \n", + "\n", + "statements = [\n", + " \"\"\"CREATE TABLE IF NOT EXISTS \"person\" (\"person_name\" VARCHAR(30) NOT NULL PRIMARY KEY, \"lives_in_town\" VARCHAR(40) NOT NULL, \"nickname\" VARCHAR(20));\"\"\",\n", + " \"\"\"CREATE TABLE IF NOT EXISTS \"job\" (\"job_name\" VARCHAR(30) NOT NULL PRIMARY KEY, \"start_date\" DATE NOT NULL, \"end_date\" DATE NOT NULL, \"salary\" DECIMAL(7, 2) NOT NULL, \"person_employed_id\" VARCHAR(30) NOT NULL, FOREIGN KEY (\"person_employed_id\") REFERENCES \"person\" (\"person_name\"));\"\"\",\n", + " \"\"\"CREATE INDEX \"job_person_employed_id\" ON \"job\" (\"person_employed_id\");\"\"\",\n", + " \"\"\"CREATE TABLE IF NOT EXISTS \"personnumkey\" (\"id\" INTEGER NOT NULL PRIMARY KEY, \"person_name\" VARCHAR(30) NOT NULL, \"lives_in_town\" VARCHAR(40) NOT NULL, \"nickname\" VARCHAR(20));\"\"\",\n", + "]\n", + "\n", + "with sqlite3.connect(database_filename) as conn:\n", + " try: \n", + " for stmt in statements:\n", + " print(stmt)\n", + " conn.execute(stmt)\n", + " except Exception as e:\n", + " print(e)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "
\n", + "

Activity

\n", + "
\n", + "

Warm up for the assignment

\n", + "

Before we launch into the assignment, let's be sure that you have everything you need to get started. We'll enhance the modules from the video along the way.

\n", + "

Preparing

\n", + "

Be sure to

\n", + "
\n", + "
pip install peewee\n",
+    "
\n", + "
\n", + "

 first.

\n", + "

Also, be sure that  

\n", + "
\n", + "
sqlite3 -version\n",
+    "
\n", + "
\n", + "

returns the sqlite3 version number, indicating it is installed. It should be, as it's bundled with Python 3.

\n", + "

Clone the repo at 

\n", + "
git@github.com:milesak60/RDBMS.git
\n", + "

although you should already have that from earlier in this lesson.

\n", + "

Make sure everything runs before proceeding to the next step.

\n", + "

Let's add a department

\n", + "

We have details of Persons. We have details of Jobs. Now we need to track in which Department a Person held a Job. For a Department, we need to know it's department number, which is 4 characters long and start with a letter. We need to know the department name (30 characters), and the name of the department manager (30 characters). We also need to know the duration in days that the job was held. Think about this last one carefully.

\n", + "

Make the necessary changes, annotating the code with log statements to explain what's going on. Also, draw a digram to help think through how you will incorporate Department into the programs.

\n", + "

Finally, produce a list using pretty print that shows all of the departments a person worked in for every job they ever had. 

\n", + "

Instructions

\n", + "

Once you've completed the activity from the lesson content, commit your changes and submit:

\n", + "
    \n", + "
  • a link to your repository on GitHub
  • \n", + "
  • the relevant .py file(s)
  • \n", + "
\n", + "

We'll be grading this activity purely on the percentage of included tests that pass.

\n", + "

Submitting Your Work 

\n", + "

Put the file(s) (ex: a_new_file.py) in your student directory in a new subdirectory named for this lesson, and add it to your clone early (git add a_new_file.py). Make frequent commits with good, clear messages about what you're doing and why.

\n", + "

When you're done and ready for the instructors to review your work, push your changes to your GitHub fork (git push) and then go to the GitHub website and make a pull request. Copy the link to the pull request.

\n", + "

Click the Submit Assignment button in the upper right.

\n", + "

Part 1: File(s)

\n", + "

Use the Choose File button to find and select the saved .py file or, if there are multiple files for the assignment, the .zip file.

\n", + "

Part 2: GitHub Link

\n", + "

Paste the GitHub link to the pull request in the comments area.

\n", + "

Click the Submit Assignment button.

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + "
\n", + "

Assignment

\n", + "
\n", + "

Instructions

\n", + "

Goal:

\n", + "

Redesign the object oriented mailroom program from class one using Peewee classes so that the data is persisted in sqlite. The approach you used in the OO exercise will naturally lend itself to this. (See Lesson 4, video 2)

\n", + "

Suggestions

\n", + "

You will need ways to add, update and delete data. Update and delete will mean that you need to find the data to update / delete. Perhaps you can do this by allowing a search first, and then selecting the particular instance to delete.

\n", + "

Remember that you need to read from the database, rather than relying on data held in variables when your program is running. To show you understand how this works, run the donor report from a separate program that read the database.

\n", + "

Generally, be sure to adapt the exception handling so that it helps identify any database errors, and consider how you may need to adapt your tests.

\n", + "

Be sure to give a lot of thought to what you should use as the primary key for your Peewee classes. In doing this, just consider data items that are unique in the context of the mailroom application. If you have to resort to generated keys, be sure to note why in the applicable docstring. And talking of which, be sure to define all your classes, as you learned in the videos.

\n", + "

The example programs for the videos will be a good starting point for reminders of syntax, but remember that the primary determinate of the structure of your solution will be a good object oriented Python application. The fact that it will now be persistent should not make too ,much difference. 

\n", + "

\n", + "

Submitting Your Work 

\n", + "

Put the file(s) (ex: a_new_file.py) in your student directory in a new subdirectory named for this lesson, and add it to your clone early (git add a_new_file.py). Make frequent commits with good, clear messages about what you're doing and why.

\n", + "

When you're done and ready for the instructors to review your work, push your changes to your GitHub fork (git push) and then go to the GitHub website and make a pull request. Copy the link to the pull request.

\n", + "

Click the Submit Assignment button in the upper right.

\n", + "

Part 1: File(s)

\n", + "

Use the Choose File button to find and select the saved .py file or, if there are multiple files for the assignment, the .zip file.

\n", + "

Part 2: GitHub Link

\n", + "

Paste the GitHub link to the pull request in the comments area.

\n", + "

Click the Submit Assignment button.

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
👹
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 800e4a7a652906435cc23a683df5caa5d46535e2 Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Mon, 9 Jul 2018 16:27:28 -0700 Subject: [PATCH 10/15] commit activity08 --- .../nosql-master/.circleci/config.yml | 58 +++ .../Py220_lesson08/nosql-master/.gitignore | 116 +++++ .../Py220_lesson08/nosql-master/.pylintrc | 426 ++++++++++++++++++ .../Py220_lesson08/nosql-master/README.md | 5 + .../nosql-master/sqlalchemy-rawsql | 18 + .../nosql-master/src/__init__.py | 0 .../nosql-master/src/learn_data.py | 49 ++ .../nosql-master/src/learnnosql.py | 41 ++ .../nosql-master/src/learnnosql2.py | 39 ++ .../nosql-master/src/login_database.py | 80 ++++ .../nosql-master/src/mongodb_script.py | 58 +++ .../nosql-master/src/neo4j_script.py | 97 ++++ .../nosql-master/src/redis_script.py | 58 +++ .../nosql-master/src/simple_script.py | 113 +++++ .../nosql-master/src/utilities.py | 43 ++ 15 files changed, 1201 insertions(+) create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/.circleci/config.yml create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/.gitignore create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/.pylintrc create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/README.md create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/sqlalchemy-rawsql create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/src/__init__.py create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learn_data.py create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learnnosql.py create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learnnosql2.py create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/src/login_database.py create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/src/mongodb_script.py create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/src/neo4j_script.py create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/src/redis_script.py create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/src/simple_script.py create mode 100755 Student/tammyd_Py220/Py220_lesson08/nosql-master/src/utilities.py diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/.circleci/config.yml b/Student/tammyd_Py220/Py220_lesson08/nosql-master/.circleci/config.yml new file mode 100755 index 0000000..c6c783b --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/.circleci/config.yml @@ -0,0 +1,58 @@ +# Python CircleCI 2.0 configuration file +# +# Check https://circleci.com/docs/2.0/language-python/ for more details +# +version: 2 +jobs: + build: + docker: + # specify the version you desire here + # use `-browsers` prefix for selenium tests, e.g. `3.6.1-browsers` + - image: circleci/python:3.6.1 + + # Specify service dependencies here if necessary + # CircleCI maintains a library of pre-built images + # documented at https://circleci.com/docs/2.0/circleci-images/ + # - image: circleci/postgres:9.4 + + working_directory: ~/repo + + steps: + - checkout + - run: mkdir logs + + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "requirements.txt" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + - run: + name: install dependencies + command: | + python3 -m venv venv + . venv/bin/activate + pip install -r requirements.txt + + - save_cache: + paths: + - ./venv + key: v1-dependencies-{{ checksum "requirements.txt" }} + + # run tests! + # this example uses Django's built-in test-runner + # other common Python testing frameworks include pytest and nose + # https://pytest.org + # https://nose.readthedocs.io + - run: + name: run tests + command: | + . venv/bin/activate + autopep8 --in-place --aggressive src/*.py tests/*.py + pytest --pylint --profile --cov =src tests/ --junitxml=test_results/results.xml src/*.py tests/*.py + + - store_artifacts: + path: test_results + destination: results + diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/.gitignore b/Student/tammyd_Py220/Py220_lesson08/nosql-master/.gitignore new file mode 100755 index 0000000..3e3b980 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/.gitignore @@ -0,0 +1,116 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +.DS_Store + +#secrets +.config/ + +prof/ +.pytest_cache/ +.idea/ + +test_results/ +logs/ + +data/ + diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/.pylintrc b/Student/tammyd_Py220/Py220_lesson08/nosql-master/.pylintrc new file mode 100755 index 0000000..f0d5efe --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/.pylintrc @@ -0,0 +1,426 @@ +[MASTER] + +# Specify a configuration file. +#rcfile= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Pickle collected data for later comparisons. +persistent=yes + +# List of plugins (as comma separated values of python modules names) to load, +# usually to register additional checkers. +load-plugins= + +# Use multiple processes to speed up Pylint. +jobs=1 + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code +extension-pkg-whitelist= + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED +confidence= + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time. See also the "--disable" option for examples. +#enable= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once).You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use"--disable=all --enable=classes +# --disable=W" +# +# ----------------------------------------------------------------------- +# 2015-01-12 - What follows is the list of all disabled items necessary +# to get a clean run of lint across CourseBuilder. These are separated +# into three tiers: +# +# - Fix-worthy. This includes: +# - Probable bugs +# - Easily-addressed hygiene issues, +# - Real warnings which we may mark as suppressed on a case-by-case basis. +# - Items that are questionable practice, but not necessarily economical to fix. +# - Items that we intend to ignore, as we do not consider them bad practice. +# +# Warning messages are documented at http://docs.pylint.org/features.html +# +# ---------------------------------------------------------------------- +# Fix-worthy: +# +# ---- Possible bugs: +# disable=super-on-old-class +# disable=arguments-differ (# of arguments to overriding/overridden method) +# disable=signature-differs +# disable=method-hidden +# disable=abstract-method (Abstract method not overridden in derived class) +# disable=no-member (self.foo used when foo not declared in class) +# +# ---- Easy-to-fix and improves readability, cleanliness: +# disable=relative-import +# +# ---- Probably legitimate, but needs markup to indicate intentionality +# disable=no-init (Class does not have __init__, nor do ancestor classes) +# disable=import-error +# disable=attribute-defined-outside-init +# +# ---------------------------------------------------------------------- +# Fix when economical: +# +# ---- Minor code cleanliness problems; fix when encountered. +# disable=unused-argument +# disable=unused-variable +# disable=invalid-name (Variable name does not meet coding standard) +# disable=duplicate-code +# +# ---- Laundry list of tunable parameters for when things are too big/small +# disable=abstract-class-little-used +# disable=too-few-public-methods +# disable=too-many-instance-attributes +# disable=too-many-ancestors +# disable=too-many-return-statements +# disable=too-many-lines +# disable=too-many-locals +# disable=too-many-function-args +# disable=too-many-public-methods +# disable=too-many-arguments +# +# ---------------------------------------------------------------------- +# Ignored; OK by our coding standard: +# +# disable=bad-continuation (Bad whitespace on following line) +# disable=no-self-use (Member function never uses 'self' parameter) +# disable=missing-docstring +# disable=fixme +# disable=star-args +# disable=locally-disabled (Notes local suppression of warning) +# disable=locally-enabled (Notes re-enable of suppressed warning) +# disable=bad-option-value (Notes suppression of unknown warning) +# disable=abstract-class-not-used (Warns when not used in same file) +# +# Unfortunately, since the options parsing does not support multi-line entries +# nor line continuation, all of the above items are redundantly specified here +# in a way that pylint is willing to parse. +disable=super-on-old-class,arguments-differ,signature-differs,method-hidden,abstract-method,no-member,relative-import,no-init,import-error,attribute-defined-outside-init,abstract-class-not-used,unused-argument,unused-variable,invalid-name,duplicate-code,abstract-class-little-used,too-few-public-methods,too-many-instance-attributes,too-many-ancestors,too-many-return-statements,too-many-lines,too-many-locals,too-many-function-args,too-many-public-methods,too-many-arguments,bad-continuation,no-self-use,missing-docstring,fixme,star-args,locally-disabled,locally-enabled,bad-option-value + +[REPORTS] + +# Set the output format. Available formats are text, parseable, colorized, msvs +# (visual studio) and html. You can also give a reporter class, eg +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Put messages in a separate file for each module / package specified on the +# command line instead of printing them on stdout. Reports (if any) will be +# written in a file name "pylint_global.[txt|html]". +files-output=no + +# Tells whether to display a full report or only the messages +reports=no + +# Python expression which should return a note less than 10 (10 is the highest +# note). You have access to the variables errors warning, statement which +# respectively contain the number of errors / warnings messages and the total +# number of statements analyzed. This is used by the global evaluation report +# (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details +#msg-template= + + +[SPELLING] + +# Spelling dictionary name. Available dictionaries: none. To make it working +# install python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to indicated private dictionary in +# --spelling-private-dict-file option instead of raising a message. +spelling-store-unknown-words=no + + +[SIMILARITIES] + +# Minimum lines number of a similarity. +min-similarity-lines=4 + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + + +[LOGGING] + +# Logging modules to check that the string format arguments are in logging +# function parameter format +logging-modules=logging + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME,XXX,TODO + + +[VARIABLES] + +# Tells whether we should check for unused import in __init__ files. +init-import=yes + +# A regular expression matching the name of dummy variables (i.e. expectedly +# not used). +dummy-variables-rgx=_$|dummy + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid to define new builtins when possible. +additional-builtins= + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_,_cb + + +[TYPECHECK] + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis +ignored-modules= + +# List of classes names for which member attributes should not be checked +# (useful for classes with attributes dynamically set). +ignored-classes=SQLObject + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E0201 when accessed. Python regular +# expressions are accepted. +generated-members=REQUEST,acl_users,aq_parent + + +[BASIC] + +# List of builtins function names that should not be used, separated by a comma +bad-functions=map,filter,input + +# Good variable names which should always be accepted, separated by a comma +good-names=i,j,k,ex,Run,_ + +# Bad variable names which should always be refused, separated by a comma +bad-names=foo,bar,baz,toto,tutu,tata + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Include a hint for the correct naming format with invalid-name +include-naming-hint=no + +# Regular expression matching correct function names +function-rgx=[a-z_][a-z0-9_]{2,50}$ + +# Naming hint for function names +function-name-hint=[a-z_][a-z0-9_]{2,50}$ + +# Regular expression matching correct variable names +variable-rgx=[a-z_][a-z0-9_]{1,30}$ + +# Naming hint for variable names +variable-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct constant names +const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Naming hint for constant names +const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ + +# Regular expression matching correct attribute names +attr-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for attribute names +attr-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct argument names +argument-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for argument names +argument-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression matching correct class attribute names +class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Naming hint for class attribute names +class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ + +# Regular expression matching correct inline iteration names +inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ + +# Naming hint for inline iteration names +inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ + +# Regular expression matching correct class names +class-rgx=[A-Z_][a-zA-Z0-9]+$ + +# Naming hint for class names +class-name-hint=[A-Z_][a-zA-Z0-9]+$ + +# Regular expression matching correct module names +module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Naming hint for module names +module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ + +# Regular expression matching correct method names +method-rgx=[a-z_][a-z0-9_]{2,30}$ + +# Naming hint for method names +method-name-hint=[a-z_][a-z0-9_]{2,30}$ + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=__.*__ + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + + +[FORMAT] + +# Maximum number of characters on a single line. +max-line-length=80 + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + +# List of optional constructs for which whitespace checking is disabled +no-space-check=trailing-comma,dict-separator + +# Maximum number of lines in a module +max-module-lines=2000 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + + +[IMPORTS] + +# Deprecated modules which should not be used, separated by a comma +deprecated-modules=regsub,TERMIOS,Bastion,rexec + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled) +import-graph= + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled) +ext-import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled) +int-import-graph= + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__,__new__,setUp + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=mcs + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict,_fields,_replace,_source,_make + + +[DESIGN] + +# Maximum number of arguments for function / method +max-args=12 + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore +ignored-argument-names=_.* + +# Maximum number of locals for function / method body +max-locals=25 + +# Maximum number of return / yield for function / method body +max-returns=6 + +# Maximum number of branch for function / method body +max-branches=40 + +# Maximum number of statements in function / method body +max-statements=105 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=50 + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "Exception" +overgeneral-exceptions=Exception \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/README.md b/Student/tammyd_Py220/Py220_lesson08/nosql-master/README.md new file mode 100755 index 0000000..48170fc --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/README.md @@ -0,0 +1,5 @@ +# nosql + +python certificate nosql example + +All of the Python code is in the src directory. diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/sqlalchemy-rawsql b/Student/tammyd_Py220/Py220_lesson08/nosql-master/sqlalchemy-rawsql new file mode 100755 index 0000000..74ff224 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/sqlalchemy-rawsql @@ -0,0 +1,18 @@ +""" + a simple example of how to use sqlalchemy to run sql against a database + +""" + +import sqlalchemy +from sqlalchemy import create_engine + +# replace xxx with database specific conection string + +engine = create_engine('xxx') + +with engine.connect() as con: + + rs = con.execute('SELECT * FROM book') + + for row in rs: + print row diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/__init__.py b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learn_data.py b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learn_data.py new file mode 100755 index 0000000..d58f589 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learn_data.py @@ -0,0 +1,49 @@ +""" + Data for database demonstrations +""" + + +def get_furniture_data(): + """ + demonstration data + """ + + furniture_data = [ + { + 'product': 'Red couch', + 'description': 'Leather low back', + 'monthly_rental_cost': 12.99, + 'in_stock_quantity': 10 + }, + { + 'product': 'Blue couch', + 'description': 'Cloth high back', + 'monthly_rental_cost': 9.99, + 'in_stock_quantity': 3 + }, + { + 'product': 'Coffee table', + 'description': 'Plastic', + 'monthly_rental_cost': 2.50, + 'in_stock_quantity': 25 + }, + { + 'product': 'Red couch', + 'description': 'Leather high back', + 'monthly_rental_cost': 15.99, + 'in_stock_quantity': 17 + }, + { + 'product': 'Blue recliner', + 'description': 'Leather high back', + 'monthly_rental_cost': 19.99, + 'in_stock_quantity': 6 + }, + { + 'product': 'Chair', + 'description': 'Plastic', + 'monthly_rental_cost': 1.00, + 'in_stock_quantity': 45 + } + ] + return furniture_data diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learnnosql.py b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learnnosql.py new file mode 100755 index 0000000..e8ab095 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learnnosql.py @@ -0,0 +1,41 @@ +#!/usr/local/bin/python + +""" + +Integrated example for nosql databases + +""" + +import learn_data +import mongodb_script +# import redis_script +# import neo4j_script +import simple_script +import utilities + + +def showoff_databases(): + """ + Here we illustrate basic interaction with nosql databases + """ + + log = utilities.configure_logger('default', '../logs/nosql_dev.log') + + log.info("Mongodb example to use data from Furniture module, so get it") + furniture = learn_data.get_furniture_data() + + mongodb_script.run_example(furniture) + + log.info("Other databases use data embedded in the modules") + + # redis_script.run_example() + # neo4j_script.run_example() + simple_script.run_example(furniture) + + +if __name__ == '__main__': + """ + orchestrate nosql examples + """ + + showoff_databases() diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learnnosql2.py b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learnnosql2.py new file mode 100755 index 0000000..932c750 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/learnnosql2.py @@ -0,0 +1,39 @@ +""" + +Integrated example for nosql databases + +""" + +import learn_data +import mongodb_script +#import redis_script +#import neo4j_script +import simple_script +import utilities + + +def showoff_databases(): + """ + Here we illustrate basic interaction with nosql databases + """ + + log = utilities.configure_logger('default', '../logs/nosql_dev.log') + + log.info("Mongodb example to use data from Furniture module, so get it") + furniture = learn_data.get_furniture_data() + + mongodb_script.run_example(furniture) + + log.info("Other databases use data embedded in the modules") + + #redis_script.run_example() + #neo4j_script.run_example() + simple_script.run_example(furniture) + + +if __name__ == '__main__': + """ + orchestrate nosql examples + """ + + showoff_databases() diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/login_database.py b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/login_database.py new file mode 100755 index 0000000..27a795d --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/login_database.py @@ -0,0 +1,80 @@ +""" + module that will login to the various demonstration databases consistently +""" + +import configparser +from pathlib import Path +import pymongo +# import redis +# from neo4j.v1 import GraphDatabase, basic_auth + +import utilities + +log = utilities.configure_logger('default', '../logs/login_databases_dev.log') +config_file = Path(__file__).parent.parent / '.config/config.ini' +config = configparser.ConfigParser() + + +def login_mongodb_cloud(): + """ + connect to mongodb and login + """ + + log.info('Here is where we use the connect to mongodb.') + log.info('Note use of f string to embed the user & password (from the tuple).') + try: + config.read(config_file) + user = "tammytdo" + pw = "9*MongoDB" + + except Exception as e: + print(f'error: {e}') + + client = pymongo.MongoClient(f'mongodb://tammytdo:9*MongoDB@cluster0-shard-00-00-7ak2y.mongodb.net:27017,cluster0-shard-00-01-7ak2y.mongodb.net:27017,cluster0-shard-00-02-7ak2y.mongodb.net:27017/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin&retryWrites=true') + + return client + + +# def login_redis_cloud(): +# """ +# connect to redis and login +# """ +# try: +# config.read(config_file) +# host = config["redis_cloud"]["host"] +# port = config["redis_cloud"]["port"] +# pw = config["redis_cloud"]["pw"] + + +# except Exception as e: +# print(f'error: {e}') + +# log.info('Here is where we use the connect to redis.') + +# try: +# r = redis.StrictRedis(host=host, port=port, password=pw, decode_responses=True) + +# except Exception as e: +# print(f'error: {e}') + +# return r + + +# def login_neo4j_cloud(): +# """ +# connect to neo4j and login + +# """ + +# log.info('Here is where we use the connect to neo4j.') +# log.info('') + +# config.read(config_file) + +# graphenedb_user = config["neo4j_cloud"]["user"] +# graphenedb_pass = config["neo4j_cloud"]["pw"] +# graphenedb_url = 'bolt://hobby-opmhmhgpkdehgbkejbochpal.dbs.graphenedb.com:24786' +# driver = GraphDatabase.driver(graphenedb_url, +# auth=basic_auth(graphenedb_user, graphenedb_pass)) + +# return driver diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/mongodb_script.py b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/mongodb_script.py new file mode 100755 index 0000000..758fc31 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/mongodb_script.py @@ -0,0 +1,58 @@ +""" + mongodb example +""" + +import pprint +import login_database +import utilities + +log = utilities.configure_logger('default', '../logs/mongodb_script.log') + + +def run_example(furniture_items): + """ + mongodb data manipulation + """ + + with login_database.login_mongodb_cloud() as client: + log.info('Step 1: We are going to use a database called dev') + log.info('But if it doesnt exist mongodb creates it') + db = client['dev'] + + log.info('And in that database use a collection called furniture') + log.info('If it doesnt exist mongodb creates it') + + furniture = db['furniture'] + + log.info('Step 2: Now we add data from the dictionary above') + furniture.insert_many(furniture_items) + + log.info('Step 3: Find the products that are described as plastic') + query = {'description': 'Plastic'} + results = furniture.find_one(query) + + log.info('Step 4: Print the plastic products') + print('Plastic products') + pprint.pprint(results) + + log.info('Step 5: Delete the blue couch (actually deletes all blue couches)') + furniture.remove({"product": {"$eq": "Blue couch"}}) + + log.info('Step 6: Check it is deleted with a query and print') + query = {'product': 'Blue couch'} + results = furniture.find_one(query) + print('The blue couch is deleted, print should show none:') + pprint.pprint(results) + + log.info( + 'Step 7: Find multiple documents, iterate though the results and print') + + cursor = furniture.find({'monthly_rental_cost': {'$gte': 15.00}}).sort('monthly_rental_cost', 1) + print('Results of search') + log.info('Notice how we parse out the data from the document') + + for doc in cursor: + print(f"Cost: {doc['monthly_rental_cost']} product name: {doc['product']} Stock: {doc['in_stock_quantity']}") + + log.info('Step 8: Delete the collection so we can start over') + db.drop_collection('furniture') diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/neo4j_script.py b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/neo4j_script.py new file mode 100755 index 0000000..99f21ed --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/neo4j_script.py @@ -0,0 +1,97 @@ +""" + neo4j example +""" + + +import utilities +import login_database +import utilities + +log = utilities.configure_logger('default', '../logs/neo4j_script.log') + + +def run_example(): + + log.info('Step 1: First, clear the entire database, so we can start over') + log.info("Running clear_all") + + driver = login_database.login_neo4j_cloud() + with driver.session() as session: + session.run("MATCH (n) DETACH DELETE n") + + log.info("Step 2: Add a few people") + + with driver.session() as session: + + log.info('Adding a few Person nodes') + log.info('The cyph language is analagous to sql for neo4j') + for first, last in [('Bob', 'Jones'), + ('Nancy', 'Cooper'), + ('Alice', 'Cooper'), + ('Fred', 'Barnes'), + ('Mary', 'Evans'), + ('Marie', 'Curie'), + ]: + cyph = "CREATE (n:Person {first_name:'%s', last_name: '%s'})" % ( + first, last) + session.run(cyph) + + log.info("Step 3: Get all of people in the DB:") + cyph = """MATCH (p:Person) + RETURN p.first_name as first_name, p.last_name as last_name + """ + result = session.run(cyph) + print("People in database:") + for record in result: + print(record['first_name'], record['last_name']) + + log.info('Step 4: Create some relationships') + log.info("Bob Jones likes Alice Cooper, Fred Barnes and Marie Curie") + + for first, last in [("Alice", "Cooper"), + ("Fred", "Barnes"), + ("Marie", "Curie")]: + cypher = """ + MATCH (p1:Person {first_name:'Bob', last_name:'Jones'}) + CREATE (p1)-[friend:FRIEND]->(p2:Person {first_name:'%s', last_name:'%s'}) + RETURN p1 + """ % (first, last) + session.run(cypher) + + log.info("Step 5: Find all of Bob's friends") + cyph = """ + MATCH (bob {first_name:'Bob', last_name:'Jones'}) + -[:FRIEND]->(bobFriends) + RETURN bobFriends + """ + result = session.run(cyph) + print("Bob's friends are:") + for rec in result: + for friend in rec.values(): + print(friend['first_name'], friend['last_name']) + + log.info("Setting up Marie's friends") + + for first, last in [("Mary", "Evans"), + ("Alice", "Cooper"), + ('Fred', 'Barnes'), + ]: + cypher = """ + MATCH (p1:Person {first_name:'Marie', last_name:'Curie'}) + CREATE (p1)-[friend:FRIEND]->(p2:Person {first_name:'%s', last_name:'%s'}) + RETURN p1 + """ % (first, last) + + session.run(cypher) + + print("Step 6: Find all of Marie's friends?") + cyph = """ + MATCH (marie {first_name:'Marie', last_name:'Curie'}) + -[:FRIEND]->(friends) + RETURN friends + """ + result = session.run(cyph) + print("\nMarie's friends are:") + for rec in result: + for friend in rec.values(): + print(friend['first_name'], friend['last_name']) diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/redis_script.py b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/redis_script.py new file mode 100755 index 0000000..e32e2ef --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/redis_script.py @@ -0,0 +1,58 @@ +""" + demonstrate use of Redis +""" + + +import login_database +import utilities + + +def run_example(): + """ + uses non-presistent Redis only (as a cache) + + """ + + log = utilities.configure_logger('default', '../logs/redis_script.log') + + try: + log.info('Step 1: connect to Redis') + r = login_database.login_redis_cloud() + log.info('Step 2: cache some data in Redis') + r.set('andy', 'andy@somewhere.com') + + log.info('Step 2: now I can read it') + email = r.get('andy') + log.info('But I must know the key') + log.info(f'The results of r.get: {email}') + + log.info('Step 3: cache more data in Redis') + r.set('pam', 'pam@anywhere.com') + r.set('fred', 'fred@fearless.com') + + log.info('Step 4: delete from cache') + r.delete('andy') + log.info(f'r.delete means andy is now: {email}') + + log.info( + 'Step 6: Redis can maintain a unique ID or count very efficiently') + r.set('user_count', 21) + r.incr('user_count') + r.incr('user_count') + r.decr('user_count') + result = r.get('user_count') + log.info('I could use this to generate unique ids') + log.info(f'Redis says 21+1+1-1={result}') + + log.info('Step 7: richer data for a SKU') + r.rpush('186675', 'chair') + r.rpush('186675', 'red') + r.rpush('186675', 'leather') + r.rpush('186675', '5.99') + + log.info('Step 8: pull some data from the structure') + cover_type = r.lindex('186675', 2) + log.info(f'Type of cover = {cover_type}') + + except Exception as e: + print(f'Redis error: {e}') diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/simple_script.py b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/simple_script.py new file mode 100755 index 0000000..163f679 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/simple_script.py @@ -0,0 +1,113 @@ +""" +pickle etc +""" + +import pickle +import shelve +import csv +import json + +import pprint +import utilities + +log = utilities.configure_logger('default', '../logs/mongodb_script.log') + + +def run_example(furniture_items): + """ + various persistence and serialization scenarios + + """ + + def run_pickle(): + """ + Write and read with pickle + """ + log.info("\n\n====") + log.info('Step 1: Demonstrate persistence with pickle') + log.info('Write a pickle file with the furniture data') + + pickle.dump(furniture_items, open('../data/data.pkl', 'wb')) + + log.info('Step 2: Now read it back from the pickle file') + read_data = pickle.load(open('../data/data.pkl', 'rb')) + log.info('Step 3: Show that the write and read were successful') + assert read_data == furniture_items + log.info("and print the data") + pprint.pprint(read_data) + + def run_shelve(): + """ + write and read with shelve + + """ + log.info("\n\n====") + log.info("Step 4: Demonstrate working with shelve") + shelf_file = shelve.open('../data/shelve.dat') + log.info("Step 5: store data at key") + shelf_file['key'] = furniture_items + + log.info("Step 6: Now retrieve a COPY of data at key") + read_items = shelf_file['key'] + + log.info("Check it worked") + assert read_items == furniture_items + + log.info("And now print the copy") + pprint.pprint(read_items) + + log.info("Step 7: delete data stored at key to cleanup and close") + del shelf_file['key'] + shelf_file.close() + + def run_csv(): + """ + write and read a csv + """ + log.info("\n\n====") + peopledata = [ + ('John', 'second guitar', 117.45), + ('Paul', 'bass', 22.01), + ('George', 'lead guitar', 45.99), + ('Ringo', 'drume', 77.0), + ('Roger', 'vocals', 12.5), + ('Keith', 'drums', 6.25), + ('Pete', 'guitar', 0.1), + ('John', 'bass', 89.71) + ] + log.info("Step 8: Write csv file") + with open('../data/rockstars.csv', 'w') as people: + peoplewriter = csv.writer(people) + peoplewriter.writerow(peopledata) + + log.info("Step 9: Read csv file back") + with open('../data/rockstars.csv', 'r') as people: + people_reader = csv.reader(people, delimiter=',', quotechar='"') + for row in people_reader: + pprint.pprint(row) + + def run_json(): + log.info("\n\n====") + log.info("Step 10: Look at working with json data") + furniture = [{'product': 'Red couch','description': 'Leather low back'}, + {'product': 'Blue couch','description': 'Cloth high back'}, + {'product': 'Coffee table','description': 'Plastic'}, + {'product': 'Red couch','description': 'Leather high back'}] + + log.info("Step 11: Return json string from an object") + furniture_string = json.dumps(furniture) + + log.info("Step 12: Print the json") + pprint.pprint(furniture_string) + + log.info("Step 13: Returns an object from a json string representation") + furniture_object = json.loads(furniture_string) + log.info("Step 14: print the string") + pprint.pprint(furniture_object) + + run_pickle() + run_shelve() + run_csv() + run_json() + + return diff --git a/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/utilities.py b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/utilities.py new file mode 100755 index 0000000..15b1079 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson08/nosql-master/src/utilities.py @@ -0,0 +1,43 @@ +""" +enable easy and controllable logging +""" + +import logging +import logging.config + + +def configure_logger(name, log_path): + """ + generic logger + """ + logging.config.dictConfig({ + 'version': 1, + 'formatters': { + 'default': {'format': '%(asctime)s - %(levelname)s - %(message)s', 'datefmt': '%Y-%m-%d %H:%M:%S'} + }, + 'handlers': { + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + 'formatter': 'default', + 'stream': 'ext://sys.stdout' + }, + 'file': { + 'level': 'DEBUG', + 'class': 'logging.handlers.RotatingFileHandler', + 'formatter': 'default', + 'filename': log_path, + 'maxBytes': 1024, + 'backupCount': 3 + } + }, + 'loggers': { + 'default': { + 'level': 'DEBUG', + 'handlers': ['console', 'file'] + } + }, + 'disable_existing_loggers': False + }) + return logging.getLogger(name) + From b98a9edfa83ff5428076eeaccb7463b37797143a Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Mon, 9 Jul 2018 16:29:26 -0700 Subject: [PATCH 11/15] commit assignment09 and activity09 --- Student/tammyd_Py220/Py220_lesson09/async.py | 69 +++++++++++++ .../Py220_lesson09/concurrency.py | 57 +++++++++++ .../Py220_lesson09/get_news_sync.py | 98 +++++++++++++++++++ 3 files changed, 224 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson09/async.py create mode 100644 Student/tammyd_Py220/Py220_lesson09/concurrency.py create mode 100644 Student/tammyd_Py220/Py220_lesson09/get_news_sync.py diff --git a/Student/tammyd_Py220/Py220_lesson09/async.py b/Student/tammyd_Py220/Py220_lesson09/async.py new file mode 100644 index 0000000..9cd9d86 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson09/async.py @@ -0,0 +1,69 @@ +# coroutines + +async def corout(): + print("running corout") + return "something returned" + +#note that the returned value gets tacked on to the StopIteration + +async def corout2(): + print("running corout2") + await corout() + + +# make a coroutine +cr = corout() + +#run it with a send: +cr.send(None) + + +cr2 = corout2() +cr2.send(None) + + +from types import coroutine + +#Now we have a coroutine decorator with an await in it + +@coroutine +def do_nothing(): + yield "something from do_nothing" + + +dn = do_nothing() +dn.send(None) + +async def do_a_few_things(num=3): + for i in range(num): + print(f"in the loop for the {i}th time") + res = await do_nothing() + print("res is:", res) + return "do a few things result" + +daft = do_a_few_things(5) + +#call up to 5 times +daft.send(None) + +# to keep going, keep calling send() until we get the StopIteration + +while True: + try: + daft.send(None) + except StopIteration as si: + print("The awaitable is complete") + print("passed out:", si) + break + + +# recell from generators that send naturally snd a val into the generator +def gen(): + for i in range(3): + res = yield i + print(f"loop: {i}, result: {res}") + return "returned from gen" +g = gen() + +# g.send(45) +# g.send(60) \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson09/concurrency.py b/Student/tammyd_Py220/Py220_lesson09/concurrency.py new file mode 100644 index 0000000..1b5a582 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson09/concurrency.py @@ -0,0 +1,57 @@ +import threading +import time +import random + +# simple threading + +def func(n): + for i in range(n): + print("hello from thread %s" % threading.current_thread().name) + time.sleep(random.random() * 2) + +# run a bunch of fuctions at the same time +threads = [] +for i in range(3): + thread = threading.Thread(target=func, args=(i+2)) + thread.start() + threads.append(thread) + +# start and append thread. +for thread in threads: + print("Joining thread: ", thread.name) + thread.join() +# to know when it is done +print("all threads finished.") + +func(10) + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~` + +# # race conditions + +# import threading +# import time + +# class shared: +# val = 1 + +# def func(): +# y = shared.val +# time.sleep(0.001) +# y += 1 +# shared.val = y + +# threads = [] + +# for i in range(100): +# thread = threading.Thread(target=func) +# threads.append(thread) +# thread.start() + +# for thread in threads: +# thread.join() + +# print(shared.val) + + + diff --git a/Student/tammyd_Py220/Py220_lesson09/get_news_sync.py b/Student/tammyd_Py220/Py220_lesson09/get_news_sync.py new file mode 100644 index 0000000..57ed580 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson09/get_news_sync.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +#Tammy + +""" +Regular synchronous script to see how much a given word is mentioned in the +news today + +Took about 21 seconds for me. + +Uses data from the NewsAPI: + +https://newsapi.org + +NOTE: you need to register with the web site to get a KEY. +""" +import time +import requests +import threading + +WORD = "trump" + +NEWS_API_KEY = "84d0483394c44f288965d7b366e54a74" + +base_url = 'https://newsapi.org/v1/' + + +def get_sources(): + """ + Get all the english language sources of news + + 'https://newsapi.org/v1/sources?language=en' + """ + url = base_url + "sources" + params = {"language": "en"} + resp = requests.get(url, params=params) + data = resp.json() + sources = [src['id'].strip() for src in data['sources']] + print("all the sources") + print(sources) + return sources + + +def get_articles(source): + """ + https://newsapi.org/v1/articles?source=associated-press&sortBy=top&apiKey=1fabc23bb9bc485ca59b3966cbd6ea26 + """ + url = base_url + "articles" + params = {"source": source, + "apiKey": NEWS_API_KEY, + # "sortBy": "latest", # some sources don't support latest + "sortBy": "top", + # "sortBy": "popular", + } + print("requesting:", source) + resp = requests.get(url, params=params) + if resp.status_code != 200: # aiohttpp has "status" + print("something went wrong with {}".format(source)) + print(resp) + print(resp.text) + return [] + data = resp.json() + # the url to the article itself is in data['articles'][i]['url'] + titles = [str(art['title']) + str(art['description']) + for art in data['articles']] + return titles + + +def count_word(word, titles): + word = word.lower() + count = 0 + for title in titles: + if word in title.lower(): + count += 1 + return count + + +start = time.time() +sources = get_sources() + +def news(): + art_count = 0 + word_count = 0 + for source in sources: + titles = get_articles(source) + art_count += len(titles) + word_count += count_word('trump', titles) + + print(WORD, "found {} times in {} articles".format(word_count, art_count)) + print("Process took {:.0f} seconds".format(time.time() - start)) + +threads = [] +for i in range(1): + thread = threading.Thread(target= news, args=()) + thread.start() + threads.append(thread) + + +#this is single threading. could only get single to work correctly. \ No newline at end of file From b304cdf325f0e96c6c9754cd5f0ec2375ed011c2 Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Mon, 9 Jul 2018 16:30:18 -0700 Subject: [PATCH 12/15] commit activity10. I chose to explore Pypy. --- .../tammyd_Py220/Py220_lesson10/jit_test.py | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson10/jit_test.py diff --git a/Student/tammyd_Py220/Py220_lesson10/jit_test.py b/Student/tammyd_Py220/Py220_lesson10/jit_test.py new file mode 100644 index 0000000..6818ee6 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson10/jit_test.py @@ -0,0 +1,155 @@ +""" +Exploring PyPy + +Code with notes + +""" + +# pypy is a fast, compliant alternative implementation of the Python language with several advantages and distinct features +# speed = it is a just in time compiler that is faster than python +# memory usage +# compatibility +# stackless + + + +import math +import time + +TIMES = 10000000 + +# take a snapshot of system clock +init = time.clock() + + + +# run an operation +for i in range(TIMES): + value = math.sqrt(1 + math.fabs(math.sin(i - math.cos(i)))) + +print("No function: %s" % (time.clock() - init)) + +# Factoring the math into a function + +def calcMath(i): + return math.sqrt(i + math.fabs(math.sin(i - math.cos(i)))) + +# take another snapshot of system clock + +init = time.clock() + +for i in range(TIMES): + calue = calcMath(i) + +# check the difference. This time there is a function. +#factored out this expression and put it into a fuction +print("Function: %s" % (time.clock() - init)) + + +# run TIMES = 1000000 under python 3.5. +# output + # No function: 1.141732 + # Function: 1.2815550000000002 + +# run TIMES = 100000000 under python 3.5. + # + +# not yet using jit compiler. still using standard python +# output + # No function: 111.869146 + # Function: 123.371944 + +# Rick changed into another environment. +## Python 3.6.4 was slower than Python 2.7.14! + +# now let's try Pypy. +# It will run on top of Python 2.7.13 +# Tammys-MBP:Py220_lesson10 tammydo$ pypy jit_test.py +# output + # No function: 0.845679 + # Function: 0.863227 + +# Pypy is so much faster! + + + + + + + + + + + + +# # ------------------------------------------------------- +# # Timeit tutorial +# # rriehle + +# from timeit import timeit as timer + +# my_repititions = 10000 +# my_range = 10000 +# my_lower_limit = my_range / 2 + +# my_list = list(range(my_range)) + + +# def multiply_by_two(x): +# return x * 2 + + +# def greater_than_lower_limit(x): +# return x > my_lower_limit + + +# print("\n\nmap_filter_with_functions") +# # map_filter_with_functions = map(multiply_by_two, filter(greater_than_lower_limit, my_list)) +# # print(*map_filter_with_functions) +# print(timer( +# 'map_filter_with_functions = map(multiply_by_two, filter(greater_than_lower_limit, my_list))', +# globals=globals(), +# number=my_repititions +# )) + +# print("\n\nmap_filter_with_lambdas") +# # map_filter_with_lambdas = map(lambda x: x * 2, filter(lambda x: x > my_lower_limit, my_list)) +# # print(*map_filter_with_lambdas) +# print(timer( +# 'map_filter_with_lambdas = map(lambda x: x * 2, filter(lambda x: x > my_lower_limit, my_list))', +# globals=globals(), +# number=my_repititions +# )) + +# print("\n\ncomprehension") +# # comprehension = [x * 2 for x in my_list if x > my_lower_limit] +# # print(*comprehension) +# print(timer( +# 'comprehension = [x * 2 for x in my_list if x > my_lower_limit]', +# globals=globals(), +# number=my_repititions +# )) + +# print("\n\ncomprehension_with_functions") +# # comprehension_with_functions = [multiply_by_two(x) for x in my_list if greater_than_lower_limit(x)] +# # print(*comprehension_with_functions) +# print(timer( +# 'comprehension_with_functions = [multiply_by_two(x) for x in my_list if greater_than_lower_limit(x)]', +# globals=globals(), +# number=my_repititions +# )) + +# print("\n\ncomprehension_with_lambdas") +# # comprehension_with_lambdas = [lambda x: x * 2 for x in my_list if lambda x: x > my_lower_limit] +# # comprehension_with_lambdas = [(lambda x: x * 2)(x) for x in my_list if (lambda x: x)(x) > my_lower_limit] +# # print(*comprehension_with_lambdas) +# print(timer( +# 'comprehension_with_lambdas = [(lambda x: x * 2)(x) for x in my_list if (lambda x: x)(x) > my_lower_limit]', +# globals=globals(), +# number=my_repititions +# )) + + +# # Consider order of operations between the forms. +# # In map_filter_with_functions the filter is applied before the map expression +# # Is that true in the other variatins? \ No newline at end of file From 6961dc02738e86e8ac0b5d281bed5dda47b2006e Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Mon, 9 Jul 2018 20:56:53 -0700 Subject: [PATCH 13/15] commit lesson04 --- .../Py220_lesson04/turn_in/Lesson 4.ipynb | 742 ++++++++++++++++++ .../Py220_lesson04/turn_in/follow_video_1.py | 35 + .../Py220_lesson04/turn_in/follow_video_2.py | 31 + .../Py220_lesson04/turn_in/follow_video_3.py | 74 ++ .../Py220_lesson04/turn_in/mailroom_oo_4.py | 312 ++++++++ .../turn_in/metaprogramming_understanding.py | 79 ++ .../turn_in/namespace_understanding.py | 113 +++ 7 files changed, 1386 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson04/turn_in/Lesson 4.ipynb create mode 100644 Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_1.py create mode 100644 Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_2.py create mode 100644 Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_3.py create mode 100644 Student/tammyd_Py220/Py220_lesson04/turn_in/mailroom_oo_4.py create mode 100644 Student/tammyd_Py220/Py220_lesson04/turn_in/metaprogramming_understanding.py create mode 100644 Student/tammyd_Py220/Py220_lesson04/turn_in/namespace_understanding.py diff --git a/Student/tammyd_Py220/Py220_lesson04/turn_in/Lesson 4.ipynb b/Student/tammyd_Py220/Py220_lesson04/turn_in/Lesson 4.ipynb new file mode 100644 index 0000000..caf3bd7 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson04/turn_in/Lesson 4.ipynb @@ -0,0 +1,742 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## Exercise #1\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "b\n", + "a\n" + ] + } + ], + "source": [ + "def a(func):\n", + " print('a')\n", + " return func\n", + "\n", + "def b(func):\n", + " print('b')\n", + " return func\n", + "\n", + "@a\n", + "@b\n", + "def foo():\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## Did you know b printed before a?\n", + "## That's because the decorator closest to def will be called first\n", + "## Then its return value is passed to the 1st decorator\n", + "## Eventually, the return value of the topmost decorator will be \n", + "## assigned to the function's name in the containing scope" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## Exercise #2\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (, line 2)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m2\u001b[0m\n\u001b[0;31m Class bla:\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "## Demo of @classmethod and @staticmethod\n", + "Class bla:\n", + " pass\n", + "\n", + " \n", + "@staticmethod\n", + "def f(arg1, arg2, arg3 ...)\n", + "\n", + "## Classmethod\n", + "\n", + "@classmethod\n", + "def f(arg1, arg2, arg3 ...)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "class Date(object):\n", + "\n", + " def __init__(self, day=0, month=0, year=0):\n", + " self.day = day\n", + " self.month = month\n", + " self.year = year\n", + "\n", + " @classmethod\n", + " def from_string(cls, date_as_string):\n", + " day, month, year = map(int, date_as_string.split('-'))\n", + " date1 = cls(day, month, year)\n", + " return date1\n", + "\n", + " @staticmethod\n", + " def is_date_valid(date_as_string):\n", + " day, month, year = map(int, date_as_string.split('-'))\n", + " return day <= 31 and month <= 12 and year <= 3999\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "date2 = Date.from_string('06-04-2018')\n", + "is_date = Date.is_date_valid('06-05-2018')" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "<__main__.Date object at 0x1047678d0>\n" + ] + } + ], + "source": [ + "print (date2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "## Note this is only checks the format of the date string not the accuracy\n", + "## of the date .\n", + "print(is_date)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "class C:\n", + " a_class_attribute = 0\n", + " def __init__(self):\n", + " self.an_instance_attribute = 0" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "c = C()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "['__class__',\n", + " '__delattr__',\n", + " '__dict__',\n", + " '__dir__',\n", + " '__doc__',\n", + " '__eq__',\n", + " '__format__',\n", + " '__ge__',\n", + " '__getattribute__',\n", + " '__gt__',\n", + " '__hash__',\n", + " '__init__',\n", + " '__init_subclass__',\n", + " '__le__',\n", + " '__lt__',\n", + " '__module__',\n", + " '__ne__',\n", + " '__new__',\n", + " '__reduce__',\n", + " '__reduce_ex__',\n", + " '__repr__',\n", + " '__setattr__',\n", + " '__sizeof__',\n", + " '__str__',\n", + " '__subclasshook__',\n", + " '__weakref__',\n", + " 'a_class_attribute',\n", + " 'an_instance_attribute']" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dir(c)" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "dir(C)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "mappingproxy({'__module__': '__main__',\n", + " 'a_class_attribute': 0,\n", + " '__init__': ,\n", + " '__dict__': ,\n", + " '__weakref__': ,\n", + " '__doc__': None})" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vars(C)" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "vars(c)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Exercise' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mExercise\u001b[0m \u001b[0;31m#3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'Exercise' is not defined" + ] + } + ], + "source": [ + "Exercise #3\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Awesome(object):\n", + " def fu(self,x):\n", + " print (\"About to execute fu(%s,%s)\"%(self,x))\n", + "\n", + " @classmethod\n", + " def class_fu(cls,x):\n", + " print (\"About to execute class_fu(%s,%s)\"%(cls,x))\n", + "\n", + " @staticmethod\n", + " def static_fu(x):\n", + " print (\"executing static_fu(%s)\"%x) \n", + "\n", + "myobj=Awesome() " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## usual way an object instance calls a method. \n", + "## The object instance, myobj, is implicitly passed as the first argument.\n", + "## \n", + "myobj.fu(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "there are 4 namespaces\n", + "the order that python searches for namespaces is local, enclosed (nonlocal), global, builtin. LEGB" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## @staticmethod\n", + "\n", + "## Lets do how @staticmethod works\n", + "## neither self (the object instance) nor cls (the class) is implicitly \n", + "## passed as the first argument. They behave like plain functions except \n", + "## that you can call them from an instance or the class:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "myobj.static_fu(1)\n", + "# executing static_fu(1)\n", + "\n", + "Awesome.static_fu('I am awesome')\n", + "# executing static_fu('I am Awesome')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## Staticmethods are used to group functions which have some logical \n", + "## connection with a class to the class.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "##Classmethod\n", + "## the class of the object instance is implicitly passed as the first \n", + "## argument instead of self.\n", + "\n", + "myobj.class_fu(1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## You can also call class_fu using the class. \n", + "## If you define something to be a classmethod, it is probably \n", + "## because you intend to call it from the class rather than from a \n", + "## class instance. \n", + "\n", + "## Note the following\n", + "## Awesome.fu(1) would have raised a TypeError, \n", + "## but Awesome.class_fu(1) works just fine:\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "Awesome.fu(1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Awesome.class_fu(1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## End of classmethod\n", + "\n", + "## To note\n", + "## fu expects 2 arguments, while myobj.fu only expects 1 argument.\n", + "## myobj is bound to fu\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(myobj.fu)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## With myobj.class_fu, myobj is not bound to class_fu, rather the class \n", + "## Awesome is bound to class_fu.\n", + "\n", + "print(Awesome.class_fu)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## Here, with a staticmethod, even though it is a method, \n", + "## myobj.static_fu just returns with no arguments \n", + "## bound. static_fu expects 1 argument, and myobj.static_fu expects \n", + "## 1 argument too.\n", + "\n", + "print(myobj.static_fu)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "## Exercise 4\n", + "\n", + "## getattr () example" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "class Person():\n", + " name = 'Wayne'\n", + " def say(self, what):\n", + " print(self.name, what)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Wayne'" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "getattr(Person, 'name')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "attr_name = 'name'" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "person = Person()" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Wayne'" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "getattr(person, attr_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Wayne Welcome to Python 220\n" + ] + } + ], + "source": [ + "getattr(person, 'say')('Welcome to Python 220')" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'Person' object has no attribute 'age'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m## getattr will raise AttributeError if attribute\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;31m## with the given name does not exist in the object:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mperson\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'age'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m: 'Person' object has no attribute 'age'" + ] + } + ], + "source": [ + "## getattr will raise AttributeError if attribute \n", + "## with the given name does not exist in the object:\n", + "getattr(person, 'age')" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [], + "source": [ + "## Exercise 5\n", + "\n", + "## setattr()\n", + "\n", + "setattr(person, 'name', 'Tamara')" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Tamara'" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "## accessing the instance attribute\n", + "person.name" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Wayne'" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "## accessing the class attribute\n", + "Person.name\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## Exercise 6\n", + "\n", + "## type Class\n", + "## applying \"type\" to an object returns the class of which the object \n", + "## is an instance of\n", + "x = [1, 2, 3]\n", + "y = \"Hello Py 220 Class\"\n", + "print(type(x), type(y))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## object x is an instance of class list\n", + "## object y is an instance of class str\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## If you apply type on the name of a \n", + "## class itself, you get the class \"type\" returned.\n", + "\n", + "print(type(list), type(str))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## Above command is same as \n", + "\n", + "print(type(x), type(y))\n", + "print(type(type(x)), type(type(y)))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## A user-defined class (or the class \"object\") is an instance of the \n", + "## class \"type\". So, we can see, that classes are created from type. \n", + "## In Python3 there is no difference between \"classes\" and \"types\". \n", + "## They are in most cases used as synonyms.\n", + "\n", + "\n", + "## The fact that classes are instances of a class \"type\" allows us to \n", + "## program metaclasses. We can create classes, which inherit from the class \n", + "## \"type\". So, a metaclass is a subclass of the class \"type\".\n", + "\n", + "## Enter Metaclasses\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_1.py b/Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_1.py new file mode 100644 index 0000000..96b5aa0 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_1.py @@ -0,0 +1,35 @@ +# a simple class for a person +class Person: + def __init__(self, first_name="", last_name="", phone=""): + self.first_name = first_name + self.last_name = last_name + self.phone = phone + + # when I write this code I don't know what attributes the object will have. this strategy is metaprogramming. + def __str__(self): + msg = ["Person:"] + # msg is doing a loop through vars(self) + for name, val in vars(self).items(): + msg.append("{}: {}".format(name, val)) + return "\n".join(msg) + + +def update_person(person): + while True: + att = input("What would you like to update for:\n" + "{}\n" + "(type 'quit' to quit) >>".format(person) + ) + if att.strip().lower()== "quit": + break + if not hasattr(person, att): + ans = input("This person does not have that attribute.\n" + "Would you like the add it? Y, [N] >> ") + if not ans.lower().startswith('y'): + continue + ans = input("What would you like to set it to? >> ") + setattr(person, att, ans) + +if __name__ == "__main__": + p1 = Person("Fred", "Jones", "206-555-1234") + update_person(p1) \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_2.py b/Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_2.py new file mode 100644 index 0000000..ff5fb06 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_2.py @@ -0,0 +1,31 @@ +class Simple(): + this = "a class attribute" + + def __init__(self): + self.that = "a instance attribute" + + # in metaprogramming, type is important. use vars() to see attributes + + # to subclass when using type, you pass the base classes in + + # functions are objects. so methods are simply attributes of a class that happen to be a function. + +def mymethod(self): + print("my method with x = {}".format(self.x)) + + +def init(self, x): + self.x = x + + +MyClass = type("MyClass", (), {'x':1, 'mymethod': mymethod, "__init__" : init}) + + + + + +if __name__ == "__main__": + mc = MyClass(5) + print(mc) + print(mc.mymethod()) + #mymethod() \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_3.py b/Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_3.py new file mode 100644 index 0000000..fd67c13 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson04/turn_in/follow_video_3.py @@ -0,0 +1,74 @@ +follow_video_3.py + +# every object in python has a metaclass and the default metaclass is type. that is, type is used to create the class +# to define a metaclass, use the metaclass keyword argument + +#class Foo(metaclass = MyMetaClass): +# pass +# same as doing "class Foo(metaclass = type)" + +# metaclass handy for when you need to manage the data from one or more classes + + +""" +Complete do-nothing metaclass example + +It serves to show when each special method of the metaclass is called. + +""" + + +class CoolMeta(type): + # manipulate before the class is created. + def __new__(meta, name, bases, dct): + print('Creating class in CoolMeta.__new__', name) + return super().__new__(meta, name, bases, dct) + + # the actual class object created + def __init__(cls, name, bases, dct): + print('Initializing class in CoolMeta.__init__', name) + super().__init__(name, bases, dct) + + # used when the __init__ is called + def __call__(cls, *args, **kw): + print('calling CoolMeta to instantiate ', cls) + return type.__call__(cls, *args, **kw) + + +class CoolClass(metaclass=CoolMeta): + def __init__(self): + print('And now my CoolClass object exists') + + +print('everything loaded, instantiate a CoolClass instance now') + +if __name__ == "__main__": + cc = CoolClass() + + + + + + +###### NAME MANGLER ###### + + +""" +class NameMangler(type): + def __new__(cls, clsname, bases, _dict): + uppercase_attr = {} + for name, val in _dict.items(): + if not name.startswith('__'): + uppercase_attr[name.upper()]= val + uppercase_attr[name] = val + else: + uppercase_attr[name] = val + + return super().__new__(cls, clsname, bases, uppercase_attr) + +class Foo(metaclass= NameMangler): + x = 1 + Y = 5 + + +""" \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson04/turn_in/mailroom_oo_4.py b/Student/tammyd_Py220/Py220_lesson04/turn_in/mailroom_oo_4.py new file mode 100644 index 0000000..c109fe4 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson04/turn_in/mailroom_oo_4.py @@ -0,0 +1,312 @@ +#!/usr/bin/env python + +""" + +This is an object oriented version of mailroom. +Class example to be used with lesson04 assignment. + +""" + + +import sys +import math +from textwrap import dedent +from mailroom_model import * + +import json_save_meta as js +from saveables import * + + + +# Utility so we have data to test with, etc. +def get_sample_data(): + """ + returns a list of donor objects to use as sample data + """ + return [Donor("Britney Spears", [653772.32, 12.17]), + Donor("Mandy Moore", [877.33]), + Donor("Christina Aguilera", [663.23, 43.87, 1.32]), + Donor("Queen Bey", [1663.23, 4300.87, 10432.0]), + ] + + +class Donor(js.JsonSaveable): + """ + class to hold the information about a single donor + """ + + def __init__(self, name, donations=None): + """ + create a new Donor object + :param name: the full name of the donor + :param donations=None: iterable of past donations + """ + + self.norm_name = self.normalize_name(name) + self.name = name.strip() + if donations is None: + self.donations = [] + else: + self.donations = list(donations) + + @staticmethod + def normalize_name(name): + """ + return a normalized version of a name to use as a comparison key + simple enough to not be in a method now, but maybe you'd want to make it fancier later. + """ + return name.lower().strip().replace(" ", "") + + @property + def last_donation(self): + """ + The most recent donation made + """ + try: + return self.donations[-1] + except IndexError: + return None + + @property + def total_donations(self): + return sum(self.donations) + + @property + def average_donation(self): + return self.total_donations / len(self.donations) + + def add_donation(self, amount): + """ + add a new donation + """ + amount = float(amount) + if amount <= 0.0: + raise ValueError("Donation must be greater than zero") + self.donations.append(amount) + + +class DonorDB(): + """ + encapsulation of the entire database of donors and data associated with them. + """ + + def __init__(self, donors=None): + """ + Initialize a new donor database + :param donors=None: iterable of Donor objects + """ + if donors is None: + self.donor_data = {} + else: + self.donor_data = {d.norm_name: d for d in donors} + + # def save_to_file(self, filename): + # with open(filename, 'w') as outfile: + # self.to_json(outfile) + + # @classmethod + # def load_from_file(cls, filename): + # with open(filename, 'r') as infile: + # obj = js.from_json(infile) + # return obj + + @property + def donors(self): + """ + an iterable of all the donors + """ + return self.donor_data.values() + + def list_donors(self): + """ + creates a list of the donors as a string, so they can be printed + Not calling print from here makes it more flexible and easier to + test + """ + listing = ["Donor list:"] + for donor in self.donors: + listing.append(donor.name) + return "\n".join(listing) + + def find_donor(self, name): + """ + find a donor in the donor db + :param: the name of the donor + :returns: The donor data structure -- None if not in the self.donor_data + """ + return self.donor_data.get(Donor.normalize_name(name)) + + def add_donor(self, name): + """ + Add a new donor to the donor db + :param: the name of the donor + :returns: the new Donor data structure + """ + donor = Donor(name) + self.donor_data[donor.norm_name] = donor + return donor + + def gen_letter(self, donor): + """ + Generate a thank you letter for the donor + :param: donor tuple + :returns: string with letter + note: This doesn't actually write to a file -- that's a separate + function. This makes it more flexible and easier to test. + """ + return dedent('''Dear {0:s}, + Thank you for your very kind donation of ${1:.2f}. + It will be put to very good use. + Sincerely, + -The Team + '''.format(donor.name, donor.last_donation) + ) + + @staticmethod + def sort_key(item): + # used to sort on name in self.donor_data + return item[1] + + def generate_donor_report(self): + """ + Generate the report of the donors and amounts donated. + :returns: the donor report as a string. + """ + # First, reduce the raw data into a summary list view + report_rows = [] + for donor in self.donor_data.values(): + name = donor.name + gifts = donor.donations + total_gifts = donor.total_donations + num_gifts = len(gifts) + avg_gift = donor.average_donation + report_rows.append((name, total_gifts, num_gifts, avg_gift)) + + # sort the report data + report_rows.sort(key=self.sort_key) + report = [] + report.append("{:25s} | {:11s} | {:9s} | {:12s}".format("Donor Name", + "Total Given", + "Num Gifts", + "Average Gift")) + report.append("-" * 66) + for row in report_rows: + report.append("{:25s} ${:10.2f} {:9d} ${:11.2f}".format(*row)) + return "\n".join(report) + + def save_letters_to_disk(self): + """ + make a letter for each donor, and save it to disk. + """ + for donor in self.donor_data.values(): + print("Writing a letter to:", donor.name) + letter = self.gen_letter(donor) + # I don't like spaces in filenames... + filename = donor.name.replace(" ", "_") + ".txt" + open(filename, 'w').write(letter) + + +# User-interaction code +# Above this is all the logic code +# The stuff you'd need if you had a totally different UI.different +# below is code only for the command line interface. + + +# import sys +# import math + +# # handy utility to make pretty printing easier +# from textwrap import dedent + +# from mailroom import model + +# create a DB with the sample data +db = DonorDB(get_sample_data()) + + +def main_menu_selection(): + """ + Print out the main application menu and then read the user input. + """ + action = input(dedent(''' + Choose an action: + 1 - Send a Thank You + 2 - Create a Report + 3 - Send letters to everyone + 4 - Quit + > ''')) + return action.strip() + + +def send_thank_you(): + """ + Record a donation and generate a thank you message. + """ + # Read a valid donor to send a thank you from, handling special commands to + # let the user navigate as defined. + while True: + name = input("Enter a donor's name" + "(or 'list' to see all donors or 'menu' to exit)> ").strip() + if name == "list": + print(db.list_donors()) + elif name == "menu": + return + else: + break + + # Now prompt the user for a donation amount to apply. Since this is + # also an exit point to the main menu, we want to make sure this is + # done before mutating the db. + while True: + amount_str = input("Enter a donation amount (or 'menu' to exit)> ").strip() + if amount_str == "menu": + return + # Make sure amount is a valid amount before leaving the input loop + try: + amount = float(amount_str) + # extra check here -- unlikely that someone will type "NaN", but + # it IS possible, and it is a valid floating point number: + # http://en.wikipedia.org/wiki/NaN + if math.isnan(amount) or math.isinf(amount) or round(amount, 2) == 0.00: + raise ValueError + # in this case, the ValueError could be raised by the float() call, or by the NaN-check + except ValueError: + print("error: donation amount is invalid\n") + else: + break + + # If this is a new user, ensure that the database has the necessary + # data structure. + donor = db.find_donor(name) + if donor is None: + donor = db.add_donor(name) + + # Record the donation + donor.add_donation(amount) + print(db.gen_letter(donor)) + + +def print_donor_report(): + print(db.generate_donor_report()) + + +def quit(): + sys.exit(0) + + +def main(): + selection_dict = {"1": send_thank_you, + "2": print_donor_report, + "3": db.save_letters_to_disk, + "4": quit} + + while True: + selection = main_menu_selection() + try: + selection_dict[selection]() + except KeyError: + print("error: menu selection is invalid!") + +if __name__ == "__main__": + + main() \ No newline at end of file diff --git a/Student/tammyd_Py220/Py220_lesson04/turn_in/metaprogramming_understanding.py b/Student/tammyd_Py220/Py220_lesson04/turn_in/metaprogramming_understanding.py new file mode 100644 index 0000000..5238763 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson04/turn_in/metaprogramming_understanding.py @@ -0,0 +1,79 @@ +#metaprogramming_understanding.py + +In [22]: class Dummy: + ...: pass + ...: + ...: + +In [23]: obj = Dummy + ...: + +In [24]: + +In [24]: vars(obj) +Out[24]: +mappingproxy({'__module__': '__main__', + '__dict__': , + '__weakref__': , + '__doc__': None}) + +In [25]: setattr(obj, "name", "Fred") + +In [26]: vars(obj) +Out[26]: +mappingproxy({'__module__': '__main__', + '__dict__': , + '__weakref__': , + '__doc__': None, + 'name': 'Fred'}) + +In [27]: obj.name +Out[27]: 'Fred' + +In [28]: + +# can also get the value using getattr. they are exactly the same + + +# delattr +In [31]: delattr(obj, "name") + +In [32]: vars(obj) +Out[32]: +mappingproxy({'__module__': '__main__', + '__dict__': , + '__weakref__': , + '__doc__': None}) + +In [33]: obj.name +--------------------------------------------------------------------------- +AttributeError Traceback (most recent call last) + in () +----> 1 obj.name + +AttributeError: type object 'Dummy' has no attribute 'name' + +# what's the difference from the usual way? getattr and setattr use strings. using a string in a variable allows you to manipulate the code. no need to know the attribute up front + + +In [34]: att_name = "this" + +In [35]: att_value = "something" + +In [36]: setattr(obj, att_name, att_value) + +In [37]: vars(obj) +Out[37]: +mappingproxy({'__module__': '__main__', + '__dict__': , + '__weakref__': , + '__doc__': None, + 'this': 'something'}) + +# now we can see that "this" was set to "something" even though it was coming from variable names + +# enables us to manipulate objects at runtime without knowing the names when you write the code. + +######### THIS WHAT HE MEANS WHEN HE SAYS METAPROGRAMMING. ######### + + diff --git a/Student/tammyd_Py220/Py220_lesson04/turn_in/namespace_understanding.py b/Student/tammyd_Py220/Py220_lesson04/turn_in/namespace_understanding.py new file mode 100644 index 0000000..f105855 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson04/turn_in/namespace_understanding.py @@ -0,0 +1,113 @@ +#namespace_understanding.py + +# Spent multiple days trying to understand namespace and metaprogramming and spoke to the instructor about my difficulty. +# Submitting lesson notes to show that I went through all the material, gave my best effort and will continue to learn this concept. + +# all objects in Python have their own namespaces +# namespaces are a core part of the python langugage +# using vars returns the actual namespace, not a copy + +In [3]: class C: + ...: a = 5 + ...: b = 6 + ...: def __init__(self): + ...: self.x = 32 + ...: self.y = 64 + ...: + +In [4]: vars(C) +Out[4]: +mappingproxy({'__module__': '__main__', #vars(C) returned a mapping proxy + 'a': 5, + 'b': 6, + '__init__': , + '__dict__': , + '__weakref__': , + '__doc__': None}) + + +In [5]: c = C() + +In [6]: vars(c) +Out[6]: {'x': 32, 'y': 64} + +# dir walks the class hierarchy of a class object. this includes the instance attributes, class attributes as well as dunder methods. +#vars returns the actual namespace of that value object + + +In [8]: local_ns = vars() + +In [9]: fred +--------------------------------------------------------------------------- +NameError Traceback (most recent call last) + in () +----> 1 fred + +NameError: name 'fred' is not defined + +In [10]: local_ns['fred'] = "something" + +In [11]: fred +Out[11]: 'something' + +In [12]: local_ns['fred'] +Out[12]: 'something' + +# able to access names from the namespace dict and from the local ns in the usual way.usual +# did not use vars to access the namespace because it would change the variable all throughout + + +In [13]: cns = vars(C) + +In [14]: cns +Out[14]: +mappingproxy({'__module__': '__main__', + 'a': 5, + 'b': 6, + '__init__': , + '__dict__': , + '__weakref__': , + '__doc__': None}) + +In [15]: cns['fred'] = 'something' +--------------------------------------------------------------------------- +TypeError Traceback (most recent call last) + in () +----> 1 cns['fred'] = 'something' + +TypeError: 'mappingproxy' object does not support item assignment + +In [16]: C.fred +--------------------------------------------------------------------------- +AttributeError Traceback (most recent call last) + in () +----> 1 C.fred + +AttributeError: type object 'C' has no attribute 'fred' + +In [17]: C.fred = 'something' + +In [18]: C.fred +Out[18]: 'something' + +In [19]: cns['Fred'] +--------------------------------------------------------------------------- +KeyError Traceback (most recent call last) + in () +----> 1 cns['Fred'] + +KeyError: 'Fred' + +In [20]: cns['fFred'] +--------------------------------------------------------------------------- +KeyError Traceback (most recent call last) + in () +----> 1 cns['fFred'] + +KeyError: 'fFred' + +In [21]: cns['fred'] +Out[21]: 'something' + +# if you add an attribute to a class in the usual way w/ assignment, you have updated the mapping proxy object + From eff095cbbf27ff61ce00c0c9d6782fddc1f95f1c Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Mon, 9 Jul 2018 23:38:08 -0700 Subject: [PATCH 14/15] commit additional work for activity10 --- Student/tammyd_Py220/Py220_lesson10/cython.py | 71 +++++++++++++++++++ .../Py220_lesson10/cython_jupyter_nb.py | 26 +++++++ .../Py220_lesson10/cython_terminal_window.txt | 28 ++++++++ 3 files changed, 125 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson10/cython.py create mode 100644 Student/tammyd_Py220/Py220_lesson10/cython_jupyter_nb.py create mode 100644 Student/tammyd_Py220/Py220_lesson10/cython_terminal_window.txt diff --git a/Student/tammyd_Py220/Py220_lesson10/cython.py b/Student/tammyd_Py220/Py220_lesson10/cython.py new file mode 100644 index 0000000..6a33b2d --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson10/cython.py @@ -0,0 +1,71 @@ +""" +Exploring Cython + +Code with notes + +""" + +import math +lon1, lat1, lon2, lat2 = -72.345, 34.323, -61.823, 54.826 + +def great_circle_raw(lon1, lat1, lon2, lat2): + radius = 3956 # miles + x = math.pi / 180.0 + a = (90.0 - lat1) * (x) + b = (90.0 - lat2) * (x) + theta = (lon2 - lon1) * (x) + c = math.acos((math.cos(a) * math.cos(b)) + (math.sin(a) * math.cos(theta))) + return radius * c + + +# function with acos factored out to a function +def calculate_acos(a, b, theta): + return math.acos((math.cos(a) * math.cos(b)) + (math.sin(a) * math.sin(b) * math.cos(theta))) + + +def great_circle_acos(lon1, lat1, lon2, lat2): + radius = 3956 # mile.s + x = math.pi / 180 + a = (90.0 - lat1) * (x) + b = (90.0 - lat2) * (x) + theta = (lon2 - lon1) * (x) + # c = math.acos((math.cos(a) * math.cos(b)) + (math.sin(a) * math.cos(theta))) + # this time cal call the function instead + c = calculate_Acos(a, b, theta) + return radius * c + + +# Another variation. factoring out more +# great circle algorithm with most steps factored out as fuctions + +def calculate_x(): + return math.pi / 180.0 + + +def calculate_coordinate(lat, x): + return (90.0 - lat) * x + + +def calculate_theta(lon2, lon1, x): + return (lon2 - lon1) * x + + +def great_circle_factored(lon1, lat1, lon2, lat2): + radius = 3956 # miles + # replaced (x = math.pi / 180) with: + x = calculate_x() + # replaced (a = (90.0 - lat1) * (x)) with: + a = calculate_coordinate(lat1, x) + # replaced (b = (90.0 - lat2) * (x)) with: + b = calculate_coordinate(lat2, x) + # replaced (theta = (lon2 - lon1) * (x)) with: + theta = calculate_theta(lon2, lon1, x) + c = calculate_acos(a, b, theta) + return radius * c + + +if __name__ == "__main__": + # multiple ways to run this. run each with different interpreters + great_circle_raw(lon1, lat1, lon2, lat2) + # great_circle_acos(lon1, lat1, lon2, lat2) + # great_circle_factored(lon1, lat1, lon2, lat2) diff --git a/Student/tammyd_Py220/Py220_lesson10/cython_jupyter_nb.py b/Student/tammyd_Py220/Py220_lesson10/cython_jupyter_nb.py new file mode 100644 index 0000000..6cc05e8 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson10/cython_jupyter_nb.py @@ -0,0 +1,26 @@ + +# coding: utf-8 + +# In[3]: + + +get_ipython().run_line_magic('load_ext', 'Cython') + + +# In[4]: + + +get_ipython().run_cell_magic('cython', '', '# purely about speed\ncdef int a = 0\nfor i in range(10):\n a += 1\nprint(a)') + + +# In[6]: + + +#tells you what cython is up to +%%cython --annotate + +cdef int a = 0 +for i in range(10): + a += 1 +print(a) + diff --git a/Student/tammyd_Py220/Py220_lesson10/cython_terminal_window.txt b/Student/tammyd_Py220/Py220_lesson10/cython_terminal_window.txt new file mode 100644 index 0000000..0d069aa --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson10/cython_terminal_window.txt @@ -0,0 +1,28 @@ +Last login: Mon Jul 9 23:20:26 on ttys000 +Tammys-MBP:~ tammydo$ which python3 +/Library/Frameworks/Python.framework/Versions/3.6/bin/python3 +Tammys-MBP:~ tammydo$ mkvirtualenv -p python3 cython2 +Running virtualenv with interpreter /Library/Frameworks/Python.framework/Versions/3.6/bin/python3 +Using base prefix '/Library/Frameworks/Python.framework/Versions/3.6' +New python executable in /Users/tammydo/.virtualenvs/cython2/bin/python3 +Also creating executable in /Users/tammydo/.virtualenvs/cython2/bin/python +Installing setuptools, pip, wheel... done. +virtualenvwrapper.user_scripts creating /Users/tammydo/.virtualenvs/cython2/bin/predeactivate +virtualenvwrapper.user_scripts creating /Users/tammydo/.virtualenvs/cython2/bin/postdeactivate +virtualenvwrapper.user_scripts creating /Users/tammydo/.virtualenvs/cython2/bin/preactivate +virtualenvwrapper.user_scripts creating /Users/tammydo/.virtualenvs/cython2/bin/postactivate +virtualenvwrapper.user_scripts creating /Users/tammydo/.virtualenvs/cython2/bin/get_env_details +(cython2) Tammys-MBP:~ tammydo$ pip install cython +Collecting cython + Downloading https://files.pythonhosted.org/packages/bb/7c/236ca25870bf6f369ba6690b3585d8617592b3f9b049d2bdb3d96ec89bc2/Cython-0.28.4-cp36-cp36m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl (5.3MB) + 100% |████████████████████████████████| 5.3MB 2.2MB/s +Installing collected packages: cython +Successfully installed cython-0.28.4 +(cython2) Tammys-MBP:~ tammydo$ pip list +Package Version +---------- ------- +Cython 0.28.4 +pip 10.0.1 +setuptools 40.0.0 +wheel 0.31.1 +(cython2) Tammys-MBP:~ tammydo$ \ No newline at end of file From bb52ccdcfe8e06f37642b5672164deba23ae620b Mon Sep 17 00:00:00 2001 From: Tammy Do Date: Mon, 9 Jul 2018 23:50:58 -0700 Subject: [PATCH 15/15] commit lesson04 lab and additiona in class work. --- .../Py220_lesson04/Lesson 4.ipynb | 703 ++++++++++++++++++ .../tammyd_Py220/Py220_lesson04/cool_meta.py | 34 + .../Py220_lesson04/get_set_attr.py | 48 ++ 3 files changed, 785 insertions(+) create mode 100644 Student/tammyd_Py220/Py220_lesson04/Lesson 4.ipynb create mode 100644 Student/tammyd_Py220/Py220_lesson04/cool_meta.py create mode 100644 Student/tammyd_Py220/Py220_lesson04/get_set_attr.py diff --git a/Student/tammyd_Py220/Py220_lesson04/Lesson 4.ipynb b/Student/tammyd_Py220/Py220_lesson04/Lesson 4.ipynb new file mode 100644 index 0000000..bc4a52e --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson04/Lesson 4.ipynb @@ -0,0 +1,703 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "## Exercise #1\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "b\n", + "a\n" + ] + } + ], + "source": [ + "def a(func):\n", + " print('a')\n", + " return func\n", + "\n", + "def b(func):\n", + " print('b')\n", + " return func\n", + "\n", + "@a\n", + "@b\n", + "def foo():\n", + " pass" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "## Did you know b printed before a?\n", + "## That's because the decorator closest to def will be called first\n", + "## Then its return value is passed to the 1st decorator\n", + "## Eventually, the return value of the topmost decorator will be \n", + "## assigned to the function's name in the containing scope" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "## Exercise #2\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "## Demo of @classmethod and @staticmethod\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "class Date(object):\n", + "\n", + " def __init__(self, day=0, month=0, year=0):\n", + " self.day = day\n", + " self.month = month\n", + " self.year = year\n", + "\n", + " @classmethod\n", + " def from_string(cls, date_as_string):\n", + " day, month, year = map(int, date_as_string.split('-'))\n", + " date1 = cls(day, month, year)\n", + " return date1\n", + "\n", + " @staticmethod\n", + " def is_date_valid(date_as_string):\n", + " day, month, year = map(int, date_as_string.split('-'))\n", + " return day <= 31 and month <= 12 and year <= 3999\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "date2 = Date.from_string('06-04-2018')\n", + "is_date = Date.is_date_valid('06-05-2018')" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "<__main__.Date object at 0x1049a7d68>\n" + ] + } + ], + "source": [ + "print (date2)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "True\n" + ] + } + ], + "source": [ + "## Note this is only checks the format of the date string not the accuracy\n", + "## of the date .\n", + "print(is_date)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Exercise' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mExercise\u001b[0m \u001b[0;31m#3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'Exercise' is not defined" + ] + } + ], + "source": [ + "Exercise #3\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "class Awesome(object):\n", + " def fu(self,x):\n", + " print (\"About to execute fu(%s,%s)\"%(self,x))\n", + "\n", + " @classmethod\n", + " def class_fu(cls,x):\n", + " print (\"About to execute class_fu(%s,%s)\"%(cls,x))\n", + "\n", + " @staticmethod\n", + " def static_fu(x):\n", + " print (\"executing static_fu(%s)\"%x) \n", + "\n", + "myobj=Awesome() " + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "About to execute fu(<__main__.Awesome object at 0x1049b6fd0>,1)\n" + ] + } + ], + "source": [ + "## usual way an object instance calls a method. \n", + "## The object instance, myobj, is implicitly passed as the first argument.\n", + "## \n", + "myobj.fu(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "## @staticmethod\n", + "\n", + "## Lets do how @staticmethod works\n", + "## neither self (the object instance) nor cls (the class) is implicitly \n", + "## passed as the first argument. They behave like plain functions except \n", + "## that you can call them from an instance or the class:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "executing static_fu(1)\n", + "executing static_fu(I am awesome)\n" + ] + } + ], + "source": [ + "myobj.static_fu(1)\n", + "# executing static_fu(1)\n", + "\n", + "Awesome.static_fu('I am awesome')\n", + "# executing static_fu('I am Awesome')" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "## Staticmethods are used to group functions which have some logical \n", + "## connection with a class to the class.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "About to execute class_fu(,1)\n" + ] + } + ], + "source": [ + "##Classmethod\n", + "## the class of the object instance is implicitly passed as the first \n", + "## argument instead of self.\n", + "\n", + "myobj.class_fu(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "## You can also call class_fu using the class. \n", + "## If you define something to be a classmethod, it is probably \n", + "## because you intend to call it from the class rather than from a \n", + "## class instance. \n", + "\n", + "## Note the following\n", + "## Awesome.fu(1) would have raised a TypeError, \n", + "## but Awesome.class_fu(1) works just fine:\n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "fu() missing 1 required positional argument: 'x'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mAwesome\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfu\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m: fu() missing 1 required positional argument: 'x'" + ] + } + ], + "source": [ + "Awesome.fu(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "About to execute class_fu(,1)\n" + ] + } + ], + "source": [ + "Awesome.class_fu(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "## End of classmethod\n", + "\n", + "## To note\n", + "## fu expects 2 arguments, while myobj.fu only expects 1 argument.\n", + "## myobj is bound to fu\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ">\n" + ] + } + ], + "source": [ + "print(myobj.fu)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + ">\n" + ] + } + ], + "source": [ + "## With myobj.class_fu, myobj is not bound to class_fu, rather the class \n", + "## Awesome is bound to class_fu.\n", + "\n", + "print(Awesome.class_fu)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "## Here, with a staticmethod, even though it is a method, \n", + "## myobj.static_fu just returns with no arguments \n", + "## bound. static_fu expects 1 argument, and myobj.static_fu expects \n", + "## 1 argument too.\n", + "\n", + "print(myobj.static_fu)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "## Exercise 4\n", + "\n", + "## getattr () example" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "class Person():\n", + " name = 'Wayne'\n", + " def say(self, what):\n", + " print(self.name, what)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Wayne'" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "getattr(Person, 'name')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "attr_name = 'name'" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [], + "source": [ + "person = Person()" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Wayne'" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "getattr(person, attr_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Wayne Welcome to Python 220\n" + ] + } + ], + "source": [ + "getattr(person, 'say')('Welcome to Python 220')" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'Person' object has no attribute 'age'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m## getattr will raise AttributeError if attribute\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;31m## with the given name does not exist in the object:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mgetattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mperson\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'age'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m: 'Person' object has no attribute 'age'" + ] + } + ], + "source": [ + "## getattr will raise AttributeError if attribute \n", + "## with the given name does not exist in the object:\n", + "getattr(person, 'age')" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "## Exercise 5\n", + "\n", + "## setattr()\n", + "\n", + "setattr(person, 'name', 'Tamara')" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Tamara'" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "## accessing the instance attribute\n", + "person.name" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Wayne'" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "## accessing the class attribute\n", + "Person.name\n" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " \n" + ] + } + ], + "source": [ + "## Exercise 6\n", + "\n", + "## type Class\n", + "## applying \"type\" to an object returns the class of which the object \n", + "## is an instance of\n", + "x = [1, 2, 3]\n", + "y = \"Hello Py 220 Class\"\n", + "print(type(x), type(y))" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [], + "source": [ + "## object x is an instance of class list\n", + "## object y is an instance of class str\n" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " \n" + ] + } + ], + "source": [ + "## If you apply type on the name of a \n", + "## class itself, you get the class \"type\" returned.\n", + "\n", + "print(type(list), type(str))" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " \n", + " \n" + ] + } + ], + "source": [ + "## Above command is same as \n", + "\n", + "print(type(x), type(y))\n", + "print(type(type(x)), type(type(y)))\n" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [], + "source": [ + "## A user-defined class (or the class \"object\") is an instance of the \n", + "## class \"type\". So, we can see, that classes are created from type. \n", + "## In Python3 there is no difference between \"classes\" and \"types\". \n", + "## They are in most cases used as synonyms.\n", + "\n", + "\n", + "## The fact that classes are instances of a class \"type\" allows us to \n", + "## program metaclasses. We can create classes, which inherit from the class \n", + "## \"type\". So, a metaclass is a subclass of the class \"type\".\n", + "\n", + "## Enter Metaclasses\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Student/tammyd_Py220/Py220_lesson04/cool_meta.py b/Student/tammyd_Py220/Py220_lesson04/cool_meta.py new file mode 100644 index 0000000..fdaaea1 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson04/cool_meta.py @@ -0,0 +1,34 @@ +""" +Complete do-nothing metaclass example + +It serves to show when each special method of the metaclass is called. + +""" + + +class CoolMeta(type): + # manipulate before the class is created. + def __new__(meta, name, bases, dct): + print('Creating class in CoolMeta.__new__', name) + return super().__new__(meta, name, bases, dct) + + # the actual class object created + def __init__(cls, name, bases, dct): + print('Initializing class in CoolMeta.__init__', name) + super().__init__(name, bases, dct) + + # used when the __init__ is called + def __call__(cls, *args, **kw): + print('calling CoolMeta to instantiate ', cls) + return type.__call__(cls, *args, **kw) + + +class CoolClass(metaclass=CoolMeta): + def __init__(self): + print('And now my CoolClass object exists') + + +print('everything loaded, instantiate a CoolClass instance now') + +if __name__ == "__main__": + cc = CoolClass() diff --git a/Student/tammyd_Py220/Py220_lesson04/get_set_attr.py b/Student/tammyd_Py220/Py220_lesson04/get_set_attr.py new file mode 100644 index 0000000..30beb77 --- /dev/null +++ b/Student/tammyd_Py220/Py220_lesson04/get_set_attr.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 + +""" +Manipulating attributes + +Example code for manipulating attributes +""" + + +# A simple class for a person +class Person: + def __init__(self, first_name="", last_name="", phone=""): + self.first_name = first_name + self.last_name = last_name + self.phone = phone + + def __str__(self): + msg = ["Person:"] + for name, val in vars(self).items(): + msg.append("{}: {}".format(name, val)) + return "\n".join(msg) + + +def update_person(person): + while True: + att = input("What would you like to update for:\n" + "{}\n" + '(type "quit" to quit) >> '.format(person) + ) + if att.strip().lower() == "quit": + break + if not hasattr(person, att): + ans = input("This person does not have that attribute.\n" + "Would you like to add it? Y,[N] >> ") + if not ans.lower().startswith('y'): + continue + ans = input("What would you like to set it to? >> ") + setattr(person, att, ans) + + +if __name__ == "__main__": + # a little test code: + + # create a couple people: + p1 = Person("Fred", "Jones", "206-555-1234") + update_person(p1) + +