{ "cells": [ { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# [X-Village] Lesson03 - Object and Function\n", "speaker: Amber(吳思嬋)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Object\n", "---\n", "**In Python, we do things with stuff.**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## What is an object ?\n", "---" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "### Everything in Python is an object !!!" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Built-in Types Object\n", "---\n", "Numbers, Strings, Lists, Dictionarys, Tuple, Files, Sets, etc." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Built-in Types Object example\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# Number\n", "12 # integer\n", "12.5 # float-point\n", "-12.5 # negative\n", "\n", "# String\n", "'Hello Word'\n", "\n", "# list\n", "[1, 2, 3, 4]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# variable a, object\n", "a = 3\n", "a = 'Hello World'" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## The Dynamic Typing Interlude\n", "---\n", "In Python, types are determined automatically at runtime." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Variables, Objects, and References" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "## Variables (i.e. name)\n", "---\n", "\n", "**Variables are created when assigned, can reference any type of object, and must be assigned before they are referenced.**\n", "* Variable creation\n", "* Variable types\n", "* Variable use" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "a = 3 # Assign a name to an object\n", "\n", "# 1. Create an object to represent the value 3.\n", "# 2. Create the variable a, if it does not yet exist. \n", "# 3. Link the variable a to the new object 3." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "![](https://i.imgur.com/qaynkKr.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Types Live with Objects, Not Variables" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "a = 3 # It's an integer\n", "a = 'spam' # Now it's a string\n", "a = 1.23 # Now it's a floating point" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Shared References (Shared Object)\n", "---\n", "![](https://i.imgur.com/ywCbsuH.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "![](https://i.imgur.com/fsAyUyM.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "![](https://i.imgur.com/Y27ye4P.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Shared References and In-Place Changes\n", "---\n", "* immutable objects\n", " * int, float, bool, str, etc.\n", "* mutable objects\n", " * list, set, dict, etc." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Objects are Garbage-Collected\n", "---\n", "Whenever a name is assigned to a new object, the space held by the prior object is reclaimed if it is not referenced by any other name or object." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "a = 3 # It's an integer\n", "a = 'spam' # Now it's a string" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "x = 42\n", "x = 'shrubbery' # Reclaim 42 now (unless referenced elsewhere)\n", "x = 3.1415 # Reclaim 'shrubbery' now\n", "x = [1, 2, 3] # Reclaim 3.1415 now" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Exercise1\n", "經過這三個statements, print(a)的結果為何?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# exercise1\n", "a = \"Hello\"\n", "b = a\n", "b = \"World\"\n", "print(a)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello\n" ] } ], "source": [ "# answer\n", "a = \"Hello\"\n", "b = a\n", "b = \"World\"\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Exercise2\n", "經過這三個statements, print(a)的結果為何?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# exercise\n", "a = [\"Hello\"]\n", "b = a\n", "b[0] = \"World\"\n", "print(a)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "['World']\n" ] } ], "source": [ "# answer\n", "a = [\"Hello\"]\n", "b = a\n", "b[0] = \"World\"\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Function\n", "---\n", "1. **Function Basics**\n", "2. Scopes\n", "3. Arguments\n", "4. Recursive Functions" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Coding Function: def Statements (1)\n", "* keyword: def\n", "* fucntion name, argument, return statement" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "![](https://i.imgur.com/cCia0rA.png)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World\n" ] } ], "source": [ "# example1\n", "def f():\n", " # function body\n", " print(\"Hello World\")\n", "\n", "f() # function call" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World\n" ] } ], "source": [ "# example2\n", "def f(n):\n", " # function body\n", " print(n)\n", "\n", "x = \"Hello World\"\n", "f(x) # function call" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "120\n" ] } ], "source": [ "# example 3\n", "def g(n):\n", " # function body\n", " tmp = 1\n", " for i in range(1, n+1 ,1):\n", " tmp = tmp * i\n", " return tmp\n", "\n", "x = g(5) # function call, 5*4*3*2*1\n", "print(x)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Bill: 154.5\n" ] } ], "source": [ "# example 4\n", "# Computes the total cost, including 3% sales tax\n", "# on number items at a cost of price each\n", "def total_cost(number, price):\n", " # function body\n", " tax_rate = 0.03 # 3% sales tax\n", " cost = number * price\n", " total = cost + (cost*tax_rate)\n", " return total\n", "\n", "n = 5\n", "p = 30\n", "bill = total_cost(n, p)\n", "print('Bill: ',bill)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### enclosing function\n", "---\n", "![](https://i.imgur.com/XCS7yHE.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Question\n", "如果撰寫程式時,將 return object 的 object 省略,在呼叫 function 的階段會發生什麼事?" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# return statement without object\n", "def f():\n", " x = 5\n", " return\n", "\n", "y = f() # function call\n", "print(y)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "None\n" ] } ], "source": [ "# answer\n", "def f():\n", " x = 5\n", " return\n", "\n", "y = f() # function call\n", "print(y)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "None\n" ] } ], "source": [ "# without return statement\n", "def f():\n", " x=5\n", "\n", "y = f()\n", "print(y) " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Coding Function: def Statements (2)\n", "---\n", "* **def statement** 是 executable code\n", "* keyword **def** 會建立 function object, 將 fucntion object assign 給 function name\n", "* keywood **return** 會回傳 object 給 caller\n", "* 傳遞 Arguments 的方式,使用 assignment\n", "* Arguments, return objects, 和 variables 都不需要事先宣告型別" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Why use function\n", "* **Maximizing code reuse**\n", "* Procedural decompsition" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "scrolled": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "result1: 正常\n", "result2: 過重\n" ] } ], "source": [ "# 公式:體重(公斤) / 身高^2(公尺^2)\n", "# 過輕:BMI < 18.5; 正常:18.5≦ BMI<24; 過重:24≦BMI\n", "def bmi(height, weight):\n", " calculate = weight / (height*height)\n", " if calculate < 18.5:\n", " result = '過輕'\n", " return result\n", " elif 18.5 < calculate and calculate < 24:\n", " result = '正常'\n", " return result\n", " else:\n", " result='過重'\n", " return result\n", " \n", "h = 1.63 #公尺\n", "w = 50 #公斤\n", "r = bmi(h, w)\n", "print(\"result1: \", r) # 正常\n", "\n", "h = 1.80 #公尺\n", "w = 88 #公斤\n", "r = bmi(h, w)\n", "print(\"result2: \", r) # 過重" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "result1: 正常\n", "result2: 過重\n" ] } ], "source": [ "height = 1.63 #公尺\n", "weight = 50 #公斤\n", "calculate = weight / (height*height)\n", "if calculate < 18.5:\n", " result = '過輕'\n", "elif 18.5 < calculate and calculate < 24:\n", " result = '正常'\n", "else:\n", " result='過重'\n", "print(\"result1: \", result)\n", " \n", "height = 1.80 #公尺\n", "weight = 88 #公斤\n", "calculate = weight / (height*height)\n", "if calculate < 18.5:\n", " result = '過輕'\n", "elif 18.5 < calculate and calculate < 24:\n", " result = '正常'\n", "else:\n", " result='過重'\n", "print(\"result2: \", result)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Why use function\n", "* Maximizing code reuse\n", "* **Procedural decompsition**" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# Procedural decopsition example\n", "# pizza-making robot\n", "def mixing_the_dough() #和麵\n", "def rolling_it_out() #桿麵\n", "def adding_toppings() #放料\n", "def baking_it() #烤" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### In general, functions are about procedure\n", "* how to do something, rather than what you’re doing it to ! " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Exercise\n", "---\n", "寫一個function,用途計算數字的平方根。\n", "* example\n", " * 4的平方根為2\n", " * 9的平方根為3\n", " * 2的平方根為1.4142...." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "import math\n", "x = math.sqrt(4)\n", "print(x)\n", "\n", "y = math.sqrt(2)\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Do not reinvent the wheel !! " ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### 練習1: MxM_multiplication (5min) - 列入課堂成績\n", "---\n", "請定義一個function f,參數n。\n", "呼叫function時,傳入整數m,function 會印出 m x m 的乘法表。\n", "\n", "* 提示:print 使用 end='' 可以不印出換行符號'\\n'\n", "* example:\n", " * f(9)\n", " * [output](https://i.imgur.com/0w5ajUv.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### 練習2: swap (5min) - 列入課堂成績\n", "---\n", "定義一個function f,可以將 a, b 的值互換後,需回傳值回來。\n", "* example: \n", " * a=1, b=2\n", " * (a, b) = f(a, b)\n", " * output: a=2, b=1" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### 練習3: judge_big_lower (5min) - 列入課堂成績\n", "---\n", "定義一個function f, 判斷a, b 大小關係, 回傳字串結果, a>b, a=b 或 a" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Scope example\n", "---\n", "* Global names: x, f\n", "* Local names: y, z\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "100" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Global scope\n", "x = 99 # X and f assigned in module: global\n", "def f(y): # Y and Z assigned in function: locals\n", " # Local scope\n", " z = x + y # X is a global\n", " return z\n", "\n", "f(1) # function1 in module: result=100" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## The Built-in Scope\n", "---\n", "* 在 module *builtins* 中定義的name, 都屬於 built-in scope" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "data": { "text/plain": [ "['ArithmeticError',\n", " 'AssertionError',\n", " 'AttributeError',\n", " 'BaseException',\n", " 'BlockingIOError',\n", " 'BrokenPipeError',\n", " 'BufferError',\n", " 'BytesWarning',\n", " 'ChildProcessError',\n", " 'ConnectionAbortedError',\n", " 'ConnectionError',\n", " 'ConnectionRefusedError',\n", " 'ConnectionResetError',\n", " 'DeprecationWarning',\n", " 'EOFError',\n", " 'Ellipsis',\n", " 'EnvironmentError',\n", " 'Exception',\n", " 'False',\n", " 'FileExistsError',\n", " 'FileNotFoundError',\n", " 'FloatingPointError',\n", " 'FutureWarning',\n", " 'GeneratorExit',\n", " 'IOError',\n", " 'ImportError',\n", " 'ImportWarning',\n", " 'IndentationError',\n", " 'IndexError',\n", " 'InterruptedError',\n", " 'IsADirectoryError',\n", " 'KeyError',\n", " 'KeyboardInterrupt',\n", " 'LookupError',\n", " 'MemoryError',\n", " 'ModuleNotFoundError',\n", " 'NameError',\n", " 'None',\n", " 'NotADirectoryError',\n", " 'NotImplemented',\n", " 'NotImplementedError',\n", " 'OSError',\n", " 'OverflowError',\n", " 'PendingDeprecationWarning',\n", " 'PermissionError',\n", " 'ProcessLookupError',\n", " 'RecursionError',\n", " 'ReferenceError',\n", " 'ResourceWarning',\n", " 'RuntimeError',\n", " 'RuntimeWarning',\n", " 'StopAsyncIteration',\n", " 'StopIteration',\n", " 'SyntaxError',\n", " 'SyntaxWarning',\n", " 'SystemError',\n", " 'SystemExit',\n", " 'TabError',\n", " 'TimeoutError',\n", " 'True',\n", " 'TypeError',\n", " 'UnboundLocalError',\n", " 'UnicodeDecodeError',\n", " 'UnicodeEncodeError',\n", " 'UnicodeError',\n", " 'UnicodeTranslateError',\n", " 'UnicodeWarning',\n", " 'UserWarning',\n", " 'ValueError',\n", " 'Warning',\n", " 'ZeroDivisionError',\n", " '__IPYTHON__',\n", " '__build_class__',\n", " '__debug__',\n", " '__doc__',\n", " '__import__',\n", " '__loader__',\n", " '__name__',\n", " '__package__',\n", " '__spec__',\n", " 'abs',\n", " 'all',\n", " 'any',\n", " 'ascii',\n", " 'bin',\n", " 'bool',\n", " 'bytearray',\n", " 'bytes',\n", " 'callable',\n", " 'chr',\n", " 'classmethod',\n", " 'compile',\n", " 'complex',\n", " 'copyright',\n", " 'credits',\n", " 'delattr',\n", " 'dict',\n", " 'dir',\n", " 'display',\n", " 'divmod',\n", " 'enumerate',\n", " 'eval',\n", " 'exec',\n", " 'filter',\n", " 'float',\n", " 'format',\n", " 'frozenset',\n", " 'get_ipython',\n", " 'getattr',\n", " 'globals',\n", " 'hasattr',\n", " 'hash',\n", " 'help',\n", " 'hex',\n", " 'id',\n", " 'input',\n", " 'int',\n", " 'isinstance',\n", " 'issubclass',\n", " 'iter',\n", " 'len',\n", " 'license',\n", " 'list',\n", " 'locals',\n", " 'map',\n", " 'max',\n", " 'memoryview',\n", " 'min',\n", " 'next',\n", " 'object',\n", " 'oct',\n", " 'open',\n", " 'ord',\n", " 'pow',\n", " 'print',\n", " 'property',\n", " 'range',\n", " 'repr',\n", " 'reversed',\n", " 'round',\n", " 'set',\n", " 'setattr',\n", " 'slice',\n", " 'sorted',\n", " 'staticmethod',\n", " 'str',\n", " 'sum',\n", " 'super',\n", " 'tuple',\n", " 'type',\n", " 'vars',\n", " 'zip']" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import builtins\n", "dir(builtins)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Enclosing function scope\n", "---\n", "* **E:** local scopes of any enclosing defs" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Enclosing function example\n", "---\n", "* **Global names: w, outer**\n", "* **Enclosing local names: x, inner**\n", "* **Local names: z, y**" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "110\n" ] } ], "source": [ "# Global scope\n", "w = 21 # W and outer assigned in module: global\n", "def outer(x):# X and inner assigned in enclosing function: Enclosing def locals\n", " def inner(y): # Z, Y assigned in function: local\n", " z = w + x + y # W is a global (21+88+1)\n", " print(z)\n", " inner(1)\n", "outer(88)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Exercise" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# exercise1\n", "x = 'Spam'\n", "def func():\n", " print(x)\n", " \n", "func()" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Spam\n" ] } ], "source": [ "# answer\n", "x = 'Spam'\n", "def func():\n", " print(x)\n", " \n", "func()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# exercise2\n", "x = 'Spam'\n", "def func():\n", " x = 'HI!'\n", " \n", "func()\n", "print(x)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Spam\n" ] } ], "source": [ "# answer\n", "x = 'Spam'\n", "def func():\n", " x = 'HI!'\n", " \n", "func()\n", "print(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# exercise3\n", "x = 'World'\n", "def func():\n", " x = 'Hello'\n", " print(x)\n", " \n", "func()\n", "print(x)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello\n", "World\n" ] } ], "source": [ "# answer\n", "x = 'World'\n", "def func():\n", " x = 'Hello'\n", " print(x)\n", " \n", "func()\n", "print(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [], "source": [ "# exercise 4\n", "w = 22\n", "def outer():\n", " w = 23\n", " def inner():\n", " w = 24\n", " print('first: ', w) # first print\n", " inner()\n", " print('second: ', w) # second print\n", " \n", "outer()\n", "print('third: ', w) # third print" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "first: 24\n", "second: 23\n", "third: 22\n" ] } ], "source": [ "# answer\n", "w = 22\n", "def outer():\n", " w = 23\n", " def inner():\n", " w = 24\n", " print('first: ', w) # first print\n", " inner()\n", " print('second: ', w) # second print\n", " \n", "outer()\n", "print('third: ', w) # third print" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## The global Statement\n", "---\n", "* keyword: **global**" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "99\n" ] } ], "source": [ "# example\n", "x = 88 # Global x\n", "def f(): \n", " global x\n", " x = 99 # Global x: outside def\n", "\n", "f()\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Factory Function: Closures\n", "---\n", "The function object remembers values in enclosing scopes regardless of whether those scopes are still present in memory.\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ ".action at 0x1040afae8>\n", "6\n", "8\n" ] } ], "source": [ "# This defines an outer function that simply generates and returns a nested function without calling it.\n", "# maker makes action, but returns action without running it.\n", "def maker(n):\n", " def action(x): # Generate and return action\n", " return x * n # action retains N from enclosing scope return action\n", " return action\n", "\n", "f = maker(2) # Pass 2 to argument N\n", "print(f)\n", "print(f(3)) # Pass 3 to X, N remembers 2: 3*2=6\n", "print(f(4)) # Pass 4 to X, N remembers 2: 4*2=8" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "scrolled": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ ".action at 0x1040afa60>\n", "8\n", ".action at 0x1040afae8>\n", "12\n" ] } ], "source": [ "def maker(n):\n", " def action(x): # Generate and return action\n", " return x * n # action retains N from enclosing scope return action\n", " return action\n", "\n", "f = maker(2) # Pass 2 to argument N\n", "g = maker(3) # Pass 3 to argument N\n", "\n", "print(f)\n", "print(f(4)) # Pass 4 to X, N remembers 2: 2*4=4\n", "\n", "print(g)\n", "print(g(4)) # Pass 4 to X, N remembers 3: 3*4=6" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# advanced technique\n", "# lambda arg1, arg2, ....: expression\n", "def maker(n):\n", " return lambda x: x * n\n", " \n", "h = maker(3)\n", "print(h(4))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### 練習4: N^X (10min) - 列入課堂成績\n", "---\n", "請試著用 Factory Function 的方法, 計算 N 的 X 次方。\n", "* example:\n", " * **f = maker(9)** : N=9\n", " * **f(5)** : X=5\n", " * **print(f(5))**: 59049 (為9的5次方)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Function\n", "---\n", "1. Function Basics\n", "2. Scopes\n", "3. **Arguments**\n", "4. Recursive Functions" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### 練習5 - carbon_foot - 不列入課堂成績\n", "---\n", "請試著用 Factory Function 的方法, 計算交通使用 公車, 汽車, 機車 的碳足跡排放量。\n", "\n", "* 碳足跡計算方式\n", " * rate * km\n", " * rate(kg/km): 公車:0.03, 汽車:0.24, 機車:0.06\n", "\n", "* example\n", " * way = carbon_foot('car') \n", " * way(100): 0.24 * 100 = 24.0 (kg/km)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "Review: Object\n", "---\n", "**Everything in python is an object**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "fragment" } }, "source": [ "" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4394978016 4394978016\n" ] } ], "source": [ "a = 3\n", "print(id(a), id(3))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Review: immutable object\n", "---\n", "![](https://i.imgur.com/YCRrRgE.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Review: mutable object\n", "---\n", "\n", "" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Argument-Passing Basics (1)\n", "---\n", "* **aliasing**\n", " * assignment to an argument name inside a function (e.g., a=99) does not change a variable like b in the scope of the function call." ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "88\n" ] } ], "source": [ "def f(a): # a is assigned to (references) the passed object\n", " a = 99 # Changes local variable a only\n", "b = 88 \n", "f(b) # a and b both reference same 88 initially\n", "print(b) # b is not changed" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "before_b: [1, 2]\n", "after_b: ['spam', 2]\n", "b_id: 4434998728\n", "L: ['spam', 2]\n", "L_id: 4434998728\n" ] } ], "source": [ "def changer(b): # Arguments assigned references to objects\n", " print('before_b:',b)\n", " b[0] = 'spam' # Changes shared object in place\n", " print('after_b:',b)\n", " print('b_id:',id(b))\n", " \n", "test_list = [1, 2] \n", "changer(test_list) # Pass mutable object\n", "print('L:', test_list) # l is different\n", "print('L_id:', id(test_list))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Argument-Passing Basics (2)\n", "---\n", "**Avoiding Mutable Argument Changes**: \n", "If we don’t want in-place changes within functions to impact objects we pass to them, though, we can simply make explicit copies of mutable objects," ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "before: L: [1, 2] ; L_id: 4433557320\n", "before: copyL: [1, 2] ; copyL_id: 4435469832\n", "after: L: [1, 2] ; L_id: 4433557320\n", "after: copyL: ['spam', 2] ; copyL_id: 4435469832\n" ] } ], "source": [ "def changer(b): # Arguments assigned references to objects\n", " b[0] = 'spam' # Changes shared object in place\n", " \n", "test_list = [1, 2]\n", "copy_list=test_list[:] \n", "print('before: L:', test_list, '; L_id:', id(test_list))\n", "print('before: copyL:', copy_list, '; copyL_id:', id(copy_list))\n", "changer(copy_list)\n", "print('after: L:', test_list, '; L_id:', id(test_list))\n", "print('after: copyL:', copy_list, '; copyL_id:', id(copy_list))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Argument-Passing Basics (3)\n", "---\n", "* Arguments are passed by automatically assigning objects to local variable names\n", "\n", "* Assigning to argument names inside a function does not affect the caller\n", "\n", "* Changing a mutable object argument in a function may impact the caller.\n" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Argument Matching Basics (1)\n", "---\n", "* **Positionals:** matched from left to right" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "scrolled": true, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 2 3\n" ] } ], "source": [ "# positionals example\n", "def f(x, y, z):\n", " print(x, y, z)\n", "f(1, 2, 3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Argument Matching Basics (2)\n", "---\n", "* **Keywords:** matched by argument name" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6 5 4\n" ] } ], "source": [ "# keywords example\n", "def f(x, y, z):\n", " print(x, y, z)\n", " \n", "f(z=4, y=5, x=6)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Argument Matching Basics (3)\n", "---\n", "* **Defaults:** specify values for optional arguments that aren’t passed" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "4 5 3\n", "4 5 6\n" ] } ], "source": [ "# defaults and postional\n", "def f(x, y, z=3):\n", " print(x, y, z)\n", "f(4, 5)\n", "f(4, 5, 6)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Argument Matching Basics\n", "---\n", "* **Varargs collecting:** collect arbitrarily many positional or keyword arguments\n" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(1, 2, 3, 4, 5, 6, 8, 'hello')\n", "('how', 'do', 'you', 'do')\n", "1 2\n", "(3, 4, 5, 6, 8, 'hello')\n" ] } ], "source": [ "# varargs collecting, one * for tuple\n", "def f1(*args):\n", " print(args)\n", "f1(1, 2, 3, 4, 5, 6, 8, 'hello')\n", "f1('how', 'do', 'you', 'do')\n", "\n", "def f2(x, y, *args):\n", " print(x,y)\n", " print(args)\n", "f2(1,2,3,4,5,6,8,'hello')" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'key1': 1, 'key2': 2, 'key3': 3}\n" ] } ], "source": [ "# varargs collecting, two * for dictionary\n", "def f(**kwargs):\n", " print(kwargs)\n", "f(key1=1, key2=2, key3=3)" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 2\n", "(3, 4, 5, 6, 8, 'hello')\n", "{'key1': 1, 'key2': 2, 'key3': 3}\n" ] } ], "source": [ "# mix varargs collecting\n", "def mix(x, y, *args, **kwargs):\n", " print(x,y)\n", " print(args)\n", " print(kwargs)\n", "mix(1, 2, 3, 4, 5, 6, 8, 'hello', key1=1, key2=2, key3=3)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Argument Matching Basics\n", "---\n", "* **Varargs unpacking:** pass arbitrarily many positional or keyword arguments" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1 2 3\n", "1 2 3\n" ] } ], "source": [ "# Varargs unpacking \n", "def f(x, y, z):\n", " print(x, y, z)\n", " \n", "args=(1, 2, 3)\n", "f(*args)\n", "\n", "kwargs = {'x':1, 'y':2, 'z':3 }\n", "f(**kwargs)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### Exercise: Argument_Matching - 不列入課堂成績" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [], "source": [ "# exercise\n", "# What is the output of the following code?\n", "def f1(a, b=4, c=5):\n", " print(a, b, c)\n", "f1(1, 2)\n", "\n", "def f2(a, b, c=5): \n", " print(a, b, c)\n", "f2(1, c=3, b=2)\n", "\n", "def f3(a, *args):\n", " print(a, args)\n", "f3(1, 2, 3)\n", "\n", "def f4(a, **kargs): \n", " print(a, kargs)\n", "f4(a=1, c=3, b=2)\n", "\n", "def f5(a, b, c=3, d=4): \n", " print(a, b, c, d)\n", "f5(1, *(5, 6))" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "## Function Design Concepts\n", "---\n", "* use arguments for inputs and return for outputs\n", "* use global variables only when truly necessary\n", "* don’t change mutable arguments unless the caller expects it.\n", "* each function should have a single, unified purpose." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Function Objects\n", "---\n", "* Python functions\n", " * are full-blown objects, stored in pieces of memory all their own. \n", " * can be freely passed around a program and called indirectly.\n", " * support operations that have little to do with calls at all—attribute storage and annotation." ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hello word!\n", "hello word!\n" ] } ], "source": [ "# Function objects example: assigned to name\n", "def f(msg):\n", " print(msg)\n", "\n", "f('hello word!')\n", "x = f\n", "x('hello word!')" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello world!\n" ] } ], "source": [ "# Function objects example: pass to other function\n", "def f(msg):\n", " print(msg)\n", " \n", "def g(f_obj, arg): \n", " f_obj(arg)\n", "\n", "g(f, 'Hello world!') # Pass the function to another function" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello\n", "World!!\n" ] } ], "source": [ "# Function objects example: embedded in data structures\n", "def f(msg):\n", " print(msg)\n", " \n", "test_list = [(f, 'Hello'), (f, 'World!!')]\n", "\n", "for (f_obj, arg) in test_list:\n", " f_obj(arg) # Call functions embedded in containers" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "hello:world!\n" ] } ], "source": [ "# Function objects example: return\n", "def f(msg):\n", " def g(msg2):\n", " print(msg+':'+msg2)\n", " return g\n", "\n", "t = f('hello')\n", "t('world!')" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Function\n", "---\n", "1. Function Basics\n", "2. Scopes\n", "3. Arguments\n", "4. **Recursive Functions**" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Recursive Functions\n", "---\n", "**Functions that call themselves either directly or indirectly in order to loop**" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "n: 10\n", "n: 9\n", "n: 8\n", "n: 7\n", "n: 6\n", "n: 5\n", "n: 4\n", "n: 3\n", "n: 2\n", "n: 1\n", "answer: 55\n" ] } ], "source": [ "# sum for 1+2+3+...+10\n", "def f(n):\n", " print('n:',n) # Trace recursive levels\n", " if n==1:\n", " return 1 \n", " else:\n", " return f(n-1)+n\n", "\n", "print('answer: ',f(10))\n", "\n", "# f(10)= f(9)+10 -> next level \n", "# f(9) = f(8)+9 -> next level \n", "# f(8) = f(7)+8 -> next level \n", "# ...\n", "# f(3)=f(2)+3 -> next level \n", "# f(2)=f(1)+2 -> next level \n", "# f(1) return 1 -> next level \n", "\n", "# f(2)=f(1)+ 2 = 1 + 2 -> previous level, f(1) is 1 now\n", "# f(3)=f(2)+ 3 = 3 + 3 -> previous level, f(2) is 3 now\n", "#..." ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### exercise1: recursive_1 - 不列入課堂成績\n", "---\n", "仿照上一個例子,請試著寫數字連乘的遞迴函式,計算出f(10)等於多少。\n", "* f(5) = 1 x 2 x 3 x 4 x 5 = 120\n", "* f(6)= 1 x 2 x 3 x 4 x 5 x 6 = 720" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "### 練習7: recursive_2 ( 10 min ) - 列入課堂成績\n", "---\n", "請試著寫數字連乘的遞迴函式,計算出費氏(Fibonacci)數列 F(20),公式如下:\n", "* F(0) = 0\n", "* F(1) = 1\n", "* F(n) = F(n-1) + F(n-2), when n≥2" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "![](https://i.imgur.com/jQjrefa.png)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "## Loop Statements Versus Recursion\n", "---" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "slideshow": { "slide_type": "fragment" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "receusion: 55\n", "loop 55\n" ] } ], "source": [ "# recursion\n", "def f(n):\n", " if n==1:\n", " return 1 \n", " else:\n", " return f(n-1) + n\n", "print('receusion: ', f(10))\n", "\n", "# loop\n", "total = 0\n", "for i in range(11): # 0, 1, ,2 ,3 ,4 , ..., 10\n", " total = total + i\n", "print('loop', total)" ] }, { "cell_type": "markdown", "metadata": { "slideshow": { "slide_type": "subslide" } }, "source": [ "# 不列入課堂成績 - 課堂練習 - [河內塔問題] (https://zh.wikipedia.org/wiki/%E6%B1%89%E8%AF%BA%E5%A1%94)\n", "---\n", "#### 有三根杆子A,B,C。A杆上有N個(N>1)穿孔圓盤,盤的尺寸由下到上依次變小。要求按下列規則將所有圓盤移至C杆:\n", "\n", "* 每次只能移動一個圓盤\n", "* 大盤不能疊在小盤上面。\n", "* 可將圓盤臨時置於B杆,也可將從A杆移出的圓盤重新移回A杆,但都必須遵循上述兩條規則。\n", "\n", "* ** Question: 5個圓盤,總共要移動多少次,移動的順序為何? **\n", "\n", "![](https://i.imgur.com/zbKUzwu.gif)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Slideshow", "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 }