{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 関数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 関数の定義と引数\n", "[関数を定義](https://docs.python.org/ja/3/reference/compound_stmts.html#function-definitions)するには`def`キーワードを用いる。関数が呼び出されたときの実行内容は、インデントを1つ下げて記述する。\n", "\n", "```python\n", "def 関数名(引数1の変数, 引数2の変数, ...):\n", " # 関数が呼び出されたときに実行する処理\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数`w`は1つの引数`n`を受け取る関数で、その実行内容は文字`'w'`を`n`回表示することである。" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "def w(n):\n", " for i in range(n):\n", " print('w', end='')" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "wwwww" ] } ], "source": [ "w(5)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "www" ] } ], "source": [ "w(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下の関数`w`は2つの引数`n`と`c`を受け取り、文字`c`を`n`回表示する。" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def w(n, c):\n", " for i in range(n):\n", " print(c, end='') " ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "フフフ" ] } ], "source": [ "w(3, 'フ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### キーワード引数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数に値を渡すとき、変数名を明示することもできる(キーワード引数)。" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "フフフ" ] } ], "source": [ "w(n=3, c='フ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "キーワード引数を使うと、関数定義時の順番に関係なく引数を渡すことができる。" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "フフフ" ] } ], "source": [ "w(c='フ', n=3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数定義時の順番による引数(この例では`n`)とキーワード引数(この例では`c`)を混ぜて関数を呼び出すこともできる。" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "フフフ" ] } ], "source": [ "w(3, c='フ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "キーワード引数の後に順番による引数を配置することはできない(もともと、関数`w`の2番目の引数は`c`を取ることになっていたが、キーワード引数`n=5`を渡してしまったので、`c`を順番による引数として渡すことができなくなった)。" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [ { "ename": "SyntaxError", "evalue": "positional argument follows keyword argument (525943670.py, line 1)", "output_type": "error", "traceback": [ "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_204916/525943670.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m w(n=5, 'フ')\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m positional argument follows keyword argument\n" ] } ], "source": [ "w(n=5, 'フ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "同じ引数を2回以上渡すことはできない(以下の例では引数`c`が2回渡されている)。" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [ { "ename": "SyntaxError", "evalue": "keyword argument repeated: c (2347743153.py, line 1)", "output_type": "error", "traceback": [ "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_204916/2347743153.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m w(c='フ', n=5, c='w')\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m keyword argument repeated: c\n" ] } ], "source": [ "w(c='フ', n=5, c='w')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 引数のデフォルト値" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下の関数`w`は2つの引数`n`と`c`を受け取り、文字`c`を`n`回表示する。ただし、引数`c`が指定されなかったときは、`c`の規定値(デフォルト値)として`'w'`を用いる。" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "def w(n, c='w'):\n", " for i in range(n):\n", " print(c, end='')" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "フフフ" ] } ], "source": [ "w(3, 'フ')" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "www" ] } ], "source": [ "w(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下の関数`w`は2つの引数`n`と`c`を受け取り、文字`c`を`n`回表示する。ただし、引数`n`が指定されなかったときはデフォルト値として`3`を、引数`c`が指定されなかったときはデフォルト値として`'w'`を用いる。" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "def w(n=3, c='w'):\n", " for i in range(n):\n", " print(c, end='')" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "フフフフフ" ] } ], "source": [ "w(5, 'フ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`n`の引数を省略し、`c`の引数だけを指定するために、以下のような関数呼び出しを行うとエラーになる。" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [ { "ename": "SyntaxError", "evalue": "invalid syntax (2733099650.py, line 1)", "output_type": "error", "traceback": [ "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_204916/2733099650.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m w(, 'フ')\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" ] } ], "source": [ "w(, 'フ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このような時は、キーワード引数で関数を呼び出せばよい。" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "フフフ" ] } ], "source": [ "w(c='フ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下の関数呼び出しはすべて同じ結果になる。" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "フフフフフ" ] } ], "source": [ "w(5, c='フ')" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "フフフフフ" ] } ], "source": [ "w(n=5, c='フ')" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "フフフフフ" ] } ], "source": [ "w(c='フ', n=5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 関数の戻り値" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数から値を返すには[return](https://docs.python.org/ja/3/reference/simple_stmts.html#the-return-statement)文を用いる。" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "def plus_one(x):\n", " x += 1\n", " return x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数の戻り値を評価することで、関数の値が表示される。" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plus_one(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "先ほど説明した関数`w`は、関数の内部でprint関数を呼び出して文字を表示していたが、ここではincrement関数の戻り値が評価されることによって、関数の値が表示されている。以下のように、関数の戻り値を変数`r`に代入した段階では値が表示されず、変数`r`を評価してから値が表示される。" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "r = plus_one(0)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "r" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数の戻り値として文字列を返すこともできる。" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "def measure_word(n):\n", " if n in (1, 6, 8, 10):\n", " return 'ぽん'\n", " elif n == 3:\n", " return 'ぼん'\n", " else:\n", " return 'ほん'" ] }, { "cell_type": "code", "execution_count": 26, "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 i in range(1, 11):\n", " print(i, measure_word(i))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数の戻り値として、複数の値を返すこともできる(厳密には複数の値がタプルと呼ばれる1つのオブジェクトにまとめられてから返され、その戻り値が関数の呼び出し元で分解される)。" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "def fg(x):\n", " return x ** 2 - 2, 2 * x" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [], "source": [ "fx, gx = fg(0)" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "-2" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fx" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "gx" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下の関数divisorは与えられた整数`n`に約数があれば、約数のなかで最小のものを返す。" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [], "source": [ "def divisor(n):\n", " for a in range(2, n//2+1):\n", " if n % a == 0:\n", " return a" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "divisor(12)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`n`が素数の場合(約数がない場合)はreturn文が実行されないため、値を返さない。" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "divisor(11)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "より正確には、`None`と呼ばれる特殊な定数が返されている。" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "NoneType" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = divisor(11)\n", "type(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "値が`None`かどうかは、オブジェクトの同一性を検査する演算子`is`を用いる(`divisor(n) == None`とは書かない)。これは慣習だと思ったほうがよい(正確な理由はオブジェクトの[比較](https://docs.python.org/ja/3/library/stdtypes.html#comparisons)がカスタマイズされたとしても`None`との比較が正しく行われるようにするためであるが、そのようなお約束だと思っておく方がよい)。" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "11 は素数\n" ] } ], "source": [ "n = 11\n", "if divisor(n) is None:\n", " print(n, 'は素数')\n", "else:\n", " print(n, 'は素数ではない')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ドキュメンテーション文字列" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数宣言の直後に文字列を書くと、ドキュメンテーション文字列として扱われる。他のプログラミング言語ではコメントとして記述することが多いが、ドキュメンテーション文字列はインタプリタ上で参照可能であるうえ、[Sphinx](https://www.sphinx-doc.org/)などのドキュメンテーション生成ツールなどで用いられる。" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "def gcd(x, y):\n", " \"\"\"\n", " Find the greatest common divisor of the given numbers.\n", " \n", " >>> gcd(60, 48)\n", " 12\n", " \n", " >>> gcd(17, 53)\n", " 1\n", " \"\"\"\n", " while y != 0:\n", " (x, y) = (y, x % y)\n", " return x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ドキュメンテーション文字列は[help](https://docs.python.org/ja/3/library/functions.html#help)関数で参照できる。" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Help on function gcd in module __main__:\n", "\n", "gcd(x, y)\n", " Find the greatest common divisor of the given numbers.\n", " \n", " >>> gcd(60, 48)\n", " 12\n", " \n", " >>> gcd(17, 53)\n", " 1\n", "\n" ] } ], "source": [ "help(gcd)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Jupyterでは関数名に続けて`?`を書くことで、ドキュメンテーション文字列を参照できる。" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "\u001b[0;31mSignature:\u001b[0m \u001b[0mgcd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mDocstring:\u001b[0m\n", "Find the greatest common divisor of the given numbers.\n", "\n", ">>> gcd(60, 48)\n", "12\n", "\n", ">>> gcd(17, 53)\n", "1\n", "\u001b[0;31mFile:\u001b[0m /tmp/ipykernel_204916/1813389976.py\n", "\u001b[0;31mType:\u001b[0m function\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "gcd?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、ドキュメンテーション文字列に含まれている実行例を使って、関数のテストを実行できる。gcd関数のドキュメンテーション文字列には以下の実行例が書かれている。実際に関数を実行した結果、期待通りの値が返されるかどうか、テストできる。\n", "```\n", ">>> gcd(60, 48)\n", "12\n", "\n", ">>> gcd(17, 53)\n", "1\n", "```" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Finding tests in NoName\n", "Trying:\n", " gcd(60, 48)\n", "Expecting:\n", " 12\n", "ok\n", "Trying:\n", " gcd(17, 53)\n", "Expecting:\n", " 1\n", "ok\n" ] } ], "source": [ "import doctest\n", "doctest.run_docstring_examples(gcd, globals(), verbose=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 変数のスコープと関数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Jupyterのセルで定義された変数はグローバル変数として維持される。" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "x = 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数の中からグローバル変数の値を取得できる。" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "関数f: x = 1\n" ] } ], "source": [ "def f():\n", " print('関数f: x =', x)\n", "\n", "f()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数の中で変数を定義すると、その変数は関数内のローカル変数として管理される。" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "関数f: x = 0\n", "関数外: x = 1\n" ] } ], "source": [ "def f():\n", " x = 0\n", " print('関数f: x =', x)\n", "\n", "f()\n", "print('関数外: x =', x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "グローバル変数の値をどうしても更新したい時は、[global](https://docs.python.org/ja/3/reference/simple_stmts.html#the-global-statement)文を使う(**普通は使わない**)。" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "関数f: x = 0\n", "関数外: x = 0\n" ] } ], "source": [ "def f():\n", " global x\n", " x = 0\n", " print('関数f: x =', x)\n", "\n", "f()\n", "print('関数外: x =', x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数内のローカル変数に別の関数からアクセスすることはできない。以下のコードでは、関数`f`の中で関数`g`で定義された変数`z`にアクセスできないため、エラーとなる。" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [ { "ename": "NameError", "evalue": "name 'z' 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/tmp/ipykernel_204916/2461913939.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 6\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 7\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0mg\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[0m", "\u001b[0;32m/tmp/ipykernel_204916/2461913939.py\u001b[0m in \u001b[0;36mg\u001b[0;34m()\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m(\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 5\u001b[0m \u001b[0mz\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[0;32m----> 6\u001b[0;31m \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[0m\u001b[1;32m 7\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0mg\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[0;32m/tmp/ipykernel_204916/2461913939.py\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[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mz\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 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mg\u001b[0m\u001b[0;34m(\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 5\u001b[0m \u001b[0mz\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[0;31mNameError\u001b[0m: name 'z' is not defined" ] } ], "source": [ "def f():\n", " print(z)\n", " \n", "def g():\n", " z = 1\n", " f()\n", "\n", "g()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数の引数で渡された変数の値を関数内で変更しても、呼び出し元の変数の値に影響を与えない。ただし、後述するコレクション({ref}`ch:list`や{ref}`ch:dict`など)を引数に渡したときには異なる挙動を示す。以下のコードでは、関数内で`x += 1`されるが、呼び出し元の変数の値は変更されない。" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [], "source": [ "x = 1" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "関数f: x = 2\n", "関数外: x = 1\n" ] } ], "source": [ "def f(x):\n", " x += 1\n", " print('関数f: x =', x)\n", "\n", "f(x)\n", "print('関数外: x =', x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 関数オブジェクト" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$f(x) = x^2 - 2 = 0$の解を[Newton-Raphson法](https://ja.wikipedia.org/wiki/%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%88%E3%83%B3%E6%B3%95)で求めるとき、$f(x)$と$f'(x)$の値を、それぞれ、関数fとgの呼び出しで取得できるようにすると、プログラムの見通しが良くなる。" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.4142135623746899\n" ] } ], "source": [ "def f(x):\n", " return x ** 2 - 2\n", "\n", "def g(x):\n", " return 2 * x\n", "\n", "x = 1\n", "while True:\n", " fx, gx = f(x), g(x)\n", " if -1e-8 < fx < 1e-8:\n", " break\n", " x -= fx / gx\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "これを、$h(x) = x^2 +5x + 6 = 0$の解を求めるプログラムに書き換えるには、例えば以下のような修正を行えばよい。\n", "+ $f(x)$と$f'(x)$の値を返す関数hfとhgを実装する\n", "+ Newton-Raphson法の実装で関数fとgを呼び出していた箇所を、hfとhgに変更する。\n", "\n", "ところが、この方針ではNewton-Raphson法の実装の多くの部分をコピー・ペーストすることになる。" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-1.9999999999999991\n" ] } ], "source": [ "def hf(x):\n", " return x ** 2 + 5 * x + 6\n", "\n", "def hg(x):\n", " return 2 * x + 5\n", "\n", "x = 1\n", "while True:\n", " fx, gx = hf(x), hg(x)\n", " if -1e-8 < fx < 1e-8:\n", " break\n", " x -= fx / gx\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "また、Newton-Raphson法を実行するときの初期値を変更するには、冒頭の`x = 1`の行だけを変更するだけであるが、やはりNewton-Raphson法の実装の多くをコピー・ペーストする必要がある。" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-3.0000000002328306\n" ] } ], "source": [ "x = -4\n", "while True:\n", " fx, gx = hf(x), hg(x)\n", " if -1e-8 < fx < 1e-8:\n", " break\n", " x -= fx / gx\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "そこで、Newton-Raphson法のアルゴリズムの実装を再利用できるようにするため、アルゴリズム本体を関数として実装する。以下のnewton_raphson関数は、\n", "\n", "+ 第1引数(`func_f`)に解を求めたい二次多項式を表現した**関数**を指定する\n", "+ 第2引数(`func_g`)に解を求めたい二次多項式の微分を表現した**関数**を指定する\n", "+ 第3引数(`x`)にNewton-Raphson法の初期値を指定する(省略された場合は$0$とする)" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [], "source": [ "def newton_raphson(func_f, func_g, x=0):\n", " while True:\n", " fx, gx = func_f(x), func_g(x)\n", " if -1e-8 < fx < 1e-8:\n", " return x\n", " x -= fx / gx" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "既に定義済みの関数hfに対応する方程式の解を求めるには、次のようにすればよい。" ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "-1.9999999999946272" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "newton_raphson(hf, hg)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "初期値を$x=-4$として、関数hfに対応する方程式の解を求める(もうひとつの解が求まる)。" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "-3.0000000002328306" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "newton_raphson(hf, hg, -4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "異なる関数(既に定義済みの関数fとg)に対応する方程式の解を求めるには、newton_raphson関数の引数を変更するだけでよい。" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "1.4142135623746899" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "newton_raphson(f, g, 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "newton_raphson関数のように、引数に関数を渡すことができるのは、変数も関数もオブジェクトへの参照として扱われているためである。" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "function" ] }, "execution_count": 55, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数`f`を別の変数`q`に代入すると、`q`も同じ関数として呼び出すことができる。" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [], "source": [ "q = f" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "-2" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "q(0)" ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "-2" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f(0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "無名関数([lambda](https://docs.python.org/ja/3/reference/expressions.html#lambda)関数)を使うと、defキーワードで関数を定義せずに、簡単な関数を定義できる。無名関数は、以下のように記述する\n", "```python\n", "lambda 引数のリスト: 返り値\n", "```\n", "\n", "手始めに、$3x^2+6x-72$をlambda関数として定義し、その関数オブジェクトを変数`f`に代入する。" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [], "source": [ "f = lambda x: 3 * x ** 2 + 6 * x - 72" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "変数`f`は関数として使うことができる。" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "-72" ] }, "execution_count": 60, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f(0)" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(x)>" ] }, "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "function" ] }, "execution_count": 62, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "fやgといった関数を定義せずに$3x^2+6x-72=0$の解を求めるには、$3x^2+6x-72$と、その微分である$6x+6$をlambda関数として定義し、newton_raphson関数の引数に渡せばよい。" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "4.000000000053722" ] }, "execution_count": 63, "metadata": {}, "output_type": "execute_result" } ], "source": [ "newton_raphson(lambda x: 3 * x ** 2 + 6 * x - 72, lambda x: 6 * x + 6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 可変長引数\n", "\n", "(このセクションの内容を理解するには、{ref}`ch:tuple`や{ref}`ch:dict`の知識が必要である)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 可変長引数リスト\n", "\n", "以下の関数decimalは任意の長さ(可変長)の引数をとり、対応する10進数を返す。" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [], "source": [ "def decimal(*args):\n", " v = 0\n", " for arg in args:\n", " v *= 10\n", " v += arg\n", " return v" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "324" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ "decimal(3, 2, 4)" ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "65534" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "decimal(6, 5, 5, 3, 4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数に渡された引数はタプルとして変数`args`に格納されている。" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [], "source": [ "def func(*args):\n", " print(type(args), repr(args))" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " (3, 2, 4)\n" ] } ], "source": [ "func(3, 2, 4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数decimalに可変長の引数を渡す代わりに、タプルを渡すことを意図したが、`arg = ((3, 2, 4),)`となってしまうので、期待通りの動作にはならない。" ] }, { "cell_type": "code", "execution_count": 69, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [ { "ename": "TypeError", "evalue": "unsupported operand type(s) for +=: 'int' and 'tuple'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/tmp/ipykernel_204916/399528650.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0mV\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mdecimal\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mV\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/tmp/ipykernel_204916/979405978.py\u001b[0m in \u001b[0;36mdecimal\u001b[0;34m(*args)\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0marg\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margs\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[0mv\u001b[0m \u001b[0;34m*=\u001b[0m \u001b[0;36m10\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mv\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0marg\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mTypeError\u001b[0m: unsupported operand type(s) for +=: 'int' and 'tuple'" ] } ], "source": [ "V = (3, 2, 4)\n", "decimal(V)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "タプルやリストを関数の引数として展開するには、`*`を付ける。" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "324" ] }, "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ "decimal(*V)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、print関数の引数として`V`を渡すとき、`*`の有無で実行結果が変化する(以上の理屈から考えてみよう)。" ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(3, 2, 4)\n" ] } ], "source": [ "print(V)" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3 2 4\n" ] } ], "source": [ "print(*V)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "decimal関数が10進数ではない引数を受け付けるようにするため、底(`base`)を引数に指定できるように改良した。" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [], "source": [ "def decimal(base, *args):\n", " v = 0\n", " for arg in args:\n", " v *= base\n", " v += arg\n", " return v" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下の関数呼び出しは分かりにくいかもしれないが、最初の引数である`2`は変数`base`に格納され、以降の引数は可変長引数として`args`にタプルとして格納されるので、2進数の1010、すなわち10が返される。" ] }, { "cell_type": "code", "execution_count": 74, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 74, "metadata": {}, "output_type": "execute_result" } ], "source": [ "decimal(2, 1, 0, 1, 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数呼び出しの分かりにくさを軽減するため、`base`をキーワード引数として関数を呼び出してみたが、キーワード引数の後に可変長引数を配置することができないため、エラーになる。" ] }, { "cell_type": "code", "execution_count": 75, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [ { "ename": "SyntaxError", "evalue": "positional argument follows keyword argument (3667318082.py, line 1)", "output_type": "error", "traceback": [ "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_204916/3667318082.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m decimal(base=2, 1, 0, 1, 0)\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m positional argument follows keyword argument\n" ] } ], "source": [ "decimal(base=2, 1, 0, 1, 0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`base`をキーワード引数として渡したい場合は、可変長引数の後ろに配置すればよい。" ] }, { "cell_type": "code", "execution_count": 76, "metadata": {}, "outputs": [], "source": [ "def decimal(*args, base):\n", " v = 0\n", " for arg in args:\n", " v *= base\n", " v += arg\n", " return v" ] }, { "cell_type": "code", "execution_count": 77, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "decimal(1, 0, 1, 0, base=2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 可変長キーワード引数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のencode関数は引数`src`の各文字を、キーワード引数で指定された文字列に置換したものを返す。" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [], "source": [ "def encode(src, **kwargs):\n", " dst = ''\n", " for c in src:\n", " dst += kwargs.get(c, '')\n", " return dst" ] }, { "cell_type": "code", "execution_count": 79, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'010110'" ] }, "execution_count": 79, "metadata": {}, "output_type": "execute_result" } ], "source": [ "encode('abc', a='0', b='10', c='110', d='1110', e='1111')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数に渡された引数は辞書として変数`kwargs`に格納されている。" ] }, { "cell_type": "code", "execution_count": 80, "metadata": {}, "outputs": [], "source": [ "def func(src, **kwargs):\n", " print(type(kwargs), repr(kwargs))" ] }, { "cell_type": "code", "execution_count": 81, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " {'a': '0', 'b': '10', 'c': '110', 'd': '1110', 'e': '1111'}\n" ] } ], "source": [ "func('abc', a='0', b='10', c='110', d='1110', e='1111')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数encodeに可変長キーワード引数を渡す代わりに、辞書を渡すことを意図したが、そのままでは辞書を可変長キーワード引数として扱わないため、エラーになる。" ] }, { "cell_type": "code", "execution_count": 82, "metadata": {}, "outputs": [], "source": [ "D = {'a': '0', 'b': '10', 'c': '110', 'd': '1110', 'e': '1111'}" ] }, { "cell_type": "code", "execution_count": 83, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [ { "ename": "TypeError", "evalue": "encode() takes 1 positional argument but 2 were given", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/tmp/ipykernel_204916/2598886634.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mencode\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'abc'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mD\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;31mTypeError\u001b[0m: encode() takes 1 positional argument but 2 were given" ] } ], "source": [ "encode('abc', D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "辞書を関数の可変長キーワード引数として渡すには、`**`を付ける。" ] }, { "cell_type": "code", "execution_count": 84, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'010110'" ] }, "execution_count": 84, "metadata": {}, "output_type": "execute_result" } ], "source": [ "encode('abc', **D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下は、関数encodeがキーワード引数`unk`を取り、さらに可変長キーワード引数を受け取る例である。" ] }, { "cell_type": "code", "execution_count": 85, "metadata": {}, "outputs": [], "source": [ "def encode(src, unk='?', **kwargs):\n", " dst = ''\n", " for c in src:\n", " dst += kwargs.get(c, unk)\n", " return dst" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "キーワード引数`unk`を省略して呼び出す例である。" ] }, { "cell_type": "code", "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'010110?'" ] }, "execution_count": 86, "metadata": {}, "output_type": "execute_result" } ], "source": [ "encode('abcz', a='0', b='10', c='110', d='1110', e='1111')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "順番による引数よりも後であれば、キーワード引数`unk`をどこに書いてもよい。" ] }, { "cell_type": "code", "execution_count": 87, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'010110#'" ] }, "execution_count": 87, "metadata": {}, "output_type": "execute_result" } ], "source": [ "encode('abcz', unk='#', a='0', b='10', c='110', d='1110', e='1111')" ] }, { "cell_type": "code", "execution_count": 88, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'010110!'" ] }, "execution_count": 88, "metadata": {}, "output_type": "execute_result" } ], "source": [ "encode('abcz', a='0', b='10', c='110', d='1110', e='1111', unk='!')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下の実行結果からも明らかなように、キーワード引数`unk`は辞書`kwargs`に含まれない。" ] }, { "cell_type": "code", "execution_count": 89, "metadata": {}, "outputs": [], "source": [ "def func(src, unk='?', **kwargs):\n", " print(type(kwargs), repr(kwargs))" ] }, { "cell_type": "code", "execution_count": 90, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " {'a': '0', 'b': '10', 'c': '110', 'd': '1110', 'e': '1111'}\n" ] } ], "source": [ "func('abcz', a='0', b='10', c='110', d='1110', e='1111', unk='!')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "可変長引数リストと可変長キーワード引数を同時に受け付けることも可能である。" ] }, { "cell_type": "code", "execution_count": 91, "metadata": {}, "outputs": [], "source": [ "def encode(*args, unk='?', **kwargs):\n", " s = ''\n", " for arg in args:\n", " s += kwargs.get(arg, unk)\n", " return s" ] }, { "cell_type": "code", "execution_count": 92, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'010110?'" ] }, "execution_count": 92, "metadata": {}, "output_type": "execute_result" } ], "source": [ "encode('a', 'b', 'c', 'z', a='0', b='10', c='110', d='1110', e='1111')" ] }, { "cell_type": "code", "execution_count": 93, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'010110!'" ] }, "execution_count": 93, "metadata": {}, "output_type": "execute_result" } ], "source": [ "encode('a', 'b', 'c', 'z', a='0', b='10', c='110', d='1110', e='1111', unk='!')" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "remove-cell" ] }, "source": [ "---\n", "\n", "[Python早見帳](https://chokkan.github.io/python/) © Copyright 2020-2024 by [岡崎 直観 (Naoaki Okazaki)](https://www.chokkan.org/). この作品はクリエイティブ・コモンズ 表示 - 非営利 - 改変禁止 4.0 国際 ライセンスの下に提供されています。\"クリエイティブ・コモンズ・ライセンス\"" ] } ], "metadata": { "@context": { "CreativeWork": "http://schema.org/CreativeWork", "Organization": "http://schema.org/Organization", "Person": "http://schema.org/Person", "author": "http://schema.org/author", "copyrightHolder": "http://schema.org/copyrightHolder", "copyrightYear": "http://schema.org/copyrightYear", "license": "http://schema.org/license", "name": "http://schema.org/name", "title": "http://schema.org/name", "url": "http://schema.org/url" }, "@type": "CreativeWork", "author": [ { "@type": "Person", "name": "Naoaki Okazaki", "url": "https://www.chokkan.org/" } ], "copyrightHolder": [ { "@type": "Person", "name": "Naoaki Okazaki", "url": "https://www.chokkan.org/" } ], "copyrightYear": 2024, "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.10.12" }, "license": "https://creativecommons.org/licenses/by-nc-nd/4.0/deed.ja", "title": "Python早見帳" }, "nbformat": 4, "nbformat_minor": 4 }