Repository: UTokyo-IPP/utokyo-ipp.github.io Branch: master Commit: 8e5f4ea052f0 Files: 104 Total size: 3.2 MB Directory structure: gitextract_omcyvnxe/ ├── LICENSE ├── README.md ├── colab/ │ ├── 1/ │ │ ├── 1-0.ipynb │ │ ├── 1-1.ipynb │ │ ├── 1-2.ipynb │ │ ├── 1-3.ipynb │ │ └── 1-4.ipynb │ ├── 2/ │ │ ├── 2-1.ipynb │ │ ├── 2-2.ipynb │ │ └── 2-3.ipynb │ ├── 3/ │ │ ├── 3-1.ipynb │ │ ├── 3-2.ipynb │ │ └── 3-3.ipynb │ ├── 4/ │ │ ├── 4-1.ipynb │ │ ├── 4-2.ipynb │ │ ├── 4-3.ipynb │ │ ├── sample.txt │ │ ├── shift_jis.txt │ │ ├── test.txt │ │ ├── text/ │ │ │ └── novel.txt │ │ └── utf-8.txt │ ├── 5/ │ │ ├── 5-1.ipynb │ │ ├── 5-2.ipynb │ │ ├── 5-3.ipynb │ │ └── factorial.py │ ├── 6/ │ │ ├── 6-1.ipynb │ │ ├── 6-2.ipynb │ │ ├── 6-3.ipynb │ │ └── jugemu.txt │ ├── 7/ │ │ ├── 7-1.ipynb │ │ ├── 7-2.ipynb │ │ └── iris.csv │ ├── LICENSE │ ├── appendix/ │ │ ├── 1-jupyter-notebook.ipynb │ │ ├── 2-set.ipynb │ │ ├── 3-recursion.ipynb │ │ ├── 3-visualization.ipynb │ │ ├── 4-csv.ipynb │ │ ├── 5-bokeh.ipynb │ │ ├── 5-command.ipynb │ │ ├── 5-matplotlib.ipynb │ │ ├── 5-re.ipynb │ │ ├── B1S.xml │ │ ├── argsprint.py │ │ ├── sample.py │ │ ├── sin.html │ │ ├── small.csv │ │ ├── text-sample.txt │ │ ├── tokyo-july-temps.csv │ │ └── tokyo-temps.csv │ ├── index.ipynb │ └── index_of_terms.ipynb └── docs/ ├── .buildinfo ├── .nojekyll ├── 1/ │ ├── 1-0.html │ ├── 1-1.html │ ├── 1-2.html │ ├── 1-3.html │ └── 1-4.html ├── 2/ │ ├── 2-1.html │ ├── 2-2.html │ └── 2-3.html ├── 3/ │ ├── 3-1.html │ ├── 3-2.html │ └── 3-3.html ├── 4/ │ ├── 4-1.html │ ├── 4-2.html │ └── 4-3.html ├── 5/ │ ├── 5-1.html │ ├── 5-2.html │ └── 5-3.html ├── 6/ │ ├── 6-1.html │ ├── 6-2.html │ └── 6-3.html ├── 7/ │ ├── 7-1.html │ └── 7-2.html ├── _static/ │ ├── alabaster.css │ ├── basic.css │ ├── custom.css │ ├── custom.css~ │ ├── doctools.js │ ├── documentation_options.js │ ├── language_data.js │ ├── nbsphinx-code-cells.css │ ├── nbsphinx-gallery.css │ ├── pygments.css │ ├── searchtools.js │ └── sphinx_highlight.js ├── appendix/ │ ├── 1-jupyter-notebook.html │ ├── 2-set.html │ ├── 3-recursion.html │ ├── 3-visualization.html │ ├── 4-csv.html │ ├── 5-bokeh.html │ ├── 5-command.html │ ├── 5-matplotlib.html │ └── 5-re.html ├── genindex.html ├── index.html ├── index_of_terms.html ├── objects.inv ├── search.html ├── searchindex.js └── toc.html ================================================ FILE CONTENTS ================================================ ================================================ FILE: LICENSE ================================================ Copyright (c) 2020 Mathematics and Informatics Center, The University of Tokyo. Attribution-NonCommercial-NoDerivatives 4.0 International ======================================================================= Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an "as-is" basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. Using Creative Commons Public Licenses Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC- licensed material, or material used under an exception or limitation to copyright. More considerations for licensors: wiki.creativecommons.org/Considerations_for_licensors Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor's permission is not necessary for any reason--for example, because of any applicable exception or limitation to copyright--then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public: wiki.creativecommons.org/Considerations_for_licensees ======================================================================= Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. Section 1 -- Definitions. a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. b. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. c. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. d. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. e. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. f. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. g. Licensor means the individual(s) or entity(ies) granting rights under this Public License. h. NonCommercial means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange. i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. Section 2 -- Scope. a. License grant. 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: a. reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and b. produce and reproduce, but not Share, Adapted Material for NonCommercial purposes only. 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 3. Term. The term of this Public License is specified in Section 6(a). 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a) (4) never produces Adapted Material. 5. Downstream recipients. a. Offer from the Licensor -- Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. b. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). b. Other rights. 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 2. Patent and trademark rights are not licensed under this Public License. 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes. Section 3 -- License Conditions. Your exercise of the Licensed Rights is expressly made subject to the following conditions. a. Attribution. 1. If You Share the Licensed Material, You must: a. retain the following if it is supplied by the Licensor with the Licensed Material: i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); ii. a copyright notice; iii. a notice that refers to this Public License; iv. a notice that refers to the disclaimer of warranties; v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; b. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and c. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. For the avoidance of doubt, You do not have permission under this Public License to Share Adapted Material. 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. Section 4 -- Sui Generis Database Rights. Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only and provided You do not Share Adapted Material; b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. Section 5 -- Disclaimer of Warranties and Limitation of Liability. a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. Section 6 -- Term and Termination. a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 2. upon express reinstatement by the Licensor. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. Section 7 -- Other Terms and Conditions. a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. Section 8 -- Interpretation. a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. ======================================================================= Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” The text of the Creative Commons public licenses is dedicated to the public domain under the CC0 Public Domain Dedication. Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. Creative Commons may be contacted at creativecommons.org. ================================================ FILE: README.md ================================================ # Pythonプログラミング入門の教材 東京大学における[「Pythonプログラミング入門」](https://utokyo-ipp.github.io/course/)の教材を提供する公開レポジトリ. ## 4つの形式 * HTML版: * PDF版: * Colab版: * HTML版にある ![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg) から対応するノートブックを開ける. * Jupyter版: * ローカルでipynbを実行するためのファイル一式. ## 本レポジトリの管理ポリシー * 本レポジトリは,最新公開版の提供を目的としており,改訂履歴の提供は目的としていない. * 履歴は予告なく削除されることがある. * 著作権管理の都合で,全てのpull requestは機械的にrejectされる. * ただし,提案を例示する手段として,pull requestを作成することは止めない. * 誤植等の報告として,issueの作成は歓迎する. * 教材改訂の際に適宜反映する予定. ## ビルドとデプロイ Jupyter版をソースとして,他の形式がビルドされている. ビルドとデプロイは,[ipynb_deployer](https://github.com/satoshigeyuki/ipynb_deployer)によって自動化されている. ================================================ FILE: colab/1/1-0.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 1-0. Colaboratory (Colab) の使い方\n", "\n", "Colaboratory(通称 Colab)によるノートブックの操作方法について説明します。\n", "\n", "## Colaboratoryの立ち上げ\n", "\n", "ブラウザにGoogleアカウント(個人でもECCSでもどちらでもよい)でログインした後に、以下のURLを開いてください。\n", " \n", "- https://colab.research.google.com/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 教材のオープン\n", "\n", "HTML版の教材の「Open in Colab」をクリックしたり、\n", "Google Drive上の教材を直接Colabratoryでオープンした場合、\n", "指定したノートブックがオープンされますが、ノートブックを操作した結果は\n", "Google Drive上に保存されません。\n", "ノートブックの上方にある「ドライブにコピー」のボタンを押せば、\n", "自分のGoogle Drive上にノートブックのコピーが作られてオープンされます。\n", "ノートブックを操作した結果はコピーに保存されます。\n", "\n", "なお、ノートブックには `ipynb` という拡張子(エクステンション)が付いています。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ノートブックの操作\n", "\n", "ノートブックの上方のタイトルの下には、「ファイル」や「編集」などのメニュー、\n", "その下には「+ コード」と「+ テキスト」というボタンが表示されています。\n", "\n", "Ctrl+s(Macの場合は Cmd+s)を入力することによって、\n", "編集・操作中のノートブックを Google Drive のファイルにセーブできます。\n", "なお、ノートブックは適当なタイミングでオートセーブされます。\n", "ファイルメニューの右に「すべての変更を保存しました」と表示されていれば、\n", "Ctrl+s を入力する必要はありません。\n", "\n", "以下の参考文献は、Jupyter Notebook に関する一般的な解説です。\n", "jupyterコマンドを起動してブラウザでノートブックを使うのと、\n", "Google Colaboratory によりノートブックを使うのでは、\n", "インタフェースが大分異なっていることに注意してください。\n", "\n", "- https://jupyter.readthedocs.io/en/latest/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## セル\n", "\n", "ノートブックはセルから成り立っています。\n", "\n", "主に次の二種類のセルを使います。\n", "\n", "* Codeセル(コードセル):\n", "Pythonのコードが書かれたセルです。\n", "Codeセルの左端には `[ ]` と表示されています。\n", "Codeセルの中のコードを実行するには、\n", "`[ ]` のところにマウスカーソルを移動してクリックします。\n", "`[ ]` のところにマウスカーソルを移動すると、●の中に▷が表示されます。\n", "これはプレイボタンを意味します。\n", "プレイボタンを押すとコードが実行され、その結果がセルの下部に挿入されます。\n", "(Shiftを押しながらEnterを押しても実行できます。)\n", "* Markdownセル(テキストセル):\n", "説明が書かれたセルです。\n", "このセル自身はMarkdownセルです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "1+1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## セルの編集\n", "\n", "Codeセル上のプレイボタンでないところにマウスカーソルを移動しクリックすると、\n", "Codeセルが選択され、文字カーソルが表示されて、セルの編集が可能になります。\n", "Ctrlの付かない文字はそのまま挿入されます。\n", "\n", "以下のような編集コマンドが使えます。\n", "\n", "* Ctrl+c: copy\n", "* Ctrl+x: cut\n", "* Ctrl+v: paste\n", "* Ctrl+z: undo\n", "* …\n", "\n", "Codeセルが選択されているとき、Shift+Enter(もしくはShift+Return)を入力すると、\n", "セルの中のコードが実行されて、次のセルが選択されます。\n", "\n", "## 練習\n", "\n", "次のCodeセルを選択して `10/3` と入力して実行してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Codeセルの実行が終了し、別のセルが選択されると、\n", "セルの左端は `[2]` のようになり、`[ ]` の中に番号が入ります。\n", "この番号は、そのCodeセルが何番目に実行されたかを示すもので、\n", "Codeセルが実行されるたびに1ずつ増えます。\n", "同じセルを続けて実行すれば、この番号は1ずつ増えるでしょう。\n", "\n", "## セルの挿入\n", "\n", "Codeセルを新たに挿入するには、\n", "ファイルメニューの下の「+ コード」ボタンを押します。\n", "現在選択されているセルの下にCodeセルが挿入されます。\n", "\n", "たとえば、このMarkdownセルを選択してから、\n", "「+ コード」ボタンを押してみてください。\n", "このMarkdownセルを選択するには、マウスカーソルをここに持って来て\n", "クリックすればよいです。説明の全体が四角で囲まれるはずです。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Markdownセルを新たに挿入するには、\n", "ファイルメニューの下の「+ テキスト」ボタンを押します。\n", "なお、ここではMarkdownセルの説明は行っていません。\n", "\n", "## セルの実行が止まらないとき\n", "\n", "Codeセルの左端の●の中に□が表示され、\n", "その周りをノの字が回り続けているならば、セルのコードは実行中です。\n", "いつまでたってもコードの実行が終了しない場合は、\n", "そのアイコンを押して、コードの実行を強制終了してください。\n", "●の中に□が表示されたアイコンはストップボタンを意味します。\n", "\n", "たとえば、次のような例です。\n", "プレイボタンを押し実行中であることを確かめてから、\n", "ストップボタンを押してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "while True:\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## セルの操作\n", "\n", "セルを選択するとセルの右上に色々なボタンが表示されます。\n", "これらを押すことにより、セルの削除、セルの移動、コピーペーストなど、\n", "セルに対する各種の操作を行うことができます。\n", "\n", "## ノートブックの参照\n", "\n", "Colaboratoryが使用するノードブックは Google Drive 上にあります。\n", "右上の「共有」のボタンを押すことにより、\n", "ノートブックの共有設定を変えることができます。\n", "その上で、ノートブックが表示されているブラウザ上のURLを伝えることにより、\n", "教員やTAにノートブックを見せることができます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ノートブックのダウンロード\n", "\n", "Google Drive 上のノートブックをパソコンにダウンロードするには、\n", "Colaboratoryのファイルメニューで「.ipynb をダウンロード」を選択します。\n", "\n", "![](https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/./1/colab4.png)" ] } ], "metadata": { "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.12.4" }, "nbsphinx": { "execute": "never" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: colab/1/1-1.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 1-1. 数値演算\n", "数値演算について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/introduction.html#using-python-as-a-calculator\n", "- https://docs.python.org/ja/3/tutorial/modules.html\n", "- https://docs.python.org/ja/3/library/numeric.html\n", "- https://docs.python.org/ja/3/library/math.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 簡単な算術計算\n", "\n", "CodeセルにPythonの式を入力して、プレイボタンを押すか、\n", "Shiftを押しながらEnterを押すと、式が評価され、その結果の値がセルの下に挿入されます。\n", "\n", "1+1 の計算をしてみましょう。次のセルに `1+1` と入力して、\n", "Shiftを押しながらEnterを押してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このようにして、電卓の代わりにPythonを使うことができます。**`+`** は言うまでもなく**足し算**を表しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7-2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7*2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7**2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`-`** は**引き算**、**`*`** は**掛け算**、**`**`** は**べき乗**を表しています。\n", "\n", "式を適当に書き換えてから、Shiftを押しながらEnterを押すと、\n", "書き換えた後の式が評価されて、セルの下の値はその結果で置き換わります。\n", "たとえば、上の `2` を `100` に書き換えて、7の100乗を求めてみてください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "割り算はどうなるでしょうか。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7/2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7//2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pythonでは、**割り算**(**除算**)は **`/`** で表され、**整数除算**は **`//`** で表されます。\n", "`//` は小数部を切り捨てた整数値(**商**)を返します。\n", "\n", "整数同士の `//` の結果は整数になります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7/1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7//1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "整数除算の**余り**(**剰余**)を求めたいときは、別の演算子 **`%`** を用います。\n", "\n", "整数同士の `%` の結果は整数になります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7%2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## コメント\n", "Pythonでは一般に、コードの中に **`#`** が出現すると、それ以降、その行の終わりまでが**コメント**になります。\n", "コメントは行頭からも、行の途中からでも始めることができます。\n", "\n", "プログラムの実行時には、コメントは無視されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# このように行頭に '#' をおけば、行全体をコメントとすることができます。\n", "\n", "# 次のようにコード行に続けて直前のコードについての説明をコメントとして書くこともできます。\n", "2**10 # 2の10乗を計算します" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 次のようにコード行自体をコメントとすることで、その行を無視させる(コメントアウトする)こともよく行われます。\n", "# 2**10 # 2の10乗を計算します この行が「コメントアウト」された\n", "2**12 # 実は計算したいのは2の12乗でした" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 整数と実数\n", "Pythonでは、**整数**と小数点のある数(**実数**)は、数学的に同じ数を表す場合でも、\n", "コンピュータの中で異なる形式で記憶されますので、表示は異なります。\n", "(実数は**浮動小数点数**ともいいます。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7/1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7//1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "しかし、以下のように、比較を行うと両者は等しいものとして扱われます。\n", "値同士が等しいかどうかを調べる `==` という演算子については、後で紹介します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7/1 == 7//1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`+` と `-` と `*` と `//` と `%` と `**` では、2つの数が整数ならば結果も整数になります。\n", "2つの数が実数であったり、整数と実数が混ざっていたら、結果は実数になります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2+5" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2+5.0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`/` の結果は必ず実数となります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7/1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここで、自分で色々と式を入力してみてください。\n", "以下に、いくつかセルを用意しておきます。\n", "足りなければ、Insertメニューを使ってセルを追加することができます。" ] }, { "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": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 実数のべき表示" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2.0**1000" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "非常に大きな実数は、10のべきとともに表示(**べき表示**)されます。\n", "`e+301` は10の301乗を意味します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2.0**-1000" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "非常に小さな実数も、10のべきとともに表示されます。\n", "`e-302` は10の-302乗を意味します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### いくらでも大きくなる整数" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2**1000" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように、Pythonでは整数はいくらでも大きくなります。\n", "もちろん、コンピュータのメモリに納まる限りにおいてですが。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2**2**2**2**2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 整数と実数の間の変換\n", "\n", "実数を整数に変換するには、**`int`** という関数を用います。\n", "(関数に関する一般的な説明は1-2を参照してください。)\n", "`int(x)` は、実数 `x` を(`0` の方向に)切り下げた結果を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "int(2.9)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "int(-2.9)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "逆に、整数を実数に変換するには、**`float`** という関数を用います。\n", "`float(i)` は、整数 `i` を実数に変換した結果を返します。\n", "たとえば `i+0.0` としても、`i` を実数に変換できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "float(2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2+0.0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 数値誤差\n", "\n", "浮動小数点数には、**数値誤差**が不可避です。\n", "これは、有限のビット数で、無限に小さくなり得る小数刻みを表現しようとするためです。\n", "(参照:[Wikipedia - 浮動小数点数](https://ja.wikipedia.org/wiki/%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0#%E3%82%A8%E3%83%A9%E3%83%BC%EF%BC%88%E8%AA%A4%E5%B7%AE%EF%BC%89))\n", "\n", "Pythonでは、整数は無限桁で表現されるため、整数演算には誤差が生じません。\n", "しかし、整数を実数に変換したときには、一般に誤差が生じます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "10**60" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "float(10**60)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "int(float(10**60))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "数え上げのような離散的な値を扱う時には、実数を経由せずに、整数のみで演算するようにしましょう。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 演算子の優先順位と括弧\n", "掛け算や割り算は足し算や引き算よりも先に評価されます。\n", "すなわち、掛け算や割り算の方が足し算や引き算よりも**優先順位**が高いと定義されています。\n", "\n", "**括弧**を使って式の評価順序を指定することができます。\n", "\n", "なお、数式 $a(b-c)$、$(a-b)(c-d)$ は、それぞれ $a$ と $b-c$、$a-b$ と $c-d$ の積を意味しますが、\n", "コードでは、`a*(b-c)` や `(a-b)*(c-d)` のように積の演算子である `*` を明記する必要があることに注意してください。\n", "\n", "また、数や演算子の間には、自由に空白を入れることができます。(後でもう一度説明します。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7 - 2 * 3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "(7 - 2) * 3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "17 - 17//3*3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "56 ** 4 ** 2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "56 ** 16" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の例では、`4**2` が先に評価されて、`56**16` が計算されます。\n", "つまり、`x**y**z` = `x**(y**z)` が成り立ちます。\n", "このことをもって、`**` は右に結合するといいます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "16/8/2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "(16/8)/2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の例では、`16/8` が先に評価されて、`2/2` が計算されます。\n", "つまり、`x/y/z` = `(x/y)/z` が成り立ちます。\n", "このことをもって、`/` は左に結合するといいます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`*` と `/` をまぜても左に結合します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "10/2*3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以上のように、演算子によって式の評価の順番がかわりますので注意してください。\n", "\n", "ではまた、自分で色々と式を入力してみてください。\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": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 単項の `+` と `-`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`+`** と **`-`** は、単項の演算子(**単項演算子**)としても使えます。\n", "(これらの演算子の後に1つだけ数が書かれます。\n", "前と後の両方に数が書かれる演算子は**2項演算子**と言います。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "-3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "+3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 算術演算子のまとめ\n", "\n", "算術演算子を、評価の優先順位にしたがって、すなわち結合力の強い順にまとめておきましょう。\n", "\n", "まず、2項のべき演算子 `**` が最も強く結合します。\n", "`**` は右の方から計算され、このことを「右に結合する」と表します。\n", "\n", "次に、単項の `+` と `-` が強く結合します。\n", "なお、 `**` の右側に単項の `+` や `-` がある場合は、`+` と `-` がより強く結合します。\n", "例えば、 `-10 ** 2` では `**` がより強く結合し `-100` となり、 `10 ** -2` では `-` がより強く結合し `0.01` となります。\n", "\n", "その次に、2項の `*` と `/` と `//` と `%` が強く結合します。これらは左に結合します。\n", "\n", "最後に、2項の `+` と `-` は最も弱く結合します。これらも左に結合します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 空白\n", "既に `7 - 2 * 3` のような例が出てきましたが、\n", "演算子と数の間や、演算子と変数(後述)の間には、空白を入れることができます。\n", "ここで**空白**とは、**半角の空白**のことで、英数字と同様に1バイトの文字コードに含まれているものです。\n", "\n", "複数の文字から成る演算子、たとえば `**` や `//` の間に空白を入れることはできません。\n", "エラーになることでしょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "7 **2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "7* *2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 全角の空白\n", "日本語文字コードである***全角の空白***は、空白とはみなされませんので注意してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "7 **2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## エラー\n", "色々と試していると、**エラー**が起こることもあったでしょう。\n", "以下は典型的なエラーです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "10/0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このエラーは、ゼロによる割り算を行ったためです。\n", "**実行時エラー**の典型的なものです。\n", "\n", "エラーが起こった場合は、修正して評価し直すことができます。\n", "上の例で、0 をたとえば 3 に書き換えて評価し直してみてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "10/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "こちらのエラーは**構文エラー**です。\n", "つまり、入力がPythonの構文に違反しているため実行できなかったのです。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 数学関数(モジュールのインポート)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import math" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "math.sqrt(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "数学関係の各種の関数は、**モジュール**(**ライブラリ**)として提供されています。\n", "これらの関数を使いたいときは、上のように、**`import`** で始まる\n", "`import math` というおまじないを一度唱えます。\n", "そうしますと、**`math`** というライブラリが読み込まれて(**インポート**されて)、\n", "`math.関数名` という形で関数を用いることができます。\n", "上の例では、平方根を計算する **`math.sqrt`** という関数が用いられています。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "もう少し例をあげておきましょう。sinとcosは **`math.sin`** と **`math.cos`** で求まります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "math.sin(0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "math.pi" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`math.pi`** は、円周率を値とする変数です。\n", "\n", "変数については後に説明されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "math.sin(math.pi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この結果は本当は 0 にならなければならないのですが、\n", "数値誤差のためにこのようになっています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "math.sin(math.pi/2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "math.sin(math.pi/4) * 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "黄金比を求めてください。黄金比とは、5 の平方根に 1 を加えて 2 で割ったものです。約 1.618 になるはずです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "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.12.4" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: colab/1/1-2.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 1-2. 変数と関数の基礎\n", "変数と関数の基礎について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/introduction.html#first-steps-towards-programming\n", "- https://docs.python.org/ja/3/tutorial/controlflow.html#defining-functions\n", "- https://docs.python.org/ja/3/library/functions.html#print" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 変数\n", "プログラミング言語における**変数**とは、値に名前を付ける仕組みであり、名前はその値を指し示すことになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "h = 188.0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以上のように **`=`** を用いる構文によって、`188.0` という値に `h` という名前が付きます。これを**変数定義**と呼びます。\n", "\n", "定義された変数は、式の中で使うことができます。`h` という変数自体も式なので、`h` という式を評価することができ、変数が指し示す値が返ります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "h" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "異なる変数は、いくらでも導入できます。たとえば、以下では `w` を変数定義します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "w = 104.0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここで、`h` を身長 (cm)、`w` を体重 (kg) の意味と考えると、次の式によってBMI(ボディマス指数)を計算できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "w / (h/100.0) ** 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、演算子 `**` の方が `/` よりも先に評価されることに注意してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "変数という名前の通り、変数が指し示す値を変えることもできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "w = 104.0-10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように変数を再定義すれば、元々 `w` が指し示していた値 `104.0` を忘れて、新たな値 `94.0` を指し示すようになります。\n", "この後で、前と同じBMIの式を評価してみると、`w` の値の変化に応じて、BMIの計算結果は変わります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "w / (h/100.0) ** 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、未定義の変数(たとえば `BMI`)を式の中で用いると、次のようにエラーが生じます。\n", "\n", "```\n", "---------------------------------------------------------------------------\n", "NameError Traceback (most recent call last)\n", " in \n", "----> 1 BMI # 未定義の変数\n", "\n", "NameError: name 'BMI' is not defined\n", "```\n", "\n", "次のセルの行頭にある `#` を削除して実行してみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# BMI # 未定義の変数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以降では、単純のため、変数が指し示す値を、変数の値として説明していきます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 代入文\n", "変数定義に用いた **`=`** による構文を、Pythonでは**代入文** (**assignment statement**) と呼びます。\n", "そして、代入文を実行することを**代入** (**assignment**) と言います。\n", "代入文は、`=` の左辺に右辺の式の評価結果の値を割り当てる文です。\n", "上記の例のように、左辺が変数の場合には、代入文は変数定義と解釈されます。\n", "\n", "代入文は、右辺を評価した後に左辺に割り当てるという順番に従います。右辺に出現する変数が左辺に出て来てもかまいません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "w = w-10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の代入文は、`w` の値を `10` 減らす操作となります。`=` は数学的な等号ではないことに注意してください。\n", "\n", "もう一度BMIを計算してみると、`w` の値が減ったことで、先と結果が変わります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "w / (h/100.0) ** 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***注意***: 数学における代入は、substitution(置換)であり、プログラミング言語における代入 (assignment) とは異なります。代入という単語よりも、assignment(割り当て)という単語で概念を覚えましょう。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 累積代入文\n", "上の例のように変数の値を減らす操作は、次のような**累算代入文** (**augmented assignment statement**) を使って簡潔に記述することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "w -= 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここで、**`-=`** という演算子は、`-` と `=` を結合させた演算子で、`w = w - 10` という代入文と同じ意味になります。\n", "これは代入文と2項演算が複合したものであり、`-` に限らず、他の2項演算についても同様に複合した累算代入文が利用できます。たとえば、変数の値を増やすには **`+=`** という演算子を用いることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "w += 10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`=` も含めて、これらの演算子は**代入演算子**と呼ばれています。代入演算子によって変数の値がどのように変わるか、確かめてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 関数の定義と返値\n", "前述のように、変数の値が変わるたびにBMIの式を入力するのは面倒です。以下では、身長 `height` と体重 `weight` をもらって、BMIを計算する**関数** `bmi` を定義してみましょう。関数を定義すると、BMIの式の再入力を省けて便利です。\n", "\n", "次のような形式で、**関数定義**を記述できます。\n", "\n", "関数定義など、複数行のコードセルには、**行番号**を振るのがよいかもしれません。行番号を振るかどうかは、コマンドモードでエルの文字(大文字でも小文字でもよいです)を入力することによって、スイッチできます。行番号があるかないかは、コードの実行には影響しません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def bmi(height, weight):\n", " return weight / (height/100.0) ** 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python では、**関数定義**は、上のような形をしています。\n", "最初の行は以下のように **`def`** で始まります。\n", "\n", "------\n", "```Python\n", " def 関数名(引数, ...):\n", "```\n", "------\n", "**引数**(ひきすう)とは、関数が受け取る値を指し示す変数のことです。**仮引数**(かりひきすう)ともいいます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`:` 以降は関数定義の本体であり、関数の処理を記述する部分として以下の構文が続きます。\n", "\n", "------\n", "```Python\n", " return 式\n", "```\n", "------ \n", "\n", "この構文は **`return`** で始まり、**return文**と呼ばれます。return文は、`return` に続く式の評価結果を、関数の呼び出し元に返して(これを**返値**と言います)、関数を終了するという意味を持ちます。この関数を、入力となる引数とともに呼び出すと、`return` の後の式の評価結果を返値として返します。\n", "\n", "\n", "ここで、Pythonでは、\n", "`return` の前に空白が入ることに注意してください。\n", "このような行頭の空白を**インデント**と呼びます。\n", "Pythonでは、インデントの量によって、\n", "構文の**入れ子**を制御するようになっています。このことについては、\n", "より複雑な構文が出てきたときに説明しましょう。\n", "\n", "\n", "上記では、`def` の後に続く `bmi` が関数名です。それに続く括弧の中に書かれた `height` と `weight` は、**引数**です。また、`return` の後にBMIの計算式を記述しているので、関数の呼び出し元にはBMIの計算結果が返値として返ります。\n", "\n", "\n", "では、定義した関数 `bmi` を呼び出してみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bmi(188.0,104.0)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "第1引数を身長(cm)、第2引数を体重(kg)としたときのBMIが計算されていることがわかります。\n", "\n", "関数呼び出しは演算式の一種なので、引数の位置には任意の式を記述できますし、\n", "関数呼び出し自体も式の中に記述できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "1.1*bmi(174.0, 119.0 * 0.454)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "もう1つ関数を定義してみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def felt_air_temperature(temperature, humidity):\n", " return temperature - 1 / 2.3 * (temperature - 10) * (0.8 - humidity / 100)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この関数は、温度と湿度を入力として、体感温度を返します。\n", "このように、関数名や変数名には `_` (アンダースコア)を含めることができます。\n", "アンダースコアで始めることもできます。\n", "\n", "数字も関数名や変数名に含めることができますが、\n", "名前の最初に来てはいけません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "felt_air_temperature(28, 50)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、`return` の後に式を書かないと、何も返されなかったことを表現するために、「何もない」ことを表す **`None`** という特別な値が返ります。\n", "(`None` という値は色々なところで現れることでしょう。)\n", "\n", "return文に到達せずに関数定義本体の最後まで行ってしまったときも、`None` という値が返ります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 予約語\n", "Pythonでの `def` や `return` は、関数定義やreturn文の始まりを記述するための特別な記号であり、それ以外の用途に用いることができません。\n", "このように構文上で役割が予約されている語は、**予約語**と呼ばれます。\n", "Codeセルの構文ハイライトで(太字緑色などで)強調されるものが予約語だと覚えておけば大体問題ありません。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習 `ft_to_cm`\n", "\n", "`f` フィート `i` インチをセンチメートルに変換する関数 `ft_to_cm(f,i)` を定義してください。\n", "ただし、1 フィート = 12 インチ = 30.48 cm としてよい。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def ft_to_cm(f, i):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "定義ができたら、次のセルを実行して、エラーがでないことを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "assert round(ft_to_cm(5, 2) - 157.48, 6) == 0\n", "assert round(ft_to_cm(6, 5) - 195.58, 6) == 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習 `quadratic`\n", "\n", "二次関数 $f(x) = ax^2+bx+c$ の値を求める `quadratic(a,b,c,x)` を定義してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def quadratic(a, b, c, x):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "定義ができたら、次のセルを実行して、エラーがでないことを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "assert quadratic(1, 2, 1, 3) == 16\n", "assert quadratic(1, -5, -2, 7) == 12" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ローカル変数\n", "次の関数は、ヘロンの公式によって、\n", "与えられた三辺の長さに対して三角形の面積を返すものです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import math\n", "\n", "def heron(a,b,c):\n", " s = 0.5*(a+b+c)\n", " return math.sqrt(s * (s-a) * (s-b) * (s-c))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`math.sqrt` を使うために `import math` を行っています。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次の式を評価してみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "heron(3,4,5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この関数の中では、まず、3辺の長さを足して 2 で割った(0.5 を掛けた)値を求めています。\n", "そして、その値を `s` という変数に代入しています。\n", "この `s` という変数は、この関数の中で代入されているので、この関数の中だけで利用可能な変数となります。\n", "そのような変数を**ローカル変数**と呼びます。\n", "\n", "そして、`s` を使った式が計算されてreturn文で返されます。\n", "ここで、関数定義のひとまとまりの本体であることを表すために、`s` への代入文もreturn文も、同じ深さでインデントされていることに注意してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pythonでは、関数の中で定義された変数は、その関数のローカル変数となります。関数の引数もローカル変数です。関数の外で同じ名前の変数を使っても、それは関数のローカル変数とは「別もの」と考えられます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`heron` を呼び出した後で、関数の外で `s` の値を参照しても、以下のように、`s` が未定義という扱いになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下では、`heron` の中では、`s` というローカル変数の値は 3 になりますが、関数の外では、`s` という変数は別もので、その値はずっと `100` です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s = 100\n", "heron(3,4,5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `print`\n", "上の例で、ローカル変数は関数の返値を計算するのに使われますが、それが定義されている関数の外からは参照することができません。\n", "\n", "ローカル変数の値など、関数の実行途中の状況を確認するには、 **`print`** というPythonが最初から用意してくれている関数(**組み込み関数**)を用いることができます。この `print` を関数内から呼び出すことでローカル変数の値を確認できます。\n", "\n", "`print` は任意個の引数を取ることができ、コンマ `,` の区切りには空白文字が出力されます。引数を与えずに呼び出した場合には、改行のみを出力します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def heron(a,b,c):\n", " s = 0.5*(a+b+c)\n", " print('The value of s is', s)\n", " return math.sqrt(s * (s-a) * (s-b) * (s-c))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "heron(1,1,1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように `print` 関数を用いて変数の値を観察することは、プログラムの誤り(**バグ**)を見つけ、修正(**デバッグ**)する最も基本的な方法です。これは1-4でも改めて説明します。\n", "\n", "なお、以降の説明では、 `print` 関数を呼び出して値を出力することを「**印字**する」と表現します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `print` と `return`\n", "関数が値を返すことを期待されている場合は、必ず `return` を使ってください。\n", "\n", "関数内で値を印字しても、関数の返値として利用することはできません。\n", "\n", "たとえば `heron` を以下のように定義すると、`heron(1,1,1) * 2` のような計算ができなくなります。\n", "\n", "---\n", "```Python\n", "def heron(a,b,c):\n", " s = 0.5*(a+b+c)\n", " print('The value of s is', s)\n", " print(math.sqrt(s * (s-a) * (s-b) * (s-c)))\n", "```\n", "---\n", "\n", "なお、\n", "\n", "```Python\n", " return print(math.sqrt(s * (s-a) * (s-b) * (s-c)))\n", "```\n", "\n", "のように書いても駄目です。`print` 関数は `None` という値を返しますので、これでは関数は常に `None` という値を返してしまいます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## コメントと空行\n", "**コメント**については既に説明しましたが、\n", "関数定義にはコメントを付加して、後から読んでもわかるようにしましょう。\n", "\n", "コメントだけの行は**空行**(空白のみから成る行)と同じに扱われます。\n", "\n", "関数定義の中に空行を自由に入れることができますので、\n", "長い関数定義には、区切りとなるところに空行を入れるのがよいでしょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# heronの公式により三角形の面積を返す\n", "def heron(a,b,c): # a,b,c は三辺の長さ\n", " \n", " # 辺の合計の半分をsに置く\n", " s = 0.5*(a+b+c)\n", " print('The value of s is', s)\n", " \n", " return math.sqrt(s * (s-a) * (s-b) * (s-c))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 関数の参照の書き方\n", "\n", "関数は、\n", "\n", "  関数 `heron` は、三角形の三辺の長さをもらって三角形の面積を返します。\n", " \n", "というように、名前だけで参照することもありますが、\n", "\n", "  `heron(a,b,c)` は、三角形の三辺の長さ `a`, `b`, `c` をもらって三角形の面積を返します。\n", "\n", "というように、引数を明示して参照することもあります。\n", "\n", "ときには、\n", "\n", "  `heron()` は三角形の面積を返します。\n", " \n", "のように、関数名に `()` を付けて参照することがあります。\n", "この記法は、`heron` が関数であることを明示しています。\n", "\n", "関数には引数がゼロ個のものがあるのですが、`heron()` と参照するとき、\n", "`heron` は必ずしも引数の数がゼロ個ではないことに注意してください。\n", "\n", "後に学習するメソッドという関数の親戚に対しても同様の記法が用いられます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習 `qe_disc` `qe_solution1` `qe_solution1`\n", "\n", "二次方程式 $ax^2 + bx + c = 0$ に関して以下のような関数を定義してください。\n", "\n", "1. 判別式 $b^2 - 4ac$ を求める `qe_disc(a,b,c)`\n", "2. 解のうち、大きくない方を求める `qe_solution1(a,b,c)`\n", "3. 解のうち、小さくない方を求める `qe_solution2(a,b,c)`\n", "\n", "ただし、`qe_solution1` と `qe_solution2` は `qe_disc` を使って定義してください。\n", "二次方程式が実数解を持つと仮定してよいです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import math\n", "\n", "def qe_disc(a, b, c):\n", " ...\n", "\n", "def qe_solution1(a, b, c):\n", " ...\n", "\n", "def qe_solution2(a, b, c):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "定義ができたら、次のセルを実行して、エラーがでないことを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "assert qe_disc(1, -2, 1) == 0\n", "assert qe_disc(1, -5, 6) == 1\n", "assert round(qe_solution1(1, -2, 1) - 1, 6) == 0\n", "assert round(qe_solution2(1, -2, 1) - 1, 6) == 0\n", "assert round(qe_solution1(1, -5, 6) - 2, 6) == 0\n", "assert round(qe_solution2(1, -5, 6) - 3, 6) == 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲グローバル変数\n", "\n", "Pythonでは、関数の中で代入が行われない変数は、グローバル変数とみなされます。\n", "\n", "**グローバル変数**とは、関数の外(**トップレベル**もしくは**モジュールレベル**と呼ばれます)で定義される変数のことです。\n", "\n", "グローバル変数は、関数の中から参照することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "g = 9.8" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def force(m):\n", " return m*g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以上のように `force` を定義すると、\n", "`force` の中で `g` というグローバル変数を参照することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "force(104)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "g = g/6" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以上のように、`g` の値を変更してから `force` を実行すると、\n", "変更後の値が用いられます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "force(104)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下はより簡単な例です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = 10\n", "def foo():\n", " return a\n", "def bar():\n", " a = 3\n", " return a" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "foo()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bar()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = 20" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "foo()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`bar` の中では `a` への代入があるので、`a` はローカル変数になります。\n", "ローカル変数の `a` とグローバル変数の `a` は別ものと考えてください。\n", "ローカル変数 `a` への代入があっても、グローバル変数の `a` の値は変化しません。\n", "`foo` の中の `a` はグローバル変数です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def boo(a):\n", " return a" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "boo(5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数の引数もローカル変数の一種と考えられ、グローバル変数とは別ものです。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def ft_to_cm(f, i):\n", " return 30.48*f + (30.48/12)*i" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def quadratic(a, b, c, x):\n", " return a*x*x + b*x + c" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import math\n", "\n", "def qe_disc(a, b, c):\n", " return b*b - 4*a*c\n", "\n", "def qe_solution1(a, b, c):\n", " return (-b - math.sqrt(qe_disc(a, b, c))) / (2*a)\n", "\n", "def qe_solution2(a, b, c):\n", " return (-b + math.sqrt(qe_disc(a, b, c))) / (2*a)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/1/1-3.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 1-3. 論理・比較演算と条件分岐の基礎\n", "論理・比較演算と条件分岐の基礎について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/controlflow.html\n", "- https://docs.python.org/ja/3/reference/compound_stmts.html\n", "- https://docs.python.org/ja/3/library/stdtypes.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## if文による条件分岐\n", "制御構造については第2回と第3回で本格的に扱いますが、\n", "ここでは **`if`** による**条件分岐**(**if文**)の基本的な形だけ紹介します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def bmax(a,b):\n", " if a > b: \n", " return a \n", " else:\n", " return b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の関数 `bmax` は、2つの引数の大きい方\n", "(正確には小さくない方)を返します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここで `if` による条件分岐が用いられています。\n", "\n", "----\n", "```Python\n", " if a > b: \n", " return a \n", " else:\n", " return b\n", "```\n", "----\n", "`a` が `b` より大きければ `a` が返され、そうでなければ、`b` が返されます。\n", "\n", "ここで、`return a` が、`if` より右にインデントされていることに注意してください。\n", "`return a` は、`a > b` が成り立つときのみ実行されます。\n", "\n", "**`else`** は `if` の右の条件が成り立たない場合を示しています。\n", "`else:` として、必ず `:` が付くことに注意してください。\n", "\n", "また、`return b` も、`else` より右にインデントされていることに注意してください。\n", "`if` と `else` は同じインデントになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bmax(3,5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数の中で `return` と式が実行されますと、関数は即座に返りますので、\n", "関数定義の中のその後の部分は実行されません。\n", "\n", "たとえば、上の条件分岐は以下のように書くこともできます。\n", "\n", "----\n", "```Python\n", " if a > b: \n", " return a \n", " return b\n", "```\n", "----\n", "\n", "ここでは、`if` から始まる条件分岐には `else:` の部分がありません。\n", "条件分岐の後に `return b` が続いています。\n", "(`if` と `return b` のインデントは同じです。)\n", "\n", "`a > b` が成り立っていれば、`return a` が実行されて a の値が返ります。\n", "したがって、その次の `return b` は実行されません。\n", "\n", "`a > b` が成り立っていなければ、`return a` は実行されません。\n", "これで条件分岐は終わりますので、その次にある `return b` が実行されます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、Pythonでは、`max` という関数があらかじめ定義されています。(すなわち、`max` は組み込み関数です。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "max(3,5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 様々な条件\n", "`if` の右などに来る条件として様々なものを書くことができます。これらの条件には **`>`** や **`<`** などの**比較演算子**が含まれています。\n", "\n", "```Python\n", " x < y # x は y より小さい\n", " x <= y # x は y 以下\n", " x > y # x は y より大きい\n", " x >= y # x は y 以上\n", " x == y # x と y は等しい\n", " x != y # x と y は等しくない\n", "```\n", "\n", "特に等しいかどうかの比較には **`==`** という演算子が使われることに注意してください。\n", "`=` は代入の演算子です。\n", "\n", "**`<=`** は小さいか等しいか、**`>=`** は大きいか等しいかを表します。\n", "**`!=`** は等しくないことを表します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "さらに、このような基本的な条件を、\n", "**`and`** と **`or`** を用いて組み合わせることができます。\n", "\n", "```Python\n", " i >= 0 and j > 0 # i は 0 以上で、かつ、j は 0 より大きい\n", " i < 0 or j > 0 # i は 0 より小さいか、または、j は 0 より大きい\n", "```\n", "\n", "`i` が 1 または 2 または 3 である、という条件は以下のようになります。\n", "\n", "```Python\n", " i == 1 or i == 2 or i == 3\n", "```\n", "\n", "これを `i == 1 or 2 or 3` と書くことはできませんので、注意してください。\n", "\n", "また、**`not`** によって条件の否定をとることもできます。\n", "\n", "```Python\n", " not x < y # x は y より小さくない(x は y 以上)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "比較演算子は、以下のように連続して用いることもできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "1 < 2 < 3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "3 >= 2 < 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習 `absolute`\n", "\n", "数値 `x` の絶対値を求める関数 `absolute(x)` を定義してください。\n", "Pythonには `abs` という絶対値を求める組み込み関数が用意されていますが、それを使わずに定義してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def absolute(x):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "定義ができたら、次のセルを実行して、エラーがでないことを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "assert absolute(5) == 5\n", "assert absolute(-5) == 5\n", "assert absolute(0) == 0" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "### 練習 `sign`\n", "\n", "`x` が正ならば 1、負ならば -1、ゼロならば 0 を返す関数 `sign(x)` を定義してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sign(x):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "定義ができたら、次のセルを実行して、エラーがでないことを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "assert sign(5) == 1\n", "assert sign(-5) == -1\n", "assert sign(0) == 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 真理値を返す関数\n", "ここで、真理値を返す関数について説明します。\n", "\n", "Pythonが扱うデータには様々な種類があります。\n", "数については既に見て来ました。\n", "\n", "**真理値**とは、 **`True`** または **`False`** のどちらかの値のことです。\n", "これらは変数ではなく、**組み込み定数**であることに注意してください。\n", "\n", "- `True` は、正しいこと(**真**)を表します。\n", "- `False` は、間違ったこと(**偽**)を表します。\n", "\n", "実は、`if` の後の条件の式は、`True` か `False` を値として持ちます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 3" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x > 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のように、`x` に 3 を代入しておくと、\n", "`x > 1` という条件は成り立ちます。\n", "したがって、`x > 1` という式の値は `True` になるのです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x < 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x%2 == 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "そして、真理値を返す関数を定義することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def is_even(x):\n", " return x%2 == 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この関数は、`x` を 2 で割った余りが 0 に等しいかどうかという\n", "条件の結果である真理値を返します。\n", "\n", "`x == y` は、`x` と `y` が等しいかどうかという条件です。\n", "この関数は、この条件の結果である真理値を `return` によって返しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "is_even(2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "is_even(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このような関数は、`if` の後に使うことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def is_odd(x):\n", " if is_even(x):\n", " return False\n", " else:\n", " return True" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように、直接に `True` や `False` を返すこともできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "is_odd(2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "is_odd(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## オブジェクト\n", "\n", "Pythonにおける値(式の評価結果)は全て**オブジェクト**と総称されます。\n", "変数の値もオブジェクトです。\n", "\n", "したがって、数や真理値もオブジェクトです。\n", "今後、文字列やリストなど、様々な種類のデータが登場しますが、\n", "それらは全てオブジェクトです。\n", "\n", "今後、オブジェクトという用語がところどころで出て来ますが、\n", "オブジェクトとデータは同義と思って差し支えありません。\n", "正確には、式の評価結果や変数の値となるデータがオブジェクトです。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `None`\n", "**`None`** というデータがあります。\n", "\n", "セルの中の式を評価した結果が `None` になると、\n", "何も表示されません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "None" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`print` で無理やり表示させると以下のようになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(None)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`None` という値は、特段の値が何もない、\n", "ということを表すために使われることがあります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "条件としては、`None` は偽と同様に扱われます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if None:\n", " print('OK')\n", "else:\n", " print('NG')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`return` の後に式を書かないことがあります。\n", "\n", "---\n", "```Python\n", " return\n", "```\n", "---\n", "\n", "この場合、以下のように `None` が指定されているとみなされます。\n", "\n", "---\n", "```Python\n", " return None\n", "```\n", "---\n", "\n", "このようなreturn文を実行すると、関数の実行はそこで終了して `None` が返ります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲条件として使われる他の値\n", "`True` と `False` の他に、他の種類のデータも、条件としても用いることができます。\n", "\n", "たとえば:\n", "\n", "- 数のうち、0 や 0.0 は偽、その他は真とみなされます。\n", "- 文字列では、空文字列 `''` のみ偽、その他は真とみなされます。(文字列については2-1を参照。)\n", "- 組み込み定数 `None` は偽とみなされます。(`None` については上記参照。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if 0:\n", " print('OK')\n", "else:\n", " print('NG')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if -1.1:\n", " print('OK')\n", "else:\n", " print('NG')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲再帰\n", "\n", "一般に、定義しようとするもの自身を定義の中で参照することを、\n", "**再帰**と言います。\n", "再帰による定義を再帰的定義と言います。\n", "\n", "たとえば、数列の漸化式は再帰的定義と考えられます。\n", "実際に、`n` 番目のフィボナッチ数を `fib(n)` とおくと、\n", "`fib(n)` は次のような漸化式を満たします。\n", "\n", "```Python\n", "fib(n) = n ただし n<2\n", "fib(n) = fib(n-1) + fib(n-2) ただし n>=2\n", "```\n", "\n", "この漸化式を用いて以下のように実際にフィボナッチ数を計算することができます。\n", "```Python\n", "fib(0) = 0\n", "fib(1) = 1\n", "fib(2) = fib(1) + fib(0) = 1 + 0 = 1\n", "fib(3) = fib(2) + fib(1) = 1 + 1 = 2\n", "fib(4) = fib(3) + fib(2) = 2 + 1 = 3\n", "fib(5) = fib(4) + fib(3) = 3 + 2 = 5\n", "...\n", "```\n", "\n", "この漸化式から、以下のように `fib(n)` の再帰的定義が得られます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def fib(n):\n", " if n < 2:\n", " return n\n", " else:\n", " return fib(n-1) + fib(n-2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "実際に、以下のように `fib(n)` の値が求まります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fib(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def absolute(x):\n", " if x < 0:\n", " return -x\n", " else:\n", " return x" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sign(x):\n", " if x < 0:\n", " return -1\n", " if x > 0:\n", " return 1\n", " return 0" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/1/1-4.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 1-4. テストとデバッグ\n", "\n", "テストとデバッグについて説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/errors.html\n", "\n", "## 仕様・テスト・デバッグ\n", "\n", "プログラムを書くときに、実現しようとしている事柄を**仕様**と呼びます。\n", "\n", "対象のプログラムが仕様に適合しているかを、実際にプログラムを動作させて検査することを、**テスト**と呼びます。\n", "テストの際に、テスト対象に与える入出力ペアのことを、**テストケース**と呼びます。\n", "\n", "書いたプログラムが仕様に適合しているかは、一般に自明ではありません。\n", "テストによって、仕様に反したプログラムの振舞いが、しばしば浮き彫りになります。\n", "仕様に反したプログラムの振舞いの原因を、**バグ**と呼び、それを取り除くことを**デバッグ**と呼びます。\n", "\n", "プログラミングでは、典型的には\n", "\n", "* 仕様を分析する\n", "* プログラムを書く\n", "* テストする\n", "* デバッグする\n", "\n", "という4つの行いを、必要に応じて繰り返すことになります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## assert文\n", "\n", "テストとデバッグに有用なのが、**assert文**です。\n", "これは、`assert` の次に書かれた条件式が真であるべきだと仕様を宣言する文です。\n", "偽であった場合は、`AssertionError` が発生してプログラムがそこで停止します。\n", "\n", "与えられた引数を二乗する関数 `square` を用いた具体例を示します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def square(x):\n", " return x*x\n", "\n", "x = -2\n", "assert square(x) >= 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このassert文では、仕様として条件式 `square(x) >= 0` を宣言しています。\n", "`square` 関数が「二乗する」という仕様に沿っているなら、その条件式は真であるべきです。\n", "そして、実際 `square` はその仕様に適合しているので、ここではassert文が実行されても何も起きません。\n", "\n", "しかし、`square` にバグがあった場合は、話が変わります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "def square(x):\n", " return x+x # バグがある\n", "\n", "x = -2\n", "assert square(x) >= 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルを実行すると、 `AssertionError` が生じます。\n", "\n", "このように、assert文は、それが存在する場所で、満たされていなければならない前提条件を記述するために用います。\n", "assert文で停止したら、記述された前提条件に関わる部分にバグがあることが判明します。\n", "\n", "テストケースは、テスト対象が満たすべき仕様という側面があるので、assert文はテストにも用いられます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def square(x):\n", " return x*x\n", "\n", "assert square(2) == 4\n", "assert square(-2) == 4\n", "assert square(0) == 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の例では、`square`に対する3つのテストケースについて、assert文でテストしています。テストケースが満たされた(つまりassert文で停止しなかった)からと言って、テスト対象の `square` が正しいとは言えませんが、仕様への適合度が高いことから、尤もらしいとは言えます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## エラーの分類\n", "\n", "不正なプログラムからは、様々なエラーが生じます。\n", "\n", "エラーには大きく分けて、構文エラー・実行時エラー・論理エラーの3つがあります。\n", "以下では、それぞれの意味と、典型例を示します。\n", "\n", "### 構文エラー\n", "\n", "**構文エラー**(syntax error)とは、プログラムコードが、Pythonの構文に違反しているときに生じるエラーです。\n", "\n", "Pythonにおける構文エラーの典型例として、\n", "\n", "* クォートや括弧の閉じ忘れ\n", "* コロンのつけ忘れ\n", "* インデントの崩れ\n", "* 全角スペースの利用\n", "* `==` の代わりに `=` を使う\n", "* 変数の代わりに文字列を使う(Cf. [2-1 文字列](../2/2-1.ipynb))\n", "\n", "などが挙げられます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print('This is the error) # クォートの閉じ忘れ" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def f() # コロンの付け忘れ\n", " return 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def f():\n", "return 1 # インデントの崩れ" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "1 + 1 # 全角スペースの利用" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の例を実行するとわかるように、構文エラーがあると `SyntaxError` や `IndentationError` などが発生します。\n", "それに付随するエラーメッセージが、構文エラーの具体的内容とおおよその位置を説明してくれます。\n", "\n", "構文エラーに直面した際は、エラーメッセージをよく読んで、原因を推察しましょう。\n", "上の例が示すように、エラーメッセージの説明は、必ずしも分かり易くないですが、原因の位置を絞りこむには有用です。\n", "\n", "Pythonでは、構文エラーが実行時に発生しているように見えますが、実際には、実行しようとするプログラムコードの解釈に失敗することでエラーが生じています。\n", "つまり、構文エラーは、プログラムの実行によって生じるエラーではなく、実行できなかったことで生じるエラーです。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 実行時エラー\n", "\n", "**実行時エラー**(runtime error)とは、プログラムを実行した際に生じるエラー全般を指します。\n", "簡単に言えば、プログラムを異常停止させるエラーです。\n", "\n", "実行時エラーが生じる典型的な状況として、\n", "\n", "* 存在しない名前の利用(変数名・関数名・メソッド名の誤植)\n", "* グローバル変数のつもりでローカル変数を参照(Cf. [3-3 関数](../3/3-3.ipynb))\n", "* ゼロによる除算\n", "* 辞書に登録されていないキーに対する値を取得(Cf. [3-1 辞書](../3/3-1.ipynb))\n", "* 存在しないファイルの読み込み(Cf. [4-1 ファイル入出力](../4/4-1.ipynb))\n", "* assert文における条件の不成立\n", "\n", "などが挙げられます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "undefined_variable # 未定義の変数の参照" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 1\n", "def f():\n", " x = x # グローバル変数のつもりでローカル変数を参照\n", "f()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "1/0 # ゼロによる除算" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "{'a': 1}['b'] # 登録されていないキーに対する値を参照" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "open('non-existent.txt', 'r') # 存在しないファイルの読み込み" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "実行時エラーについては、送出される例外名(上の例では `NameError`・`UnboundLocalError`・`ZeroDivisionError`・`KeyError`・`FileNotFoundError`)が自己説明的であり、それに付随するエラーメッセージも、大抵原因を分かり易く説明してくれます。\n", "\n", "実行時エラーに直面した際は、発生した例外名とエラーメッセージをよく読んで、エラーに関連する言語機能(たとえば辞書やファイル)の仕組みを改めて確認しましょう。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 論理エラー\n", "\n", "**論理エラー**(logic error)とは、プログラムを実行できるが、意図したように動作しないことを意味します。\n", "これは、プログラムから発生するエラーではなく、プログラムを書いた人のエラーです。\n", "\n", "バグと呼ばれるものの多くは、論理エラーです。\n", "したがって、デバッグでは、プログラムを書いた人の意図と、プログラムの振舞いを比較検証することになります。\n", "\n", "assert文は、仕様違反という論理エラーを、 `AssertionError` という実行時エラーに変換していると見做すことができます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## デバッグの具体例\n", "\n", "デバッグの具体的なシナリオを説明します。\n", "次の関数 `median(x, y, z)` は、`x` と `y` と `z` の中央値(真ん中の値)を求めようとするものです。\n", "ただし、 `x` と `y` と `z` は相異なる数であると仮定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def median(x, y, z):\n", " if x > y:\n", " x = y\n", " y = x\n", " if z < x:\n", " return x\n", " if z < y:\n", " return z\n", " return y\n", "\n", "assert median(3, 1, 2) == 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように、この `median` は間違っています。\n", "\n", "さて、`median` は、ローカル変数の `x`・`y`・`z` のいずれかを返す関数です。\n", "これらの変数の値が期待通りの値であるか、 `print` を入れて印字し、観察してみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def median(x, y, z):\n", " print(x, y, z)\n", " if x > y:\n", " x = y\n", " y = x\n", " print(x, y, z)\n", " if z < x:\n", " return x\n", " if z < y:\n", " return z\n", " return y\n", "\n", "assert median(3, 1, 2) == 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数の入口にある最初の `print` では、期待通りに実引数となる `3`・`1`・`2` が、`x`・`y`・`z` に代入されています。\n", "しかし、2番目の `print` では、 `3` が消えて `1` が複製されています。\n", "このことから、この2つの `print` の間にあるif文が疑わしいことが分かります。\n", "\n", "問題のif文は、`x` と `y` の値を入れ替える意図があるものでした。\n", "その意図を正しく反映すると、次のようになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def median(x, y, z):\n", " print(x, y, z)\n", " if x > y:\n", " w = x\n", " x = y\n", " y = w\n", " print(x, y, z)\n", " if z < x:\n", " return x\n", " if z < y:\n", " return z\n", " return y\n", "\n", "assert median(3, 1, 2) == 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "期待通りに動きました。 \n", "最後に、デバッグ用に導入した `print` は、`median` の仕様には含まれないので、きちんと消しましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def median(x, y, z):\n", " if x > y:\n", " w = x\n", " x = y\n", " y = w\n", " if z < x:\n", " return x\n", " if z < y:\n", " return z\n", " return y\n", "\n", "assert median(3, 1, 2) == 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## コーディングスタイル\n", "\n", "実は、生じたバグを取る対処法よりも、そもそもバグが生じにくくする予防法の方が大切です。\n", "Pythonにおいて特に重要視されているのが、**コーディングスタイル**、つまりコードの書き方です。\n", "読みにくい(可読性の低い)コードだと、些細なミスが生じやすく、また見つけにくいからです。\n", "\n", "Pythonでは[**PEP8**](https://www.python.org/dev/peps/pep-0008/)([非公式日本語訳](http://pep8-ja.readthedocs.io/ja/latest/))と呼ばれる公式のスタイルガイドがあります。\n", "PEP8には様々な側面でスタイルに関する規則があり、コードの可読性を高めることが強く推奨されています。\n", "ここまでに扱った言語の要素について、たとえば、\n", "\n", "* インデントは半角スペースを4つで1レベル\n", "* `=` `+=` `==` などの演算子の前後に半角スペースを1つ入れる\n", "* `*` と `+` の複合式では `+` の前後に半角スペースを1つ入れる(例:`2*x + y`)\n", "* 関数の開き括弧の前にスペースを入れない\n", "* `l` `I` `O` を変数名として使わない\n", "* 真理値の比較に `==` や `is` を使わない\n", "\n", "などが代表的です。\n", "\n", "PEP8に基づいたコーディングスタイルの自動検査器もあります(参照:[pycodestyle](https://pypi.org/project/pycodestyle/))。\n", "オンラインサービスもいくつか利用できるので(例:[PEP8 online](http://pep8online.com/))、適宜活用してみましょう。\n", "\n", "PEP8には陽に言及されていないものの、プログラミング一般に重要なこともあります。\n", "たとえば、\n", "\n", "* 自己説明的でない“マジックナンバー”ではなく記号的に意味がわかる変数を使う\n", "* 不要なコードは削除する\n", "* 1つの関数では1つのタスクだけを処理する\n", "\n", "などは、可読性を上げる代表的なポイントです。\n", "\n", "勘違いはバグを引き起こします。自らが勘違いしないコードを書くことが肝要です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/2/2-1.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 2-1. 文字列 (string)\n", "\n", "文書処理などに必要な文字列について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/introduction.html#strings\n", "\n", "Pythonが扱うデータには様々な種類がありますが、**文字列**はいくつかの文字の並びから構成されるデータです。\n", "Pythonは標準で多言語に対応しており、\n", "英語アルファベットだけではなく日本語をはじめとする多くの言語を取り扱えます。\n", "\n", "文字列は、文字の並びをシングルクォート `'...'`、もしくはダブルクォート `\"...\"` で囲んで記述します。\n", "\n", "以下の例では文字列をそれぞれ、変数 `word1`, `word2` に代入しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1 = 'hello'\n", "word1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word2 = 'Hello'\n", "word2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の変数の値が確かに文字列であることは、組み込み関数 **`type`** によって確認できます。\n", "`type` は、任意のデータを引数として、そのデータの種類を返します。\n", "データの種類は、**データ型**もしくは**型**と呼ばれます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(word1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`str`** は文字列のデータ型を意味します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(word2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`str` は組み込み関数としても用いられます。\n", "組み込み関数 **`str`** を使えば、任意のデータを文字列に変換できます。\n", "一般に、データ型は、そのデータ型への変換を行う関数として用いられることが多いです。\n", "\n", "1-1で学んだ数値を文字列に変換したい場合、次のように行います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word3 = str(123)\n", "word3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "逆に、`'123'` という文字列を整数に変換するには、1-1で述べた **`int`** という関数を用いることができます。\n", "(実は `int` は整数の型でもあります。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "i = int('123')\n", "i" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数 **`float`** を用いれば文字列を実数に変換できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = float('123.4')\n", "f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列の長さは、組み込み関数 **`len`** を用いて次のようにして求めます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "len(word1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "複数行にわたる文字列を記述するには、トリプルクォート(`'''...'''` もしくは `\"\"\"...\"\"\"`)を用いることができます。\n", "上記の参考URLを参照してください。\n", "トリプルクォートはコメントとしても用いられます。\n", "なお、1-4 のコーディングスタイルのところで紹介したスタイルガイドのPEP8では、\n", "トリプルクォートには `\"\"\"...\"\"\"` を使うのが適切と定められています。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 文字列とインデックス\n", "\n", "文字列はいくつかの文字によって構成されています。\n", "\n", "文字列 `'hello'` の3番目の文字を得たい場合は、以下のような記法を用います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'hello'[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列を値とする変数に対しても同様の記法を用います。多くの場合は変数に対してこの記法を用います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1 = 'hello'\n", "word1[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この括弧内の数値のことを**インデックス**と呼びます。インデックスは `0` から始まるので、\n", "ある文字列の `x` 番目の要素を得るには、インデックスとして `x-1` を指定する必要があります。\n", "\n", "こうして取得した文字は、Pythonでは長さが 1 の文字列として扱われます。\n", "(プログラミング言語によっては、文字列ではなく別の型のデータとして扱われるものもありますので注意してください。)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列に対して、インデックスを指定してその要素を変更することはできません。(次のセルはエラーとなります)\n", "Pythonのデータは、大きく、変更可能なものと変更不可能なものに分類できますが、\n", "文字列は変更不可能なデータです。\n", "したがって、文字列を加工する場合は、新たに別の文字列を作成します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "word1 = 'hello'\n", "word1[0] = 'H'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "また、文字列の長さ以上のインデックスを指定することはできません。(次はエラーとなります)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "word1[100]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "インデックスに負数を指定すると、\n", "文字列を後ろから数えた順序に従って文字列を構成する文字を得ます。\n", "たとえば、文字列の最後の文字を取得するには、`-1` を指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1[-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "まとめると文字列 `hello` の正負のインデックスは以下の表の関係になります。 \n", "\n", "|インデックス|h|e|l|l|o|\n", "|-|--|--|--|--|--|\n", "|0か正|0|1|2|3|4|\n", "|負|-5|-4|-3|-2|-1|" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 文字列とスライス\n", "**スライス**と呼ばれる機能を利用して、文字列の一部(部分文字列)を取得できます。\n", "\n", "具体的には、取得したい部分文字列の先頭の文字のインデックスと最後の文字のインデックスに\n", "`1` を加えた値を指定します。\n", "たとえば、ある文字列の2番目の文字から4番目までの文字の部分文字列を得るには次のようにします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "digits1='0123456789'\n", "digits1[1:4]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列の先頭(すなわち、インデックスが `0` の文字)を指定する場合、次のように行えます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "digits1[0:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "しかし、最初の `0` は省略しても同じ結果となります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "digits1[:3]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "同様に、最後尾の文字のインデックスも、値を省略することもできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "digits1[3:]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "digits1[3:5]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "スライスにおいても負数を指定して、\n", "文字列の最後の方から部分文字列を取得できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "digits1[-4:-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "スライスでは3番目の値を指定することで、とびとびの文字を指定できます。次のように `digits1[3:9:2]` と指定すると、インデックス `3` から2文字おきにインデックス `9` より小さい文字を並べた部分文字列を得ます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "digits1[3:9:2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3番目の値に `-1` を指定することもできます。これを使えば元の文字列の逆向きの文字列を得ることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "digits1[8:4:-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 空文字列\n", "シングルクォート(もしくはダブルクォート)で、何も囲まない場合、長さ 0 の文字列(**空文字列**(くうもじれつ)もしくは、**空列**(くうれつ))となります。\n", "具体的には、下記のように使用します。\n", "\n", "---\n", "```Python\n", "blank = ''\n", "```\n", "---\n", "\n", "空文字列は、次のように、たとえば文字列中からある部分文字列を取り除くのに使用します。\n", "(`replace` は後で説明します。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "price = '2,980円'\n", "price.replace(',', '')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列のスライスにおいて、指定したインデックスの範囲に文字列が存在しない場合、\n", "たとえば、最初に指定したインデックス `x` に対して、\n", "2番目のインデックスの値に `x` 以下のインデックスの値を指定するとどうなるでしょうか?\n", "(ただし、2つのインデックスは同じ符号を持つとし、スライスの3番目の値は用いないとします。)\n", "このような場合、結果は次のように空文字列となります(エラーが出たり、結果が `None` にはならないことに注意してください)。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "digits1='0123456789'\n", "print('空文字列1 = ', digits1[4:2])\n", "print('空文字列2 = ', digits1[-1:-4])\n", "print('空文字列3 = ', digits1[3:3])\n", "print('空文字列ではない = ', digits1[3:-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 文字列の検索\n", "\n", "`文字列A` が `文字列B` を含むかどうかを調べるには、**`in`** 演算子を使います。\n", "具体的には、次のように使用します。\n", "\n", "---\n", "```Python\n", "文字列B in 文字列A\n", "```\n", "---\n", "\n", "調べたい `文字列B` が含まれていれば `True` が、そうでなければ `False` が返ります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'lo' in 'hello'" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'z' in 'hello'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "実際のプログラムでは文字列を値とする変数を用いることが多いでしょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1 = 'hello'\n", "substr1 = 'lo'\n", "substr1 in word1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "substr2 = 'z'\n", "substr2 in word1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`not in`** 演算子は、`in` 演算子の逆を意味します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1 = 'hello'\n", "substr2 = 'z'\n", "substr2 not in word1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲エスケープシーケンス\n", "文字列を作成するにはシングル `'` あるいはダブルクォート `\"` で囲むと説明しました。\n", "これらの文字を含む文字列を作成するには、**エスケープシーケンス**と呼ばれる特殊な文字列を使う必要があります。\n", "\n", "たとえば、下のように文字列に `'` を含む文字列を `'` で囲むと文字列の範囲がずれてエラーとなります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "non_escaped = 'This is 'MINE''\n", "non_escaped" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "エラーを避けるには、エスケープシーケンスで `'` を記述します、具体的には `'` の前に `\\` と記述すると、`'` を含む文字列を作成できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "escaped1 = 'This is \\'MINE\\''\n", "escaped1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "実は、シングルクォートで囲む代わりにダブルクォートを使えばエスケープシーケンスを使わずに記述できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "doublequated = \"This is 'MINE'\"\n", "doublequated" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "他にも、ダブルクォートを表す `\\\"`、`\\` を表す `\\\\` 、改行を表す `\\n` など、様々なエスケープシーケンスがあります。 " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "escaped2 = \"時は金なり\\n\\\"Time is money\\\"\\nTime is \\\\\"\n", "print(escaped2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3連のシングルクォート、もしくはダブルクォートを利用すれば、 `\\\"` や `\\n` を使わずに記述できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "triple_single_quated = '''時は金なり\n", "'Time is money'\n", "Time is \\\\''' \n", "print(triple_single_quated)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "triple_double_quated = \"\"\"時は金なり\n", "'Time is money'\n", "Time is \\\\\"\"\" \n", "print(triple_single_quated)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、プログラムの一部を無効に(コメントアウト)したいとき、\n", "3連のクォートで囲んで文字列にしてしまうことがあります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## バックスラッシュの表示と入力\n", "\n", "エスケープシーケンスの先頭にある文字は、バックスラッシュ `\\`(Unicode `U+005C`)です。\n", "これはPythonに限った話ではないですが、バックスラッシュは環境(正確にはフォント)によって見え方が異なります。\n", "Windows上のフォントでは、円記号 `¥` として見えることが多いです。\n", "macOS上のフォントでは、そのままバックスラッシュとして見えることが多いです。\n", "\n", "JIS配列キーボードでは、バックスラッシュキーがないことがあります。\n", "Windows上では、円記号 `¥` キーでバックスラッシュが入力できます。\n", "macOS上では、`Alt` + `¥` キーでバックスラッシュが入力できます。\n", "ただし、IME設定によっても入力方法は変わるので注意してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('\\n') # 改行文字(バックスラッシュ + n)\n", "print('¥n') # 改行文字でない(円記号 + n)\n", "print('⧵n') # 改行文字でない(Unicode U+29F5 のバックスラッシュ演算子 + n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 文字列の連結\n", "**`+`** 演算子を用いれば文字列同士を**連結**できます。\n", "この演算では新しい文字列が作られ、元の文字列は変化しません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1 = 'hello'\n", "word2 = ' world'\n", "text1 = word1 + word2\n", "text1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`*`** 演算子で文字列の繰り返し回数を指定できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1 = 'hello'\n", "word1 * 3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 文字列とメソッド\n", "文字列に対する操作を行うため、様々な**メソッド**(関数のようなもの)が用意されています。\n", "\n", "メソッドは必要に応じて `(...)` 内に引数を与え、以下のように使用します。\n", "\n", "---\n", "```Python\n", "文字列.メソッド名(式, ...)\n", "# あるいは\n", "文字列変数.メソッド名(式, ...)\n", "```\n", "---\n", "\n", "文字列には以下のようなメソッドが用意されています。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **置換**\n", "\n", "**`replace`** メソッドは、指定した `部分文字列A` を、別に指定した `文字列B` で置き換えた文字列を作成します。\n", "この操作では、元の文字列は変化しません。具体的には、次のように使用します。\n", "\n", "---\n", "```Python\n", "文字列.replace(部分文字列A, 文字列B)\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1 = 'hello'\n", "word1.replace('l', '123')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習\n", "\n", "英語の文章からなる文字列 `str_engsentences` が引数として与えられたとき、`str_engsentences` 中に含まれる全ての句読点(`.`, `,`, `:`, `;`, `!`, `?`)を削除した文字列を返す関数 `remove_punctuations` を作成してください。\n", "(練習の解答はこのノートブックの一番最後にあります。)\n", "\n", "次のセルの `...` のところを書き換えて `remove_punctuations(str_engsentences)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def remove_punctuations(str_engsentences):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(remove_punctuations('Quiet, uh, donations, you want me to make a donation to the coast guard youth auxiliary?') == 'Quiet uh donations you want me to make a donation to the coast guard youth auxiliary')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習\n", "\n", "ATGCの4種類の文字から成る文字列 `str_atgc` が引数として与えられたとき、文字列 `str_pair` を返す関数 `atgc_bppair` を作成してください。ただし、`str_pair` は、`str_atgc` 中の各文字列に対して、\n", "`A` を `T` に、`T` を `A` に、`G` を `C` に、`C` を `G` に置き換えたものです。\n", "\n", "次のセルの `...` のところを書き換えて `atgc_bppair(str_atgc)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def atgc_bppair(str_atgc):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(atgc_bppair('AAGCCCCATGGTAA') == 'TTCGGGGTACCATT')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **検索**\n", "\n", "**`index`** メソッドにより、指定した `部分文字列B` が `文字列A` のどこに存在するか調べることができます。具体的には、次のように使用します。\n", "\n", "---\n", "```Python\n", "文字列A.index(部分文字列B)\n", "```\n", "---\n", "\n", "ただし、指定した部分文字列が文字列に複数回含まれる場合、最初のインデックスが返されます。また、指定した部分文字列が文字列に含まれない場合は、エラーとなります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1 = 'hello'\n", "word1.index('lo')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1.index('l')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下はエラーとなります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "word1.index('a')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`find`** メソッドも `index` と同様に部分文字列を検索し、最初に出現するインデックスを返します。\n", "\n", "`index` との違いは、部分文字列が含まれない場合エラーとはならず `-1` が返されることです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1 = 'hello'\n", "word1.find('a')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習\n", "\n", "コロン (`:`) を1つだけ含む文字列 `str1` を引数として与えると、コロンの左右に存在する文字列を入れ替えた文字列を返す関数 `swap_colon(str1)` を作成してください。\n", "\n", "次のセルの `...` のところを書き換えて `swap_colon(str1)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def swap_colon(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(swap_colon('hello:world') == 'world:hello')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **数え上げ**\n", "\n", "**`count`** メソッドにより、指定した `部分文字列B` が `文字列A` にいくつ存在するか調べることができます。\n", "\n", "---\n", "```Python\n", "文字列A.count(部分文字列B)\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word1 = 'hello'\n", "word1.count('l')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'aaaaaaa'.count('aa')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習\n", "\n", "ATGCの4種類の文字から成る文字列 `str_atgc` と塩基名(`A`, `T`, `G`, `C` のいずれか)を指定する文字列 `str_bpname` が引数として与えられたとき、`str_atgc` 中に含まれる塩基 `str_bpname` の数を返す関数 `atgc_count` を作成してください。\n", "\n", "次のセルの `...` のところを書き換えて `atgc_count(str_atgc, str_bpname)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def atgc_count(str_atgc, str_bpname):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(atgc_count('AAGCCCCATGGTAA', 'A') == 5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **大文字**・**小文字**\n", "**`lower`**, **`capitalize`**, **`upper`** メソッドを用いると、文字列の中の英文字を小文字に変換したり、大文字に変換したりすることができます。\n", "\n", "これらの操作では、元の文字列は変化しません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "upper_dna = 'DNA'\n", "upper_dna.lower() # 全ての文字を小文字にする" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "upper_dna" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lower_text = 'hello world!'\n", "lower_text.capitalize() # 先頭文字を大文字にする" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lower_text" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lower_text.upper() #全ての文字を大文字にする" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lower_text" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲空白文字の削除\n", "\n", "半角スペース `' '`・改行文字 `'\\n'`・タブ文字 `'\\t'`・全角スペース `' '` などを総称して**空白文字**と呼びます。\n", "\n", "`strip` メソッドを用いると、文字列の前後にある連続した空白文字を削除した文字列を取得できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "' abc\\n'.strip()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "' a b c \\n'.strip()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "左側の空白だけ削除する `lstrip` と右側の空白だけ削除する `rstrip` もあります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "' abc\\n'.lstrip()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "' abc\\n'.rstrip()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **文字列の比較演算**\n", "\n", "比較演算子、`==`, `<`, `>` などを用いて、2つの文字列を比較することもできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('abc' == 'abc')\n", "print('ab' == 'abc')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('abc' != 'abc')\n", "print('ab' != 'abc')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列の大小の比較は、いわゆる辞書式による比較で、文字列の最初の文字から順に比較して大小を決めます。\n", "片方がもう片方を拡張したものであれば、拡張した方を大きいとします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('abc' <= 'abc')\n", "print('abc' < 'abc')\n", "print('abc' < 'abd')\n", "print('ab' < 'abc')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "英語の文字列 `str_engsentences` が引数として与えられたとき、それが全て小文字である場合、`True` を返し、そうでない場合、 `False` を返す関数 `check_lower` を作成してください。\n", "\n", "次のセルの `...` のところを書き換えて `check_lower(str_engsentences)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def check_lower(str_engsentences):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_lower('down down down') == True)\n", "print(check_lower('There were doors all round the hall, but they were all locked') == False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 初心者によくある誤解 --- **変数**と**文字列**の混乱\n", "\n", "初心者によくある誤解として、変数と文字列を混乱する例が見られます。たとえば、文字列を引数に取る次のような関数 `func` を考えます( `func` は引数として与えられた文字列を大文字にして返す関数です)。 " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def func(str1):\n", " return str1.upper()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここで変数 `str2` を引数として `func` を呼ぶと、`str2` に格納されている文字列が大文字になって返ってきます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "str2 = 'abc'\n", "func(str2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次のように `func` を呼ぶと上とは結果が異なります。次の例では変数 `str2` (に格納されている文字列 `abc`)ではなく、文字列 `'str2'` を引数として `func` を呼び出しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "str2 = 'abc'\n", "func('str2')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "コンマ (`,`) を含む英語の文章からなる文字列 `str_engsentences` が引数として与えられたとき、`str_engsentences` 中の一番最初のコンマより後の文章のみかならなる文字列 `str_res` を返す関数 `remove_clause` を作成してください。ただし、 `str_res` の先頭は大文字のアルファベットとしてください。\n", "\n", "次のセルの `...` のところを書き換えて `remove_clause(str_engsentences)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def remove_clause(str_engsentences):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(remove_clause(\"It's being seen, but you aren't observing.\") == \"But you aren't observing.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def remove_punctuations(str_engsentences):\n", " str1 = str_engsentences.replace('.', '') # 指定の文字を空文字に置換\n", " str1 = str1.replace(',', '')\n", " str1 = str1.replace(':', '')\n", " str1 = str1.replace(';', '')\n", " str1 = str1.replace('!', '')\n", " str1 = str1.replace('?', '')\n", " return str1\n", "#remove_punctuations('Quiet, uh, donations, you want me to make a donation to the coast guard youth auxiliary?')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def atgc_bppair(str_atgc):\n", " str_pair = str_atgc.replace('A', 't')# 指定の文字に置換。ただし全て小文字\n", " str_pair = str_pair.replace('T', 'a')\n", " str_pair = str_pair.replace('G', 'c')\n", " str_pair = str_pair.replace('C', 'g')\n", " str_pair = str_pair.upper() # 置換済みの小文字の列を大文字に変換\n", " return str_pair\n", "#atgc_bppair('AAGCCCCATGGTAA') " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def swap_colon(str1):\n", " #コロンの位置を取得する # findでもOK\n", " col_index = str1.index(':')\n", " #コロンの位置を基準に前半と後半の部分文字列を取得する\n", " str2, str3 = str1[:col_index], str1[col_index+1:]\n", " #部分文字列の順序を入れ替えて結合する\n", " str4 = str3 + ':' + str2\n", " return str4\n", "#swap_colon('hello:world')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def atgc_count(str_atgc, str_bpname):\n", " return str_atgc.count(str_bpname)\n", "#atgc_count('AAGCCCCATGGTAA', 'A') " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def check_lower(str_engsentences):\n", " if str_engsentences == str_engsentences.lower():#元の文字列と小文字に変換した文字列を比較する\n", " return True\n", " return False\n", "#check_lower('down down down')\n", "#check_lower('There were doors all round the hall, but they were all locked')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def remove_clause(str_engsentences):\n", " int_index = str_engsentences.find(',')\n", " str1 = str_engsentences[int_index+2:]\n", " return str1.capitalize()\n", "#remove_clause(\"It's being seen, but you aren't observing.\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/2/2-2.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 2-2. リスト (list)\n", "\n", "複数のデータを要素としてまとめて取り扱うデータとして、リストとタプルについて説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/introduction.html#lists\n", "- https://docs.python.org/ja/3/tutorial/datastructures.html#tuples-and-sequences\n", "\n", "文字列を構成する要素は文字のみでしたが、**リスト**では構成する要素としてあらゆる型のデータを指定できます。\n", "他のプログラミング言語では、リストに相当するものとして**配列**(もしくはアレイ)やベクターなどがあります。\n", "\n", "リストを作成するには、リストを構成する要素をコンマで区切り全体をかぎ括弧 `[...]` で囲みます。 \n", "\n", "以下のセルでは数値を要素とするリストを作成して、変数に代入しています。\n", "さらに、文字列と同様に組み込み関数 `type` を用いて、変数の値がリストであることを確認しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [0, 10, 20, 30, 40, 50]\n", "numbers" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(numbers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "リストのデータ型は **`list`** です。\n", "(なお、後で見るように、`list` は他のデータをリストに変換する関数としても用いられます。)\n", "\n", "次に文字列を構成要素とするリストを作成してみます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fruits = ['apple', 'banana', 'chelly']\n", "fruits" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "リストの要素としてあらゆる型のデータを指定でき、それらは混在してもかまいません。\n", "以下のセルでは、数値と文字列が混在しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers_fruits = [10, 'apple', 20, 'banana', 30]\n", "numbers_fruits" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次のように、何も要素を格納していないリスト(**空リスト**)を作成できます。\n", "空リストはプログラム実行の途中結果を記録する場合などによく使われています。\n", "具体的な例については、後述する `append` メソッドの項を参照してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "empty=[]\n", "empty" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、`[]` を用いて空リストを作成するたびに、\n", "常に新しいオブジェクト(それまでに作られたオブジェクトとは同一でないオブジェクト)が生成されます。\n", "詳しくは「▲オブジェクトの等価性と同一性」を参照してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## リストとインデックス\n", "文字列の場合と同様に、インデックスを指定してリストの要素を取り出せます。\n", "リストの `x` 番目の要素を取得するには次のような記法を用います。\n", "インデックスは 0 から始まることに注意してください。\n", "\n", "```Python\n", "リスト[x-1]\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "abcd = ['a', 'b', 'c', 'd']\n", "abcd[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列の場合とは異なり、リストは変更可能なデータです。\n", "すなわちインデックスで指定されるリストの要素は、代入によって変更できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "abcd = ['a', 'b', 'c', 'd']\n", "abcd[2] = 'hello'\n", "abcd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列と同様に、スライスを使った範囲指定も可能です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "abcd = ['a', 'b', 'c', 'd']\n", "abcd[1:3]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "abcd = ['a', 'b', 'c', 'd']\n", "abcd[0:4:2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "リストのスライスに対しては、代入も可能です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "abcd = ['a', 'b', 'c', 'd']\n", "abcd[1:3] = ['x', 'y', 'z']\n", "abcd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "リスト `ln` を引数として取り、`ln` の偶数番目のインデックスの値を削除したリストを返す関数 `remove_evenindex` を作成してください(ただし、0 は偶数として扱うものとします)。\n", "\n", "ヒント:スライスを使います。\n", "\n", "以下のセルの `...` のところを書き換えて `remove_evenindex(ln)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def remove_evenindex(ln):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(remove_evenindex(['a', 'b', 'c', 'd', 'e', 'f', 'g']) == ['b', 'd', 'f'] )\n", "print(remove_evenindex([1, 2, 3, 4, 5]) == [2, 4])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **多重リスト**\n", "リストの要素としてリストを指定することもできます。\n", "リストを要素とするリストは多重リストと呼ばれます。\n", "次は二重リストの例です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lns = [[1, 2, 3], [10, 20, 30], ['a', 'b', 'c']]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "多重リストの要素指定は複数のインデックスで行います。\n", "前の例で外側の `[]` で示されるリストの2番目の要素のリスト、\n", "すなわち `[10, 20, 30]` の最初の要素は次のように指定します。 " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lns[1][0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3番目のリストそのものを取り出したいときは、次のように指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lns[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のようにリストの要素として、リストを値とする変数を指定することもできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lns2 = [lns, ['x', 1, [11, 12, 13]], ['y', [100, 120, 140]] ]\n", "lns2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lns2[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## リストに対する関数・演算子・メソッド\n", "\n", "### リストの要素数\n", "\n", "組み込み関数 **`len`** はリストの長さ、すなわち要素数、を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [0, 10, 20, 30, 40, 50]\n", "len(numbers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `max` と `min`\n", "\n", "リストを引数とする関数は色々とあります。\n", "関数 **`max`** は、数のリストが与えられると、その中の最大値を返します。\n", "同様に関数 **`min`** はリストの中の最小値を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [30, 50, 10, 20, 40, 60]\n", "max(numbers)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [30, 50, 10, 20, 40, 60]\n", "min(numbers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`max` と `min` は文字列のリストに対しても適用できます。文字列の比較は、いわゆる辞書順で行われます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "characters = ['e', 'd', 'a', 'c', 'f', 'b']\n", "min(characters)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `sum`\n", "\n", "関数 **`sum`** は、数のリストが与えられると、その要素の総和を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [30, 50, 10, 20, 40, 60]\n", "sum(numbers)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sum([])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### リストと演算子" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "演算子 **`+`** によってリストの連結、**`*`** によって連結における繰り返し回数を指定することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [0, 10, 20, 30, 40, 50]\n", "numbers + ['a', 'b', 'c']" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers*3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "要素が全て同じ値(たとえば、`0` )のリストを作る最も簡単な方法は、この `*` 演算子を使う方法です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "zero10 = [0] * 10\n", "zero10" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`*` は `+` を繰り返し行うのと同じ結果を返します。\n", "たとえば、`x*3` は `x+x+x` と同じ結果を返します。\n", "\n", "`x` が多重リストのとき、`x` の要素であるリストが `y` の中に複数回現れます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = [[0, 1], [2, 3]]\n", "y = x*3\n", "y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このとき、`x` の要素が変更されると、`y` の中では複数箇所に変化が起こるので、注意してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x[0][0] = 99\n", "y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "これは、`y` の中の複数個所にあるオブジェクトが同一だからです。\n", "詳しくは、以下の「▲オブジェクトの等価性と同一性」を参照してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "演算子 **`in`** は、左辺の要素がリストに含まれれば `True` を、それ以外では `False` を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "10 in numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "リストに対する `in` 演算子は、論理演算 `or` を簡潔に記述するのに用いることもできます。 たとえば、\n", "\n", "---\n", "```Python\n", "a1 == 1 or a1 == 3 or a1 == 7:\n", "```\n", "---\n", "\n", "は\n", "\n", "---\n", "```Python\n", "a1 in [1, 3, 7]:\n", "```\n", "---\n", "\n", "と同じ結果を得られます。 `or` の数が多くなる場合は、`in` を用いた方がより読みやすいプログラムを書くことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a1 = 1\n", "print(a1 == 1 or a1 == 3 or a1 == 7, a1 in [1, 3, 7])\n", "a1 = 3\n", "print(a1 == 1 or a1 == 3 or a1 == 7, a1 in [1, 3, 7])\n", "a1 = 5\n", "print(a1 == 1 or a1 == 3 or a1 == 7, a1 in [1, 3, 7])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`in` 演算子は、左辺の要素がリストに含まれるかどうかを、\n", "リストの要素を最初から順に調べることで判定しています。\n", "したがって、リストの長さに比例した時間がかかります。\n", "つまり、リストの長さが大きければ、それなりの時間がかかることに注意してください。\n", "\n", "**`not in`** 演算子は、`in` 演算子の逆を意味します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "10 not in numbers" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "11 not in numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 指定した要素のインデックス取得と数えあげ\n", "\n", "**`index`** メソッドは引数で指定した要素のインデックスの番号を返します。\n", "文字列には `index` に加えてこれと似た `find` メソッドもありましたが、リストでは使えません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [0, 10, 20, 30, 40, 50]\n", "numbers.index(20) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`count`** メソッドは指定した要素の数を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "all20 = [20]*3\n", "all20.count(20) # 指定した要素のリスト内の数" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 並べ替え(**`sort`** メソッド)\n", "\n", "`sort` メソッドはリスト内の要素を並べ替えます。\n", "引数に何も指定しなければ昇順でとなります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [30, 50, 10, 20, 40, 60]\n", "numbers.sort()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "characters = ['e', 'd', 'a', 'c', 'f', 'b']\n", "characters.sort()\n", "characters" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`reverse = True` オプションを指定すれば、要素を降順に並べ替えることもできます。\n", "(これは 3.3 のキーワード引数と呼ばれるものですが、ここでは天下り的に、\n", "並べ替えの方法を指定する情報と理解しておいてください。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [30, 50, 10, 20, 40, 60]\n", "numbers.sort(reverse = True)\n", "numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 並べ替え(**`sorted`** 組み込み関数)\n", "\n", "関数 `sorted` ではリストを引数に取って、そのリスト内の要素を昇順に並べ替えた結果をリストとして返します。\n", "\n", "---\n", "```Python\n", "sorted(リスト)\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [30, 50, 10, 20, 40, 60]\n", "sorted(numbers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列の比較は、いわゆる辞書順で行われます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "characters = ['e', 'd', 'a', 'c', 'f', 'b']\n", "sorted(characters)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`sorted` においても、 `reverse = True` と記述することで要素を降順に並べ替えることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [30, 50, 10, 20, 40, 60]\n", "sorted(numbers, reverse=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ついでですが、多重リストをソートするとどのような結果が得られるか確かめてみてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lns = [[20, 5], [10, 30], [40, 20], [30, 10]]\n", "lns.sort()\n", "lns" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 破壊的(インプレース)な操作と非破壊的な生成" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上記では、`sort` メソッドと `sorted` 関数を紹介しましたが、両者の使い方が異なることに気が付きましたか?\n", "\n", "具体的には、` sort` メソッドでは元のリストが変更されています。\n", "一方、`sorted` 関数では元のリストはそのままになっています。もう一度確認してみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [30, 50, 10, 20, 40, 60]\n", "numbers.sort()\n", "print('sortメソッドの実行後の元のリスト:', numbers)\n", "numbers = [30, 50, 10, 20, 40, 60]\n", "sorted(numbers)\n", "print('sorted関数の実行後の元のリスト:', numbers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように、`sort` メソッドは元のリストを変更してしまいます。\n", "このような操作を**破壊的**あるいは**インプレース** (**in-place**) であるといいます。\n", "\n", "一方、`sorted` 関数は新しいリストを生成し元のリストを破壊しません、このような操作は**非破壊的**であるといいます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`sorted` 関数を用いた場合、その返値(並べ替えの結果)は新しい変数に代入して使うことができます。 \n", "\n", "一方、`sort` メソッドはリストを返さないためそのような使い方はできません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [30, 50, 10, 20, 40, 60]\n", "numbers1 = sorted(numbers)\n", "print('sorted関数の返値:', numbers1)\n", "\n", "numbers = [30, 50, 10, 20, 40, 60]\n", "numbers2 = numbers.sort()\n", "print('sortメソッドの返値:', numbers2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## リストを操作するメソッドなど\n", "\n", "ここからはリストを操作するためのメソッドなどを紹介していきます。\n", "\n", "メソッドや組み込み関数が破壊的であるかどうかは、一般にその名称などからは判断できません。\n", "それぞれ破壊的かどうか理解してから利用しなければなりません。\n", "\n", "なお、次の `append` メソッド以外は、必要に応じて参照すればよく、\n", "それ以降タプルの項まで飛ばして構いません。\n", "\n", "### リストに要素を追加する\n", "\n", "**`append`** メソッドはリストの最後尾に指定した要素を付け加えます。\n", "\n", "---\n", "```Python\n", "リスト.append(追加する要素) \n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [10, 20, 30, 40, 50]\n", "numbers.append(100)\n", "numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`append` は、上述した空のリストと組み合わせて、あるリストから特定の条件を満たす要素のみからなる新たなリストを構成する、というような状況でしばしば用いられます。たとえば、リスト `numbers1 = [10, -10, 20, 30, -20, 40, -30]` から `0` より大きい要素のみを抜き出したリスト `positives` は次のように構成することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers1 = [10, -10, 20, 30, -20, 40, -30] \n", "positives = [] # 空のリストを作成する\n", "positives.append(numbers1[0])\n", "positives.append(numbers1[2])\n", "positives.append(numbers1[3])\n", "positives.append(numbers1[5])\n", "positives" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲リストにリストの要素を追加する\n", "\n", " **`extend`** メソッドはリストの最後尾に指定したリストの要素を付け加えます。\n", "\n", "---\n", "```Python\n", "リスト.extend(追加するリスト) \n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [10, 20, 30, 40, 50]\n", "numbers.extend([200, 300, 400, 200]) # numbers += [200, 300, 400, 200] と同じ\n", "numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲リストに要素を挿入する\n", "\n", "**insert** メソッドはリストのインデックスを指定した位置に新しい要素を挿入します。 \n", "\n", "---\n", "```Python\n", "リスト.insert(インデックス, 新しい要素)\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [10, 20, 30, 40, 50]\n", "numbers.insert(1, 1000)\n", "numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲リストから要素を削除する\n", "\n", "**`remove`** メソッドは指定した要素をリストから削除します。 \n", "\n", "---\n", "```Python\n", "リスト.remove(削除したい要素)\n", "```\n", "---\n", "\n", "ただし、指定した要素が複数個リストに含まれる場合、一番最初の要素が削除されます。また、指定した値がリストに含まれない場合はエラーとなります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [10, 20, 30, 40, 20] \n", "numbers.remove(30) # 指定した要素を削除\n", "numbers" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers.remove(20) # 指定した要素が複数個リストに含まれる場合、一番最初の要素を削除\n", "numbers" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "numbers.remove(100) # リストに含まれない値を指定するとエラー" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲リストからインデックスで指定した要素を削除する\n", "\n", "**`pop`** メソッドはリストから指定したインデックスを削除し、その要素を返します。\n", "\n", "---\n", "```Python\n", "リスト.pop(削除したい要素のインデックス)\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [10, 20, 20, 30, 20, 40]\n", "print(numbers.pop(3))\n", "print(numbers)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "インデックスを指定しない場合、最後尾の要素を削除して返します。\n", "\n", "---\n", "```Python\n", "リスト.pop()\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ln = [10, 20, 30, 20, 40]\n", "print(ln.pop())\n", "print(ln)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲リスト要素を削除する\n", "\n", "**`del`** 文は指定するリストの要素を削除します。具体的には以下のように削除したい要素をインデックスで指定します。 \n", "`del` も破壊的であることに注意してください。\n", "\n", "---\n", "```Python\n", "del リスト[x]\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [10, 20, 30, 40, 50]\n", "del numbers[2]\n", "numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "スライスを使うことも可能です。\n", "\n", "---\n", "```Python\n", "del リスト[x:y]\n", "```\n", "---\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [10, 20, 30, 40, 50]\n", "del numbers[2:4]\n", "numbers" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲リストの要素を逆順にする\n", "\n", "**`reverse`** メソッドはリスト内の要素の順序を逆順にします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "characters = ['e', 'd', 'a', 'c', 'f', 'b']\n", "characters.reverse()\n", "characters" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲ **`copy`**\n", "リストを複製します。\n", "すなわち、`ln` の値がリストであるとき、`ln.copy()` は `ln` と同じ長さのリストを新たに作って、\n", "`ln` の要素を新しいリストに同じ順番で格納して、その新しいリストを返します。\n", "\n", "複製されたリストに変更を加えたとしても、もとのリストは影響を受けません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [10, 20, 30, 40, 50]\n", "numbers2 = numbers.copy()\n", "del numbers[1:3]\n", "numbers.reverse()\n", "print(numbers)\n", "print(numbers2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一方、代入を用いた場合には影響を受けることに注意してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [10, 20, 30, 40, 50]\n", "numbers2 = numbers\n", "del numbers[1:3]\n", "numbers.reverse()\n", "print(numbers)\n", "print(numbers2)" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## リストと文字列の相互変換\n", "\n", "文字列は変更不可能である一方、リスト変更可能です。\n", "そのため、文字列処理をする際は、文字列のリストに一旦変換してから、変更を加えて、文字列に変換することが典型的です。\n", "ここでは、文字列とリストの相互変換の方法を示します。\n", "\n", "まず、文字列 `s` を `list` 関数に渡すと、`s` を文字単位で区切ったリストが得られます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list('abc123')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字単位ではなく、指定された文字列で区切ってリストにする際は、 **`split`** メソッドを使います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'banana'.split('n')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'A and B and C'.split(' and ')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`split` を無引数で呼び出すと、連続した空白文字を区切りと見做します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'A B\\nC '.split()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "逆に、文字のリストを連結して1つの文字列にする際は、 **`join`** メソッドを次のように使います。\n", "\n", "---\n", "```python\n", "接合点に挿入する文字列.join(文字列のリスト)\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "''.join(['a', 'b', 'c', '1', '2', '3'])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'n'.join(['ba', 'a', 'a'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、 `join` の引数は、文字列のリストだけでなく、文字列のタプルでも問題ありません。\n", "タプルについては、次で述べます。\n", "\n", "### 練習\n", "\n", "emailアドレス `email` とドメイン名 `domain` を引数に取って、`email` のドメイン名を `domain` に置き換える関数 `change_domain(email, domain)` を作成してください。\n", "なお、emailアドレスのドメイン名とは、 `'@'` で区切られた右側の部分を意味します。\n", "\n", "次のセルの `...` のところを書き換えて `change_domain(email, domain)` を完成させてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def change_domain(email, domain):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(change_domain('spam@utokyo-ipp.org', 'ipp.u-tokyo.ac.jp') == 'spam@ipp.u-tokyo.ac.jp')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## タプル (tuple)\n", "\n", "**タプル**は、リストと同じようにデータの並びであり、あらゆる種類のデータを要素にできます。\n", "ただし、リストと違ってタプルは一度設定した要素を変更できません(文字列も同様でした)。\n", "すなわち、タプルは変更不可能なデータです。\n", "したがって、リストの項で説明したメソッドの多く、要素を操作するもの、は適用できないのですが、\n", "逆にいうと、作成した後で要素を変更する必要がない場合は、\n", "タプルの方が実装の効率がよいので、リストよりもタプルを使うべきです。\n", "\n", "たとえば、関数が複数の値をリストにして返し、呼び出し側がすぐにリストをばらばらにして値を取り出すような場合は、\n", "リストよりもタプルを使うべきです。\n", "また、平面上の点を表そうとするとき、x座標とy座標を別々に変化させる必要がなければ、\n", "`(3, 5)` のようなタプルを使うのが自然です。\n", "このように、タプルを作成するには数学におけるのと同様に要素を丸括弧 `(...)` で囲みます。\n", "\n", "例を見ましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 3\n", "y = 5\n", "point = (x, y)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "point" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(point)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers3 = (1, 2, 3)\n", "numbers3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "実は、丸括弧なしでもタプルを作成できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers3 = 1,2,3\n", "numbers3" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "要素が1つだけの場合は、 `t = (1)` ではなく、次のようにします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "onlyone = (1,)\n", "onlyone" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`t = (1)` だと、`t = 1` と同じになってしまいます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "onlyone = (1)\n", "onlyone" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "何も要素を格納していないタプル(**空タプル**)は `()` で作成できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "empty = ()\n", "empty" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "リストや文字列と同様に、インデックスや組み込み関数を使った操作が可能です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers3 = (1, 2, 3)\n", "numbers3[1] # インデックスの指定による値の取得" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "len(numbers3) # lenはタプルを構成する要素の数" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers3[1:3] # スライス" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上述しましたが、一度作成したタプルの要素を後から変更することはできません。\n", "したがって以下のプログラムはエラーとなります。\n", "\n", "---\n", "```Python\n", "numbers3 = (1, 2, 3)\n", "numbers3[1] = 5\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "組み込み関数 **`list`** を使って、タプルをリストに変換できます。\n", "(`list` はリストのデータ型でもあります。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers3 = (1, 2, 3)\n", "list(numbers3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "組み込み関数 **`tuple`** を使って、逆にリストをタプルに変換できます。\n", "(`tuple` はタプルのデータ型でもあります。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers2 = [1, 2]\n", "tuple(numbers2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "整数の要素からなるリスト `ln` を引数として取り、\n", "`ln` に含まれる要素を逆順に格納したタプルを返す関数 `reverse_totuple` を作成してください。\n", "\n", "以下のセルの `...` のところを書き換えて `reverse_totuple(ln)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def reverse_totuple(ln):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(reverse_totuple([1, 2, 3, 4, 5]) == (5, 4, 3, 2, 1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 多重代入\n", "**多重代入**では、左辺に複数の変数などを指定してタプルやリストの全ての要素を一度の操作で代入することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [0, 10, 20, 30, 40]\n", "[a, b, c, d, e] = numbers\n", "b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のようにしても同じ結果を得られます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "a, b, c, d, e = numbers\n", "b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "多重代入は文字列に対しても実行可能です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a, b, c, d, e = 'hello'\n", "d" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "タプルに対しても実行可能です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers3 = (1, 2, 3)\n", "(x,y,z) = numbers3\n", "y" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のように様々な書き方が可能です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x,y,z = numbers3\n", "print(y)\n", "(x,y,z) = (1, 2, 3)\n", "print(y)\n", "x,y,z = (1, 2, 3)\n", "print(y)\n", "(x,y,z) = 1, 2, 3\n", "print(y)\n", "x,y,z = 1, 2, 3\n", "print(y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "多重代入を使うことで、2つの変数に格納された値の入れ替えを行う手続きはしばしば用いられます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 'apple'\n", "y = 'pen'\n", "x, y = y, x \n", "print(x, y) #w = x; x = y; y = w と同じ結果が得られる" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## リストやタプルの比較演算\n", "数値などを比較するのに用いた比較演算子を用いて、2つのリストやタプルを比較することもできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print([1, 2, 3] == [1, 2, 3])\n", "print([1, 2] == [1, 2, 3])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print((1, 2, 3) == (1, 2, 3))\n", "print((1, 2) == (1, 2, 3))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print([1, 2, 3] != [1, 2, 3])\n", "print([1, 2] != [1, 2, 3])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print((1, 2, 3) != (1, 2, 3))\n", "print((1, 2) != (1, 2, 3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "大小の比較は、いわゆる辞書式による比較で、リストやタプルの最初の要素から順に比較して大小を決めます。\n", "片方がもう片方を拡張したものであれば、拡張した方を大きいとします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print([1, 2, 3] <= [1, 2, 3])\n", "print([1, 2, 3] < [1, 2, 3])\n", "print([1, 2, 3] < [1, 2, 4])\n", "print([1, 2] < [1, 2, 3])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print((1, 2, 3) <= (1, 2, 3))\n", "print((1, 2, 3) < (1, 2, 3))\n", "print((1, 2, 3) < (1, 2, 4))\n", "print((1, 2) < (1, 2, 3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## for文による繰り返しとリスト・タプル\n", "\n", "きまった操作の繰り返しはコンピュータが最も得意とする処理のひとつです。\n", "リストのそれぞれの要素にわたって操作を繰り返したい場合は**for文**を用います。\n", "\n", "リスト `ls` の要素全てに対して、`実行文` を繰り返すには次のように書きます。\n", "\n", "---\n", "```Python\n", "for value in ls:\n", " 実行文\n", "```\n", "---\n", "\n", "`for` で始まる行の `in` の後に処理対象となるリスト `ls` が、`in` の前に変数 `value` が書かれます。\n", "\n", "`ls` の最初の要素、すなわち `ls[0]` が `value` に代入され `実行文` が処理されます。\n", "`実行文` の処理が終われば、`ls` の次の要素が `value` に代入され、処理が繰り返されます。\n", "このようにして、`ls` の要素に対する処理が `len(ls)` 回繰り返されると、for文の処理が終了します。 \n", "\n", "ここでの `in` の働きは、先に説明したリスト要素の有無を検査する `in` とは異なることに、\n", "そして、if文と同様、 `実行文` の前にはスペースが必要であることに注意してください。\n", "\n", "次に具体例を示します。\n", "3つの要素を持つリスト `ls` から1つずつ要素を取り出し、変数 `value` に代入しています。\n", "`実行文` では `value` を用いて取り出した要素を参照しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ls = [0,1,2]\n", "\n", "for value in ls:\n", " print('For loop:', value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`in` の後に直接リストを記述することもできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for value in [0,1,2]:\n", " print('For loop:', value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`実行文` の前にスペースがないとエラーが出ます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "for value in [0,1,2]:\n", "print('For loop:', value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "エラーが出れば意図した通りにプログラムが組めていないのにすぐ気が付きますが、\n", "エラーが出ないために意図したプログラムが組めていないことに気が付かないことがあります。\n", "たとえば、次のような内容を実行しようとしていたとします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for value in [0,1,2]:\n", " print('During for loop:', value)\n", " print('During for loop, too:', value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "後者の `print` の行のスペースの数が間違ってると、次のような結果になる場合がありますので注意してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for value in [0,1,2]:\n", " print('During for loop:', value)\n", "print('During for loop, too:', value) #この行のスペースの数が間違っていたがエラーは出ない" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "タプルの要素にまたがる処理もリストと同様に行えます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for value in (0,1,2):\n", " print('For loop:', value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下はリストに対するfor文の典型例です。`numbers` は数のリストとします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [0,1,2,3,4,5]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のようにして、このリストの要素の自乗から成るリストを求めることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "squares1 = []\n", "for x in numbers:\n", " squares1.append(x**2)\n", "squares1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`squares1` には最初に空リストが代入されます。\n", "そして、`numbers` の各要素の自乗がこのリストに次々と追加されます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "整数の要素からなるリスト `ln` を引数として取り、`ln` の要素の総和を返す関数 `sum_list` を作成してください。\n", "\n", "以下のセルの `...` のところを書き換えて `sum_list(ln)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_list(ln):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(sum_list([10, 20, 30]) == 60)\n", "print(sum_list([-1, 2, -3, 4, -5]) == -3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## for文による繰り返しと文字列\n", "\n", "for文を使うと文字列全体にまたがる処理も可能です。\n", "文字列 `str1` をまたがって一文字ずつの繰り返し処理を行う場合は次のように書きます。\n", "ここで、`c` には取り出された一文字(の文字列)が代入されています。\n", "\n", "---\n", "```Python\n", "for c in str1:\n", " 実行文\n", "```\n", "---\n", "\n", "`str1` で与えられる文字列を一文字ずつ大文字で出力する処理は以下のようになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "str1 = 'Apple and pen'\n", "for c in str1:\n", " print(c.upper())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "ATGCの4種類の文字から成る文字列 `str_atgc` が引数として与えられたとき、次のようなリスト `list_count` を返す関数 `atgc_countlist` を作成してください。ただし、 `list_count` の要素は、各塩基 `bp` に対して `str_atgc` 中の `bp` の出現回数と `bp` の名前を格納した(長さ2の)リストとします。\n", "\n", "ヒント:文字列 `'ATGC'` に対する繰り返しを用いることができます。\n", "\n", "以下のセルの `...` のところを書き換えて `atgc_countlist(str_atgc)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def atgc_countlist(str_atgc):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(sorted(atgc_countlist('AAGCCCCATGGTAA')) == sorted([[5, 'A'], [2, 'T'], [3, 'G'], [4, 'C']]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## for文によるリスト初期化の短縮記法\n", "\n", "先に、リストの要素の自乗から成るリストを求める例を説明しました。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = [0,1,2,3,4,5]\n", "\n", "squares1 = []\n", "for x in numbers:\n", " squares1.append(x**2)\n", "squares1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "詳しくは6-1で説明されますが、**内包表記**を用いて書き換えると、以下のように1行で書くことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "squares2 = [x**2 for x in numbers]\n", "squares2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "すなわち、\n", "```Python\n", "[x を含む式 for x in リストを返す式]\n", "```\n", "という式は、\"リストを返す式\" が返したリストの各要素を `x` に代入して \"`x` を含む式\" を計算し、\n", "その結果をリストにして返します。\n", "もちろん、変数は `x` でなくてもよいです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[y**2 for y in numbers]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲オブジェクトの等価性と同一性\n", "\n", "1-3で、Pythonにおける値はオブジェクトと総称されますと述べました。\n", "ここでは、オブジェクトの等価性と同一性について説明します。\n", "\n", "既に見てきたように、演算子 `==` を用いて**オブジェクトの等価性**を判定できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = []\n", "b = []" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このとき、`a` と `b` の値はどちらも空リストなので、以下のように `a` の値と `b` の値は等価です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a == b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "しかし、`[` で始まり `]` で終わる式を評価すると、\n", "必ず新しいリスト(オブジェクト)が作られて返されるので、\n", "`a` と `b` の値は同一ではありません。\n", "\n", "**オブジェクトの同一性**は演算子 **`is`** を用いて判定できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a is b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "リストの要素はオブジェクトなので、要素ごとに等価性と同一性が定まります。\n", "\n", "例として、`a` と `b` を要素とするリスト `c` を作ります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c = [a, b]\n", "c" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c[0] is c[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`a` を変化させてみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a.append(1)\n", "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "すると `c` は以下のようになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここで、`a` と `b` は等価でなくなりました。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a == b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次に、`b` を要素として二重に含むリスト `d` を作ります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "d = [b, b]\n", "d" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "d[0] is d[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`b` を変化させてみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "b.append(1)\n", "b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "すると `d` は以下のようになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "d" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "演算子 `==` でリストを比較すると、要素まで見て等価性を判定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(a, b)\n", "a == b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "演算子 `==` は、要素の比較も `==` で行います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(c, d)\n", "c == d" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一方、オブジェクトの同一性は変化しません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a is b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`==` の否定形は `!=` で、`is` の否定形は **`is not`** です。\n", "`not x == y` は `x != y` と書けます。`not x is y` は `x is not y` と書けます。\n", "`is not` はこれで1つの演算子なので注意してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "c != d" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a is not b" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def remove_evenindex(ln):\n", " ln2 = ln[1::2]\n", " return ln2\n", "#remove_evenindex(['a', 'b', 'c', 'd', 'e', 'f', 'g'])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def change_domain(email, domain):\n", " return '@'.join([email.split('@')[0], domain])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def reverse_totuple(ln):\n", " ln.reverse()\n", " tup = tuple(ln)\n", " return tup\n", "#reverse_totuple([1, 2, 3, 4, 5])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_list(ln):\n", " int_sum = 0\n", " for value in ln:\n", " int_sum += value\n", " return int_sum\n", "#sum_list([10, 20, 30])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def atgc_countlist(str_atgc):\n", " list_count = []\n", " for value in 'ATGC':\n", " int_bpcnt = str_atgc.count(value)\n", " list_count.append([int_bpcnt, value])\n", " return list_count\n", "#atgc_countlist('AAGCCCCATGGTAA') " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/2/2-3.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 2-3. 条件分岐\n", "\n", "制御構造のうち**条件分岐**について説明します。\n", "\n", "参考:\n", "\n", "- https://docs.python.org/ja/3/tutorial/controlflow.html#if-statements\n", "\n", "**`if`** で始まり条件分岐を行う制御構造によって、条件に応じてプログラムの動作を変えることができます。\n", "\n", "ここではまず「インデント」について説明し、そのあとで条件分岐について説明します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## インデントによる構文\n", "\n", "条件分岐の前に、Pythonの**インデント**(行頭の空白、字下げ)について説明します。\n", "Pythonのインデントは実行文をグループにまとめる機能を持ちます。\n", "\n", "プログラム文はインデントレベル(深さ)の違いによって異なるグループとして扱われます。\n", "細かく言えば、インデントレベルが進む(深くなる)とプログラム文はもとのグループの下に位置する\n", "別のグループに属するものとして扱われます。\n", "逆に、インデントレベルが戻る(浅くなる)までプログラム文は同じグループに属することになります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "具体例として、第1回で定義した関数 `bmax()` を使って説明します:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def bmax(a,b):\n", " if a > b: \n", " return a \n", " else:\n", " return b\n", "\n", "print('Hello World')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この例では1行目の関数定義 `def bmax(a,b):` の後から第1レベルのインデントが開始され5行目まで続きます。\n", "すなわち、5行目までは関数 `bmax` を記述するプログラム文のグループということです。 \n", "\n", "次に、3行目の一行のみの第2レベルのインデントの実行文は、\n", "if文(`if` による条件分岐)の論理式 `a > b` が `True` の場合にのみ実行されるグループに属します。 \n", "そして、4行目の `else` ではインデントが戻されています。\n", "5行目から再び始まる第2レベルの実行文は2行目の論理式が `False` の場合に実行されるグループに属します。 \n", "\n", "最後に、7行目ではインデントが戻されており、これ以降は関数 `bmax()` の定義とは関係ないことがわかります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pythonではインデントとして半角スペース4つが広く利用されています。\n", "本教材でもこの書式を利用します。\n", "1-4 のコーディングスタイルのところで紹介したスタイルガイドのPEP8でも、\n", "半角スペース4つが推奨されています。\n", "\n", "Codeセルでは行の先頭でTabを入力すれば、自動的にこの書式のインデントが挿入されます。\n", "また、インデントを戻すときはShift-Tabが便利です。\n", "なお、Colaboratoryでは、Tabを入力すると半角スペース2つのインデントが挿入されます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **`if`** ... **`else`** による条件分岐\n", "\n", "これまで関数 `bmax` を例にとって説明しましたが、一般にif文では、 `式` が真であれば `if` 直後のグループが、偽であれば `else` 直後のグループが、それぞれ実行されます。(真であった場合、`else` 直後のグループは実行されません。)\n", "\n", "---\n", "\n", "```Python\n", "if 式:\n", " ここのグループは「式」が真のときにのみ実行される\n", "else:\n", " ここのグループは「式」が偽のときにのみ実行される\n", "```\n", "\n", "---\n", "\n", "また、`else` は省略することができます。省略した場合、「式」が真のときに `if` 直後のグループが実行されるのみになります。\n", "\n", "---\n", "\n", "```Python\n", "if 式:\n", " ここのグループは「式」が真のときにのみ実行される\n", "ここのグループは常に実行される\n", "```\n", "\n", "---\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "条件が複雑になってくると、if文の中にさらにif文を記述して、条件分岐を**入れ子**(**ネスト**)にすることがあります。\n", "この場合は、インデントはさらに深くなります。\n", "\n", "そして、下の2つのプログラムの動作は明らかに異なることに注意が必要です。\n", "\n", "---\n", "\n", "```Python\n", "if 式1:\n", " ここのグループは「式1」が真のときにのみ実行される\n", " if 式2:\n", " ここのグループは「式1」「式2」が共に真のときにのみ実行される\n", " if 式3:\n", " ここのグループは「式1」「式2」「式3」が全て真のときにのみ実行される\n", " ここのグループは「式1」と「式2」が共に真のときにのみ実行される\n", " ここのグループは「式1」が真のときにのみ実行される\n", "ここのグループは常に実行される\n", "```\n", "\n", "---\n", "\n", "```Python\n", "if 式1:\n", " ここのグループは「式1」が真のときにのみ実行される\n", "ここのグループは常に実行される\n", "if 式2:\n", " ここのグループは「式2」が真のときにのみ実行される (「式1」には影響されない)\n", "ここのグループは常に実行される\n", "if 式3:\n", " ここのグループは「式3」が真のときにのみ実行される (「式1」「式2」には影響されない)\n", "ここのグループは常に実行される\n", "```\n", "\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **`if`** ... **`elif`** ... **`else`** による条件分岐\n", "\n", "ここまでで `if ... else` 文について紹介しましたが、複数の条件分岐を続けて書くことができる `elif` を紹介します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "たとえばテストの点数から評定(優、良、可、...)を計算したい場合など、「条件1のときは処理1、条件1に該当しなくても条件2であれば処理2、更にどちらでもない場合、条件3であれば処理3、...」という処理を考えます。\n", "`if ... else` による文のみでこの処理を行う場合、次のようなプログラムになってしまいます:\n", "\n", "---\n", "\n", "```Python\n", "if 式1:\n", " 「式1」が真のときにのみ実行するグループ\n", "else:\n", " if 式2:\n", " 「式1」が偽 かつ「式2」が真のときにのみ実行するグループ\n", " else:\n", " if 式3:\n", " 「式1」「式2」が偽 かつ「式3」が真のときにのみ実行するグループ\n", " else:\n", " ...\n", "``` \n", "\n", "---\n", "\n", "このような場合には、以下のように **`elif`** を使うとより簡潔にできます:\n", "\n", "---\n", "\n", "``` Python\n", "if 式1:\n", " ここのグループは「式1」が真のときにのみ実行される\n", "elif 式2:\n", " ここのグループは「式1」が偽 かつ「式2」が真のときにのみ実行される\n", "elif 式3:\n", " ここのグループは「式1」「式2」が偽 かつ「式3」が真のときにのみ実行される\n", "else:\n", " ここのグループは「式1」「式2」「式3」がいずれも偽のときにのみ実行される\n", "```\n", "\n", "---\n", "\n", "`if` ... `elif` ... `else` では、条件は上から順に評価され、式が真の場合、\n", "直後の実行文グループのみが実行され終了します。\n", "その他の場合、すなわち全ての条件が \n", "`False` のときは、`else` 以降のグループが実行されます。\n", " \n", "なお、`elif` もしくは `else` 以降を省略することも可能です。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "関数 `exception3(x,y,z)` の引数は以下の条件を満たすとします。\n", "\n", "- `x` と `y` と `z` の値は整数です。\n", "- `x` と `y` と `z` のうち、2つの値は同じで、もう1つの値は他の2つの値とは異なるとします。\n", "\n", "その異なる値を返すように、以下のセルの `...` のところを書き換えて `exception3(x,y,z)` を定義してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def exception3(x,y,z):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次のセルで動作を確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(exception3(1,2,2))\n", "print(exception3(4,2,4))\n", "print(exception3(9,3,9))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "関数 `exception9(a)` の引数は以下の条件を満たすとします。\n", "\n", "- 引数 `a` には、長さが9のリストが渡されます。\n", "- このリストの要素は整数ですが、1つの要素を除いて、残りは要素の値は全て同じとします。\n", "\n", "その1つの要素の値を返すように、以下のセルの `...` のところを書き換えて `exception9(a)` を定義してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def exception9(a):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次のセルで動作を確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(exception9([1,2,2,2,2,2,2,2,2]))\n", "print(exception9([4,4,4,4,4,2,4,4,4]))\n", "print(exception9([9,9,9,9,9,9,9,9,3]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲複数行にまたがる条件式\n", "\n", "複雑な条件式では複数行に分割した方が見やすい場合もありあます。\n", "ここでは、式を複数行にまたがって記述する1つの方法を示します。\n", "1つ目は、丸括弧で括られた式を複数の行にまたがって記述する方法です。\n", "2つ目は、行末にバックスラッシュ **`\\`** を置く方法です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "### 丸括弧で括る方法\n", "x, y, z = (-1, -2, -3)\n", "if (x < 0 and y < 0 and z < 0 and\n", " x != y and y != z and x != z):\n", " print('x, y and z are different and negatives.')\n", "\n", "### 行末にバックスラッシュ(\\) を入れる方法\n", "\n", "x, y, z = (-1, -2, -3)\n", "if x < 0 and y < 0 and z < 0 and \\\n", " x != y and y != z and x != z:\n", " print('x, y and z are different and negatives.')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **`if`** ... **`elif`** ... **`else`** における条件の評価\n", "\n", "`if` と `elif` による条件分岐では、`if` あるいは `elif` に続く条件式が `True` の場合、\n", "それ以降の `elif` に続く条件式の評価は行われません。\n", "\n", "以下のプログラムで `x` を `3`, `0`, `-4` とした際に何が表示されるかを予想したのちに実行してみましょう。\n", "\n", "特に、 `x = -4` としたときの動作に注意してください。(`x is zero.` は表示されません。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 3 # example: 3, 0, -4\n", "\n", "if x > 0:\n", " print('x is greater than zero.')\n", "elif x < 0:\n", " print('x is less than zero, but x will be 0')\n", " x = 0\n", "else:\n", " print('x is zero.')\n", "\n", "print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "以下のプログラムはプログラマの意図どおりに動作しません。\n", "`print` の出力内容から意図を判断して条件分岐を書き換えてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = -1\n", "if x < 3:\n", " print('x is larger than or equal to 2, and less than 3')\n", "elif x < 2:\n", " print('x is larger than or equal to 1, and less than 2')\n", "elif x < 1:\n", " print('x is less than 1')\n", "else:\n", " print('x is larger or equal to 3')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `or` もしくは `and` で結合された条件の評価\n", "\n", "if文に与える条件が `or` もしくは `and` で結合されている場合、条件は左から順に評価され、\n", "不要(以降の式を評価するまでもなく自明)な評価は省かれます。\n", "\n", "たとえば、`if a == 0 or b == 0:` において\n", "最初の式 `a == 0` が `True` の場合、式全体の結果が `True` となることは自明なので、\n", "二番目の式 `b == 0` を評価することなく続く実行文グループが実行されます。\n", "\n", "逆に、`if a == 0 and b == 0:` において、\n", "最初の式が `False` の場合、以降の式は評価されることなく処理が進みます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のセルで示す例の1行目で、`x` の値を `0`, `-4` に変更し、表示される内容を予想し、予想通りか確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "x = 10 # del x のエラーを抑制するため\n", "y = 10\n", "\n", "del x # x を未定義に\n", "\n", "if x > 5 or y > 5: \n", " print(\"'x' or 'y' is larger than 5\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 10\n", "y = 10 # del y のエラーを抑制するため\n", "\n", "del y # y を未定義に\n", "\n", "if x > 5 or y > 5: \n", " print(\"'x' or 'y' is larger than 5\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲**3項演算子**(条件式)\n", "\n", "Pythonでは以下のように `if ... else` を1行に書くこともできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 0\n", "sign = 'positive or zero' if x >= 0 else 'negative'\n", "print(sign)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "これは、以下と等価です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 0\n", "if x >= 0 :\n", " sign = 'positive or zero'\n", "else:\n", " sign = 'negative'\n", "print(sign)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答\n", "以下は解答例です。これ以外にも様々な解答があり得ます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def exception3(x,y,z):\n", " if x==y:\n", " return z\n", " elif x==z:\n", " return y\n", " else:\n", " return x" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def exception9(a):\n", " x = a[0] + a[1] + a[2]\n", " y = a[3] + a[4] + a[5]\n", " z = a[6] + a[7] + a[8]\n", " if x==y:\n", " return exception3(a[6], a[7], a[8])\n", " elif x==z:\n", " return exception3(a[3], a[4], a[5])\n", " else:\n", " return exception3(a[0], a[1], a[2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解説\n", "最後の練習では、条件文の順番を修正する必要があります。\n", "条件は上から順に処理され、式が真の場合にその「直後の実行文グループのみ」が処理されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = -1\n", "if x < 1:\n", " print('x is less than 1')\n", "elif x < 2:\n", " print('x is larger or equal to 1, and less than 2')\n", "elif x < 3:\n", " print('x is larger or equal to 2, and less than 3')\n", "else:\n", " print('x is larger or equal to 3')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/3/3-1.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 3-1. 辞書 (dictionary)\n", "キーと値を対応させるデータ構造である辞書について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/datastructures.html#dictionaries\n", "\n", "**辞書**は、**キー** (**key**) と**値** (**value**) を対応づけるデータです。\n", "キーとしては、文字列・数値・タプルなどの変更不可能なデータを使うことができますが、\n", "変更可能なデータであるリスト・辞書を使うことはできません。\n", "(辞書も変更可能なデータです。)\n", "一方、値としては、変更の可否にかかわらずあらゆる種類のデータを指定できます。\n", "\n", "たとえば、文字列 `'apple'` をキーとし値として数値 `3` を、`'pen'` をキーとして `5` を対応付けた辞書は、\n", "次のように作成します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple' : 3, 'pen' : 5}\n", "ppap" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(ppap)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "辞書の `キー1` に対応する値を得るには、リストにおけるインデックスと同様に、\n", "\n", "---\n", "```Python\n", " 辞書[キー1]\n", "```\n", "---\n", "\n", "とします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple' : 3, 'pen' : 5}\n", "ppap['apple']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "辞書に登録されていないキーを指定すると、エラーになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "ppap['orange']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "キーに対する値を変更したり、新たなキーと値を登録するには代入文を用います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple' : 3, 'pen' : 5}\n", "ppap['apple'] = 10\n", "ppap['pinapple'] = 7\n", "ppap" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のようにキーから値は取り出せますが、値からキーを直接取り出すことはできません。\n", "また、リストのようにインデックスを指定して値を取得することはできません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "ppap[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "キーが辞書に登録されているかどうかは、演算子 **`in`** を用いて調べることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple': 3, 'pen': 5}\n", "'apple' in ppap" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'banana' in ppap" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "組み込み関数 **`len`** によって、辞書に登録されている要素、キーと値のペア、の数が得られます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple': 3, 'pen': 5}\n", "len(ppap)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`del`** 文によって、登録されているキーの要素を削除することができます。具体的には、次のように削除します。\n", "\n", "---\n", "```Python\n", "del 辞書[削除したいキー]\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple' : 3, 'pen' : 5}\n", "del ppap['pen']\n", "ppap" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "空のリストと同様に空の辞書を作ることもできます。このような空のデータは繰り返し処理でしばしば使われます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "empty_d = {}\n", "empty_d" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "リスト `list1` が引数として与えられたとき、`list1` の各要素 `value` をキー、` value` の `list1` におけるインデックスをキーに対応する値とした辞書を返す関数 `reverse_lookup` を作成してください。\n", "\n", "以下のセルの `...` のところを書き換えて `reverse_lookup(list1)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def reverse_lookup(list1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(reverse_lookup(['apple', 'pen', 'orange']) == {'apple': 0, 'orange': 2, 'pen': 1})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 辞書のメソッド\n", "辞書のメソッドを紹介しておきます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### キーを指定して値を得るメソッド\n", "\n", "**`get`** メソッドは、引数として指定したキーが辞書に含まれてる場合にはその値を取得し、\n", "指定したキーが含まれていない場合には `None` を返します。\n", "`get` を利用することで、エラーを回避し、登録されているかどうかわからないキーを使うことができます。\n", "先に説明したキーを括弧、`[...]`、で指定する方法では、\n", "辞書にキーが存在しないとエラーとなりプログラムの実行が停止してしまいます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "ppap = {'apple' : 3, 'pen' : 5}\n", "print('キーappleに対応する値 = ', ppap.get('apple'))\n", "print('キーorangeに対応する値 = ', ppap.get('orange'))\n", "print('キーorangeに対応する値(エラー) = ', ppap['orange'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "また、`get` に2番目の引数を与えると、その引数の値を「指定したキーが含まれていない場合」に `get` が返す値とすることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple' : 3, 'pen' : 5}\n", "print('キーappleに対応する値 = ', ppap.get('apple', -1))\n", "print('キーorangeに対応する値 = ', ppap.get('orange', -1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲キーがない場合に登録を行う\n", "\n", "**`setdefault`** メソッドは、\n", "指定したキーが辞書に含まれてる場合には、対応する値を返します。 \n", "キーが含まれていない場合には、2番目の引数として指定した値を返すと同時に、キーに対応する値として登録します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple' : 3, 'pen' : 5}\n", "print('キーappleに対応する値 = ', ppap.setdefault('apple', 7))\n", "print('setdefault(\"apple\", 7)を実行後の辞書 = ', ppap)\n", "print('キーorangeに対応する値 = ', ppap.setdefault('orange', 7))\n", "print('setdefault(\"orange\", 7)を実行後の辞書 = ', ppap)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のような `setdefault` を用いた手続きを、`[...]` を用いて書き換えるとたとえば次のようになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple' : 3, 'pen' : 5}\n", "if 'apple' not in ppap:\n", " ppap['apple'] = 7\n", "print('キーappleに対応する値 = ', ppap['apple'])\n", "print('実行後の辞書 = ', ppap)\n", "if 'orange' not in ppap:\n", " ppap['orange'] = 7\n", "print('キーorangeに対応する値 = ', ppap['orange'])\n", "print('実行後の辞書 = ', ppap)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲キーを指定した削除\n", "\n", "**`pop`** メソッドは指定したキーおよびそれに対応する値を削除し、削除されるキーに対応付けられた値を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple' : 3, 'pen' : 5}\n", "print(ppap.pop('pen'))\n", "print(ppap)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲全てのキーと値の削除\n", "**`clear`** メソッドは全てのキーと値を削除します。その結果、辞書は空となります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple' : 3, 'pen' : 5}\n", "ppap.clear()\n", "ppap" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### キーの一覧を得る\n", "**`keys`** メソッドはキーの一覧を返します。これはリストのようなものとして扱うことができ、\n", "`for` ループと組み合わせて繰り返し処理で利用されます(3-2を参照してください)。\n", "以下のように、**`keys`** メソッドが返した結果に関数 `list` を適用すると、\n", "通常のリストになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple' : 3, 'pen' : 5}\n", "list(ppap.keys())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 値の一覧を得る\n", "**`values`** メソッドはキーに対応する全ての値の一覧を返します。これもリストのようなものとして扱うことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list(ppap.values())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### キーと値の一覧を得る\n", "**`items`** メソッドはキーとそれに対応する値をタプルにした一覧を返します。 これもタプルを要素とするリストのようなものとして扱うことができ、forループなどで活用します(3-2を参照してください)。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list(ppap.items())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲辞書を複製する\n", "**`copy`** メソッドは辞書を複製します。リストの場合と同様に一方の辞書を変更してももう一方の辞書は影響を受けません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple': 3, 'pen': 5, 'orange': 7}\n", "ppap2 = ppap.copy()\n", "ppap['banana'] = 9\n", "print(ppap)\n", "print(ppap2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲ ` keys`, `values`, `items` の返値\n", "`keys`, `values`, `items` メソッドの一連の説明では、返値を「リストのようなもの」と表現してきました。\n", "通常のリストとどう違うのでしょうか?\n", "\n", "次の例では、`ppap` の `keys`, `values`, `items` メソッドの返値をそれぞれ `ks`, `vs`, `itms` に代入し、\n", "`print` でそれぞれの内容を表示させています。\n", "\n", "次いで、`ppap` に新たな要素を加えたのちに、同じ変数の内容を表示させています。 \n", "1, 2回目の `print` で内容が異なることに注意してください。\n", "もとの辞書が更新されると、これらの内容も動的に変わります。 " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple': 3, 'pen': 5, 'orange': 7}\n", "ks = ppap.keys()\n", "vs = ppap.values()\n", "itms = ppap.items()\n", "print(list(ks))\n", "print(list(vs))\n", "print(list(itms))\n", "ppap['kiwi'] = 9\n", "print(list(ks))\n", "print(list(vs))\n", "print(list(itms))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 辞書とリスト" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "冒頭で述べたように、辞書では値としてあらゆる型のデータを使用できます。\n", "すなわち、次のように値としてリストを使用する辞書を作成可能です。\n", "リストの要素を参照するには数字インデックスをさらに指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "numbers = {'dozens': [10, 20, 40], 'hundreds': [100, 101, 120, 140]}\n", "print(numbers['dozens'])\n", "print(numbers['dozens'][1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "逆に、辞書を要素とするリストを作成することもできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ppap = {'apple': 3, 'pen': 5}\n", "pets = {'cat': 3, 'dog': 3, 'elephant': 8}\n", "ld = [ppap, pets]\n", "print(ld[1])\n", "print(ld[1]['dog'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "辞書 `dic1` と文字列 `str1` が引数として与えられたとき、\n", "以下のように `dic1` を変更する関数 `handle_collision` を作成してください。\n", "ただし、`dic1` のキーは整数、キーに対応する値は文字列を要素とするリストとします。\n", "\n", "1. `dic1` に `str1` の長さ `n` がキーとして登録されていない場合、`str1` のみを要素とするリスト `ls` を作成し、 `dic1` にキー `n`、`n` に対応する値 `ls` を登録します。\n", "2. `dic1` に `str1` の長さ `n` がキーとして登録されている場合、そのキーに対応する値(リスト)に `str1` を追加します。\n", "\n", "以下のセルの `...` のところを書き換えて `handle_collision(dic1, str1)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def handle_collision(dic1, str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dic1_orig = {3: ['ham', 'egg'], 6: ['coffee', 'brandy'], 9: ['port wine'], 15: ['curried chicken']}\n", "dic1_result = {3: ['ham', 'egg', 'tea'], 6: ['coffee', 'brandy'], 9: ['port wine'], 15: ['curried chicken']}\n", "handle_collision(dic1_orig, 'tea')\n", "print(dic1_orig == dic1_result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def reverse_lookup(list1):\n", " dic1 = {} # 空の辞書を作成する\n", " for value in list1:\n", " dic1[value] = list1.index(value)\n", " return dic1\n", "#reverse_lookup(['apple', 'pen', 'orange'])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def handle_collision(dic1, str1):\n", " if dic1.get(len(str1)) is None:\n", " ls = [str1]\n", " else:\n", " ls = dic1[len(str1)]\n", " ls.append(str1)\n", " dic1[len(str1)] = ls\n", "#handle_collision({3: ['ham', 'egg'], 6: ['coffee', 'brandy'], 9: ['port wine'], 15: ['curried chicken']}, 'tea')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/3/3-2.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 3-2. 繰り返し\n", "\n", "制御構造のうち**繰り返し**について説明します。\n", "\n", "参考:\n", "\n", "- https://docs.python.org/ja/3/tutorial/controlflow.html#for-statements\n", "- https://docs.python.org/ja/3/tutorial/controlflow.html#the-range-function\n", "- https://docs.python.org/ja/3/tutorial/introduction.html#first-steps-towards-programming\n", "- https://docs.python.org/ja/3/tutorial/controlflow.html#break-and-continue-statements-and-else-clauses-on-loops\n", "- https://docs.python.org/ja/3/tutorial/controlflow.html#pass-statements\n", "\n", "繰り返しを行う制御構造 `for` や `while` によって、同じ処理の繰り返しを簡単にプログラムすることができます。\n", "\n", "## for文による繰り返し\n", "\n", "2-2で、リストと文字列に対するfor文の繰り返しについて説明しました。\n", "Pythonにおける**for文**の一般的な文法は以下のとおりです。\n", "\n", "---\n", "```Python\n", "for 変数 in 文字列・リスト・辞書など:\n", " 実行文\n", "```\n", "\n", "---\n", "\n", "if文と同様、 実行文のインデントは深くなっていることに注意してください。\n", "\n", "for文では `in` 以降に与えられる、`文字列・リスト・辞書など` にわたって、\n", "`実行文` のグループを繰り返します。\n", "一般に繰り返しの順番は文字列・リスト・辞書などに要素が現れる順番で、\n", "要素は **`for`** と **`in`** の間の `変数` に代入されます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "リストの場合、リストの要素が最初から順番に取り出されます。以下に具体例を示します。関数 `len` は文字列の長さを返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "words = ['dog', 'cat', 'mouse']\n", "for w in words:\n", " print(w, len(w))\n", "print('finish')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このプログラムで、for文には3つの文字列で構成されるリスト `words` が与えられています。\n", "リストの要素は変数 `w` に順番に代入され、文字列とその長さが印字されます。\n", "そして、最後の要素の処理がおわればfor文の繰り返し(**ループ**)を抜け、完了メッセージを印字します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次は文字列に対する for文の例です。文字列を構成する文字が先頭から一文字ずつ文字列として取り出されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "word = 'supercalifragilisticexpialidocious'\n", "for c in word:\n", " print(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "組み込み関数 **`ord`** は与えられた文字の番号(コード)を整数として返します。\n", "組み込み関数 **`chr`** は逆に与えられた整数をコードとする文字を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(ord('a'))\n", "print(ord('b'))\n", "print(ord('z'))\n", "\n", "print(chr(97))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上で確認しているように、文字 `'a'`, `'b'`, `'z'` のコードはそれぞれ `97`, `98`, `112` です。文字のコードは `'a'` から `'z'` までは連続して `1` ずつ増えていきます。\n", "\n", "これを用いて以下のように英小文字から成る文字列の中の各文字の頻度を求めることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "height = [0] * 26\n", "for c in word:\n", " height[ord(c) - ord('a')] += 1\n", "\n", "print(height)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`height` を視覚化してみましょう。詳しくは、付録の 5-matplotlib を参照してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "\n", "plt.plot(height)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "left = list(range(26)) # range関数については以下を参照してください。\n", "labels = [chr(i + ord('a')) for i in range(26)] # 内包表記については 6-1 を参照ください。\n", "plt.bar(left,height,tick_label=labels)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## for文による繰り返しと辞書\n", "\n", "辞書の要素にわたって操作を繰り返したい場合もfor文を用います。\n", "辞書 `dic1` の全てのキーを変数 `key` に代入しながら、`実行文` を繰り返すには次のように書きます。\n", "\n", "---\n", "```Python\n", "for key in dic1:\n", " 実行文\n", "```\n", "---\n", "\n", "`for` の行の `in` の後を、`dic1` の代わりに `dic1.keys()` としても振舞いは同等であり、辞書のキー一覧を返す **`keys`** メソッドが自動的に使われます。\n", "\n", "次の例では、キーを1つずつ取り出し、`key` に代入した後、 \n", "`key` に対応する値を参照しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dic1 = {'cat': 3, 'dog': 3, 'elephant': 8}\n", "for key in dic1:\n", " print('key:', key, ', value:', dic1[key])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`values`** メソッドを使えば(キーを使わずに)値を1つずつ取り出すこともできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dic1 = {'cat': 3, 'dog': 3, 'elephant': 8}\n", "for value in dic1.values():\n", " print('value:', value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`items`** メソッドを使えばキーと値を一度に取り出すこともできます。\n", "次の例では、`in` の左辺に複数の変数を指定し多重代入を行っています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dic1 = {'cat': 3, 'dog': 3, 'elephant': 8}\n", "for key, value in dic1.items():\n", " print('key:', key, 'value:', value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "実は、辞書の `items` でなくとも、タプルのリストもしくはリストのリストに対しても、同様に複数の変数を指定することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list1 = [[0, 10], [1, 20], [2, 30]]\n", "for i, j in list1:\n", " print(i, j)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "辞書 `dic1` が引数として与えられたとき、次のような辞書 `dic2` を返す関数 `reverse_lookup2` を作成してください。ただし、 `dic1` のキー `key` の値が `value` である場合、 `dic2` には `value` というキーが登録されており、その値は `key` であるとします。また、 `dic1` は異なる2つのキーに対応する値は必ず異なるとします。\n", "\n", "以下のセルの `...` のところを書き換えて `reverse_lookup2` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def reverse_lookup2(dic1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(reverse_lookup2({'apple': 3, 'pen': 5, 'orange': 7}) == {3: 'apple', 5: 'pen', 7: 'orange'})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `range`\n", "\n", "特定の回数の繰り返し処理が必要なときは、**`range`** 関数を用います。\n", "\n", "---\n", "```Python\n", "for value in range(j):\n", " 実行文\n", "```\n", "---\n", "\n", "これによって実行文を `j` 回実行します。具体例を見てみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for value in range(5):\n", " print('Hi!')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "さて、`for` と `in` の間の `value` は変数ですが、 `value` には何が入っているのか確認してみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for value in range(5):\n", " print(value)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "すなわち、`value` は `0` ~ `4` を動くことがわかります。\n", "\n", "この `value` の値を用いることでリスト `ln` の要素を順番に用いることもできます。\n", "回数としてリストの長さ `len(ln)` を指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ln = ['e', 'd', 'a', 'c', 'f', 'b']\n", "for value in range(len(ln)):\n", " print(ln[value])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`range()` 関数は:\n", "\n", "1. 引数を1つ与えると `0` から引数までの整数列を返します。\n", " このとき引数の値は含まれないことの注意してください。\n", "2. 引数を2つあるいは3つ与えると:\n", " * 最初の引数を数列の開始 (start)、2番目を停止 (stop)、3番目を数列の刻み (step) とする整数列を返します。\n", " * 3番目の引数は省略可能で、既定値は `1` となっています。\n", " * 2番目の引数の値は含まれないことの注意してください。\n", "\n", "以下の例は、`0` から `9` までの整数列の総和を計算、印字するプログラムです:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s = 0\n", "for i in range(10):\n", " s = s + i\n", "\n", "print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下の例は、`1` から `9` までの奇数の総和を計算、印字するプログラムです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "s = 0\n", "for i in range(1,10,2):\n", " s = s + i\n", "\n", "print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "引数で与えられる2つの整数 `x`, `y` 間(`x`, `y` を含む)の整数の総和を返す関数 `sum_n` を for文を利用して作成してください。\n", "たとえば、`sum_n(1,3)` の結果は `1 + 2 + 3 = 6` となります。\n", "\n", "以下のセルの `...` のところを書き換えて `sum_n` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_n(x, y):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(sum_n(1, 3) == 6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "整数 `int_size` を引数として取り、\n", "長さが `int_size` であるリスト `ln` を返す関数 `construct_list` を作成してください。\n", "ただし、 `ln` の `i` 番目の要素は `i` とします(`i` は 0 以上 `int_size-1` 以下の整数)。\n", "\n", "以下のセルの `...` のところを書き換えて `construct_list(int_size)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def construct_list(int_size):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(construct_list(10) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `range` とリスト\n", "**`range`** 関数は整数列を返しますが、リストを返さないことに注意してください。\n", "これは、繰り返し回数の大きな for文などで大きなリストを作ると無駄が大きくなるためです。\n", "\n", "`range` 関数を利用して整数列のリストを生成するには、\n", "以下のように `list` を関数として用いて、明示的にリスト化する必要があります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "seq_list = list(range(5)) \n", "print(seq_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## for文の**入れ子**\n", "for文を多重に**入れ子**(**ネスト**)して使うこともよくあります。 まずは次の例を実行してみてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list1 = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]\n", "\n", "for i in range(4):\n", " for j in range(3):\n", " print('list1の', i + 1, '番目の要素(リスト)の', j + 1, '番目の要素 =', list1[i][j])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`i = 0` のときに、2番目(内側)のfor文において、\n", "`j` に `0` から `2` までの値が順に代入されて、各場合に `print` が実行されます。\n", "その後、2番目の for文の実行が終わると、1番目(外側)のfor文の最初に戻って、\n", "`i` の値に新しい値が代入されて、`i = 1` になります。\n", "その後、再度 2番目のfor文を実行することになります。\n", "このときに、この2番目の for文の中で `j` には再度、`0` から `2` までの値が順に代入されることになります。\n", "\n", "決して、「最初に `j = 2` まで代入したから、\n", "もう2番目のfor文は実行しない」という訳ではないことに注意してください。\n", "一度for文の実行を終えて、再度同じfor文(上の例でいうところの2番目の for文)に戻ってきた場合、\n", "その手続きはまた最初からやり直すことになるのです。 " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のプログラムは、変数 `C` に組み合わせの数をリストのリストとして求めます。\n", "\n", "`C[i][j]` は、`i` 個から `j` 個を選ぶ組み合わせの数になります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "C = [[1]]\n", "for i in range(100):\n", " C.append([1]+[0]*i+[1])\n", " for j in range(i):\n", " C[i+1][j+1] = C[i][j] + C[i][j+1]\n", "\n", "C[:10]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`C[100]` を視覚化してみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(C[100])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "次のような関数 `sum_lists` を作成してください。\n", "\n", "- `sum_lists` はリスト `list1` を引数とします。\n", "- `list1` の各要素はリストであり、そのリストの要素は数です。\n", "- `sum_lists` は、`list1` の各要素であるリストの総和を求め、それらの総和を足し合せて返します。\n", "\n", "以下のセルの `...` のところを書き換えて `sum_lists` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_lists(list1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(sum_lists([[20, 5], [6, 16, 14, 5], [16, 8, 16, 17, 14], [1], [5, 3, 5, 7]]) == 158)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "リスト `list1` と `list2` が引数として与えられたとき、次のようなリスト `list3` を返す関数 `sum_matrix` を作成してください。\n", "\n", "- `list1`, `list2`, `list3` は、3つの要素を持ちます。\n", "- 各要素は大きさ3のリストになっており、そのリストの要素は全て数です。\n", "- `list3[i][j]` (ただし、`i` と `j` は共に、0以上2以下の整数)は `list1[i][j]` と `list2[i][j]` の値の和になっています。\n", "\n", "以下のセルの `...` のところを書き換えて `sum_matrix` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_matrix(list1, list2):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(sum_matrix([[1,2,3],[4,5,6],[7,8,9]], [[1,4,7],[2,5,8],[3,6,9]]) == [[2, 6, 10], [6, 10, 14], [10, 14, 18]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## for文の**計算量**\n", "\n", "山口和紀編「情報」第2版(東京大学出版会)には、「**計算量**とは、\n", "アルゴリズムをもとにしたプログラムの実行時間を見積もるための指標である。」と書かれています。\n", "さらに、「この見積もりは**計算量のオーダー**と呼ばれる非常におおまかな尺度で考える。」と書かれています。\n", "(太字は引用時に追加しました。)\n", "\n", "たとえば、リストに対するfor文\n", "```Python\n", "for x in リスト:\n", " 要素xに対する処理\n", "```\n", "では、「要素に対する処理」が要素の数だけ実行されます。\n", "この処理の時間が一定であるとすると、要素の数を $n$ としたとき、\n", "全体の処理には $n$ に比例する時間がかかります。\n", "このことを、**オーダー** $n$ といって、$O(n)$ と書きます。\n", "一方、\n", "```Python\n", "for x in リスト:\n", " for y in 同じリスト:\n", " 要素の組み合わせ(x,y)に対する処理\n", "```\n", "という二重のループでは、要素の組み合わせに対する処理が一定時間で終わるとしても、\n", "ループの中でループが実行されるので、\n", "全体の処理には、$n^2$ に比例する時間がかかります。\n", "このことを $O(n^2)$ と書きます。\n", "$n$ が10倍になったとき、\n", "一重のループの実行時間は10倍にしかなりませんが、\n", "二重ループの実行時間は100倍になります。\n", "$n$ が100倍になったときは、前者は100倍ですが後者は10000倍になります。\n", "\n", "二重ループが明らかでないこともあります。\n", "以下の関数は、リストとして与えられたデータの平均と分散を計算するものです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def average(d):\n", " s = 0\n", " for x in d:\n", " s = s + x\n", " return s/len(d)\n", "\n", "def variance(d):\n", " s = 0\n", " for x in d:\n", " s = s + (x-average(d))**2\n", " return s/len(d)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ガウス分布から100個のデータと10000個のデータを生成して分散を計算してみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import random\n", "d100 = []\n", "for i in range(100):\n", " d100.append(random.gauss(0,10))\n", "d10000 = []\n", "for i in range(10000):\n", " d10000.append(random.gauss(0,10))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "variance(d100)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "variance(d10000)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "10000個の場合は相当に時間がかかることがわかります。\n", "これは、`variance` のfor文の中で `average` を呼んでいるためです。\n", "見かけ上は一重ループなのですが、`average` の中にもループがあるため、\n", "二重ループと同じ時間がかかります。\n", "したがって、10000個の場合は、100個の場合に比べて10000倍時間がかかります。\n", "\n", "ローカル変数を用いて `variance` の定義を書き直してみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def variance(d):\n", " av = average(d)\n", " s = 0\n", " for x in d:\n", " s = s + (x-av)**2\n", " return s/len(d)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "variance(d100)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "variance(d10000)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "10000個の場合でも一瞬で実行が終わったことでしょう。\n", "この場合、一重のループを2回実行しているだけだからです。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **`enumerate`**\n", "for文の繰り返し処理では、要素の順序を把握したいことがあります。\n", "これまで学んだ方法では以下のように書けます。\n", "\n", "---\n", "```Python\n", "i = 0\n", "for val in some_list:\n", " print(i, val)\n", " # 繰り返させたい処理\n", " i += 1\n", "```\n", "\n", "---\n", "\n", "Pythonでは `enumerate()` 関数が用意されており、上のプログラムは以下のように書き換えることができます。\n", "\n", "---\n", "```Python\n", "for i, val in enumerate(some_list):\n", " # 繰り返させたい処理\n", "```\n", "\n", "---\n", "\n", "2つの変数 `i`, `val` が指定されています。\n", "`i` には `0`, `1`, `2`, ... が順に代入されます。\n", "`val` にはリストの要素が順に代入されます。\n", "\n", "たとえば、リストの要素をキー、そのインデックスを値とする辞書が欲しい場合は、以下のように書くことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "words = ['dog', 'cat', 'mouse']\n", "mapping = {}\n", "for i, w in enumerate(words):\n", " mapping[w] = i\n", "\n", "print(mapping) # {'dog': 0, 'cat': 1, 'mouse': 2} が得られる。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **`in`**\n", "Pythonでは `for` ループでリストを展開する `in` とは別に、\n", "2-2 で説明したように、リスト内の要素の有無を検査する **`in`** 演算子と **`not in`** 演算子が定義されています。\n", "以下のように、`if` 文の条件に `in` が出現した場合、for文とは動作が異なるので注意してください。\n", "\n", "---\n", "\n", "```Python\n", "colors = ['red', 'green', 'blue']\n", "color = 'red'\n", "\n", "if color in colors:\n", " # do something\n", "```\n", "\n", "---\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## while文による繰り返し\n", "\n", "**while文**では **`while`** の後の条件式が `False` となるまで、実行文グループを繰り返します。\n", "\n", "下記のプログラムでは、$\\sum_{x=1}^{10}x$ が `total` の値となります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 1\n", "total = 0 \n", "while x <= 10:\n", " total += x\n", " x += 1\n", "\n", "print(x, total)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "条件式が `False` になったときに、 while文から抜けているので、\n", "終了後の `x` の値が `11` になっていることに注意してください。\n", "なお、上の例を for文で実行する場合には以下のようになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "total = 0 \n", "for x in range(11):\n", " total += x\n", "\n", "print(x, total)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 制御構造とreturn文\n", "\n", "**return文**は1-2で説明したように関数を終了し、値を返す(返値)機能を持ちます。\n", "`if`, `for`, `while` といった制御構造の中でreturn文が実行された場合、\n", "ただちに関数の処理を終了し、その後の処理は行われません。\n", "\n", "以下の関数 `simple_lsearch` は与えられたリスト、`lst` に `myitem` と等しいものがあれば `True` を、なければ `False` を返します。\n", "\n", "- 2行目のfor文で `lst` の各要素に対して繰り返しを実行するように指定されています。\n", "- 3行目のif文で要素 `item` が `myitem` と等しい場合、4行目の `return True` でただちに関数を終了しています。\n", "- for文で全てのリスト要素に対してテストが終わり、等しいものがない場合は、5行目の `return False` が実行されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def simple_lsearch(lst, myitem):\n", " for item in lst:\n", " if item == myitem:\n", " return True\n", " return False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **break文**\n", "**break文**は、 for文もしくはwhile文の実行文グループで利用可能です。\n", "break文は実行中のプログラムで最も内側の繰り返し処理を中断し、そのループを終了させる目的で利用されます。\n", "以下のプログラムは、初項 `256`、公比 1/2、の等比級数の和を求めるものです。\n", "ただし、総和が `500` をこえれば打ち切られます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = 256\n", "total = 0\n", "while x > 0:\n", " if total > 500:\n", " break # 500 を超えれば while ループを抜ける\n", " total += x\n", " x = x // 2 # // は少数点以下を切り捨てる除算\n", "\n", "print(x, total)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `str1` と `str2` が引数として与えられたとき、\n", "`str1` が `str2` を部分文字列として含むかどうか判定する関数 `simple_match` を作成してください。\n", "具体的には、`str2` を含む場合、\n", "その部分文字列が開始される `str1` のインデックスを返値として返してください。\n", "`str2` を含まない場合、 `-1` を返してください。\n", "ただし、`simple_match` の中で文字列のメソッドやモジュール(正規表現など)を使ってはいけません。\n", "\n", "以下のセルの `...` のところを書き換えて `simple_match` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def simple_match(str1, str2):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(simple_match('location', 'cat') == 2)\n", "print(simple_match('soccer', 'cat') == -1)\n", "print(simple_match('category', 'cat') == 0)\n", "print(simple_match('carpet', 'cat') == -1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **continue文**\n", "continue文はbreak文同様に、`for` および `while` ループの実行文グループで利用可能です。\n", "continue文は実行中のプログラムで最も内側の繰り返し処理を中断し、次のループの繰り返しの処理を開始します。\n", "\n", "下記のプログラムでは、`colors` リストの `'black'` は印字されませんが `'white'` は印字されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "colors = ['red', 'green', 'blue', 'black', 'white']\n", "for c in colors:\n", " if c == 'black':\n", " continue\n", " print(c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲for文とwhile文における **`else`**\n", "for文およびwhile文では `else` を書くこともできます。\n", "この実行文グループは、ループの最後に一度だけ実行されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "colors = ['red', 'green', 'blue', 'black', 'white']\n", "for c in colors:\n", " if c == 'black':\n", " continue\n", " print(c)\n", "else:\n", " print('')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "for文およびwhile文の `else` ブロックの内容は `continue` で終了したときは実行されますが、一方で\n", "`break` でループを終了したときは実行されません。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **pass文**\n", "\n", "Pythonでは空の実行文グループは許されていません。\n", "一方で、空白のコードブロックを用いることでプログラムが読みやすくなる場合があります。\n", "たとえば以下の、`if` ... `elif` ... `else` プログラムはエラーとなります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "x = -1\n", "if x < 0:\n", " print('x is positive')\n", "elif x == 0:\n", " # IndentationError: expected an indented block\n", "elif 0 < x < 5:\n", " print('x is positive and smaller than 5')\n", "else:\n", " print('x is positive and larger than or equal to 5')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なにもしないpass文を用いて、以下のように書き換えることで正常に実行されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = -1\n", "if x < 0:\n", " print('x is positive')\n", "elif x == 0:\n", " # no error\n", " pass\n", "elif 0 < x < 5:\n", " print('x is positive and smaller than 5')\n", "else:\n", " print('x is positive and larger than or equal to 5')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "以下のプログラムでは1秒おきに `print` が永久に実行されます。\n", "\n", "---\n", "```Python\n", "from time import sleep\n", "\n", "while True:\n", " print('Yeah!')\n", " sleep(1)\n", "```\n", "---\n", "\n", "10回 `print` が実行された後にwhile文を終了するように書き換えてください。\n", "実行中のセルを停止させるには、ストップボタンが使えます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "英語の文章からなる文字列 `str_engsentence` が引数として与えられたとき、\n", "`str_engsentence` 中に含まれる3文字以上の全ての英単語を要素とするリストを返す関数\n", "`collect_engwords` を作成してください。ただし、同じ単語を重複して含んでいて構いません。\n", "\n", "以下のセルの `...` のところを書き換えて `collect_engwords(str_engsentence)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def collect_engwords(str_engsentence):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(collect_engwords('Unfortunately no, it requires something with a little more kick, plutonium.') == ['Unfortunately', 'requires',\n", "'something', 'with', 'little', 'more', 'kick', 'plutonium'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "2つの同じ大きさのリストが引数として与えられたとき、\n", "2つのリストの奇数インデックスの要素を入れ替えて、\n", "その結果得られる2つのリストをタプルにして返す関数 `swap_lists` を作成してください\n", "(ただし、0 は偶数として扱うものとします)。\n", "与えられたリストは破壊しても構いません。\n", "\n", "以下のセルの `...` のところを書き換えて `swap_lists(ln1, ln2)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def swap_lists(ln1, ln2):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(swap_lists([1, 2, 3, 4, 5], ['a', 'b', 'c', 'd', 'e']) == ([1, 'b', 3, 'd', 5], ['a', 2, 'c', 4, 'e']))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "文字列 `str1` を引数として取り、\n", "`str1` の中に含まれる大文字の数を返す関数 `count_capitalletters` を作成してください。\n", "\n", "以下のセルの `...` のところを書き換えて `count_capitalletters(str1)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def count_capitalletters(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(count_capitalletters('Que Será, Será') == 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "長さが 3 の倍数である文字列 `str_augc` が引数として与えられたとき、\n", "`str_augc` を長さ 3 の文字列に区切り、それらを順に格納したリストを返す関数 `identify_codons` を作成してください。\n", "\n", "以下のセルの `...` のところを書き換えて `identify_codons(str_augc)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def identify_codons(str_augc):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(identify_codons('CCCCCGGCACCT') == ['CCC', 'CCG', 'GCA', 'CCT'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "正の整数 `int1` が引数として与えられたとき、\n", "`int1` の値の下桁から3桁毎にコンマ (`,`) を入れた文字列を返す関数 `add_commas` を作成してください。\n", "ただし、数の先頭にコンマを入れる必要はありません。\n", "\n", "以下のセルの `...` のところを書き換えて `add_commas` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def add_commas(int1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、全ての実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(add_commas(14980) == '14,980')\n", "print(add_commas(3980) == '3,980')\n", "print(add_commas(298) == '298')\n", "print(add_commas(1000000) == '1,000,000')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "リスト `list1` が引数として与えられ、次のような文字列 `str1` を返す関数 `sum_strings` を作成してください。\n", "\n", "`list1` は `k` 個の要素を持つとします(ただし、`k` は正の整数)。\n", "`list1` の要素が文字列でなければ文字列に変換してください。\n", "その上で、`list1` の1番目から `k-2` 番目の各要素の後ろにコンマとスペースからなる文字列 `', '` を加え、\n", "`k-1` 番目の要素の後ろには、`' and '` を加え、1番目から `k` 番目までの要素を繋げた文字列を `str1` とします。\n", "\n", "以下のセルの `...` のところを書き換えて `sum_strings` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_strings(list1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(sum_strings(['a', 'b', 'c', 'd']) == 'a, b, c and d')\n", "print(sum_strings(['a']) == 'a')\n", "print(sum_strings([1, 2, 3]) == '1, 2 and 3')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "辞書 `dic1` と長さ 10 以下の文字列 `str1` が引数として与えられたとき、\n", "以下のように `dic1` を変更する関数 `handle_collision2` を作成してください。\n", "ただし、`dic1` のキーは、1 以上 10 以下の整数、キーに対応する値は文字列とします。\n", "\n", "1. `dic1` に `str1` の長さ `n` がキーとして登録されていない場合、`dic1` に キー `n`、`n` に対応する値 `str1` を登録します。\n", "2. `dic1` に `str1` の長さ `n` がキーとして登録されている場合、`i` の値を `n+1`, `n+2`, ...と1つずつ増やしていき、`dic1` にキーとして登録されていない値 `i` を探します。キーとして登録されていない値 `i` が見つかった場合、その `i` をキー、`i` に対応する値として `str1` を登録してください。 ただし、`i` を 10 まで増やしても登録されていない値が見つからない場合は、`i` を 1 に戻した上で `i` を増やす作業を続行してください。\n", "3. 2の手順によって、登録可能な `i` が見つからなかった場合、`dic1` を変更しません。 \n", "\n", "以下のセルの `...` のところを書き換えて `handle_collision2(dic1, str1)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def handle_collision2(dic1, str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "dic1_orig = {6: 'Styles', 4: 'Link', 7: 'Ackroyd'}\n", "handle_collision2(dic1_orig, 'Big Four')\n", "print(dic1_orig == {6: 'Styles', 4: 'Link', 7: 'Ackroyd', 8: 'Big Four'})\n", "dic1_orig = {6: 'Styles', 4: 'Link', 7: 'Ackroyd', 8: 'Big Four', 10: 'Blue Train', 9: 'End House'}\n", "handle_collision2(dic1_orig, 'Edgware')\n", "print(dic1_orig == {6: 'Styles', 4: 'Link', 7: 'Ackroyd', 8: 'Big Four', 10: 'Blue Train', 9: 'End House', 1: 'Edgware'})\n", "dic1_orig = {6: 'Styles', 4: 'Link', 7: 'Ackroyd', 8: 'Big Four', 10: 'Blue Train', 9: 'End House', 1: 'Edgware', 2: 'Orient', 3: 'Three Act', 5: 'Clouds'}\n", "handle_collision2(dic1_orig, 'ABC')\n", "print(dic1_orig == {6: 'Styles', 4: 'Link', 7: 'Ackroyd', 8: 'Big Four', 10: 'Blue Train', 9: 'End House', 1: 'Edgware', 2: 'Orient', 3: 'Three Act', 5: 'Clouds'})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "整数を最初の要素、文字列をその次の要素とするリスト(これを子リストと呼びます)を要素とするリスト\n", "`list1` が引数として与えられたとき、次のような辞書 `dic1` を返す関数 `handle_collision3` を作成してください。\n", "\n", "* 各子リスト `list2` に対して、`dic1` のキーは `list2` の最初の要素である整数とし、そのキーに対応する値は次の要素である文字列とします。\n", "* 2つ以上の子リストの最初の要素が同じ整数である場合、`list1` においてより小さいインデックスを持つ子リストの文字列を、その整数のキーに対応する値とします。\n", "\n", "以下のセルの `...` のところを書き換えて `handle_collision3(list1)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def handle_collision3(list1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(handle_collision3([[3, 'Richard III'], [1, 'Othello'], [2, 'Tempest'], [3, 'King John'], [4, 'Midsummer'], [1, 'Lear']]) == {1: 'Othello', 2: 'Tempest', 3: 'Richard III', 4: 'Midsummer'})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def reverse_lookup2(dic1):\n", " dic2 = {} #辞書を初期化する\n", " for key, value in dic1.items():\n", " dic2[value] = key\n", " return dic2\n", "#reverse_lookup2({'apple':3, 'pen':5, 'orange':7})" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_n(x,y):\n", " sum = 0\n", " for i in range(x, y + 1):\n", " sum = sum + i\n", " return sum\n", "#sum_n(1,3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def construct_list(int_size):\n", " ln = int_size * [0]\n", " for i in range(int_size):\n", " ln[i] = i\n", " return ln\n", "#construct_list(10)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_lists(list1):\n", " total = 0\n", " for list2 in list1: # for j in range(len(list1)):とlist2 = list1[j]としてもよい\n", " #print(list2)\n", " for i in range(len(list2)):\n", " #print(i, list2[i])\n", " total += list2[i]\n", " return total" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_matrix(list1, list2):\n", " list3 = [[0,0,0],[0,0,0],[0,0,0]] #結果を格納するリストを初期化する(これがない場合も試してみてください)\n", " for i in range(3):\n", " for j in range(3):\n", " list3[i][j] += list1[i][j] + list2[i][j]\n", " #print(i, j, list1[i][j],'+', list2[i][j], '=', list3[i][j])\n", " return list3\n", "#sum_matrix([[1,2,3],[4,5,6],[7,8,9]], [[1,4,7],[2,5,8],[3,6,9]])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def simple_match(str1, str2):\n", " for i in range(len(str1)-len(str2)+1):\n", " j = 0\n", " while j < len(str2) and str1[i+j] == str2[j]: #str1とstr2が一致している限りループ(ただし、jがstr2の長さ以上にならないようにする)#この条件がないと…?\n", " j += 1\n", " if j == len(str2): #str2の最後まで一致しているとこの条件が成立\n", " return i\n", " return -1\n", "#for文による別解\n", "#def simple_match(str1, str2):\n", "# for i in range(len(str1)-len(str2)+1):\n", "# #print('i=', i)\n", "# fMatch = True#マッチ判定\n", "# for j in range(len(str2)):\n", "# #print('j=', j, 'str1[i+j]=', str1[i+j], ' str2[j]=', str2[j])\n", "# if str1[i+j] != str2[j]:#str2が終了する前に一致しない箇所があるかどうか\n", "# fMatch = False\n", "# break\n", "# if fMatch:\n", "# return i\n", "# return -1\n", "#print(simple_match('location', 'cat') == 2)\n", "#print(simple_match('soccer', 'cat') == -1)\n", "#print(simple_match('category', 'cat') == 0)\n", "#print(simple_match('carpet', 'cat') == -1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解説\n", "\n", "下のセルは、繰り返し回数として `count` 変数を利用した解答例です。回数を理解しやすくするため `print()` 関数で `count` 変数も印字しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from time import sleep\n", "\n", "count = 0\n", "while True:\n", " print('Yeah!', count)\n", " count += 1\n", " if(count >= 10):\n", " break\n", " sleep(1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def collect_engwords(str_engsentences):\n", " list_punctuation = ['.', ',', ':', ';', '!', '?']\n", " for j in range(len(list_punctuation)): #list_punctuationの中の文字列(この場合、句読点)を空文字列に置換する\n", " str_engsentences = str_engsentences.replace(list_punctuation[j], '')\n", " #print(str_engsentences)\n", " list_str1 = str_engsentences.split(' ')\n", " list_str2 = []\n", " for j in range(len(list_str1)):\n", " if len(list_str1[j]) >= 3:\n", " list_str2.append(list_str1[j])\n", " return list_str2\n", "#collect_engwords('Unfortunately no, it requires something with a little more kick, plutonium.')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def swap_lists(ln1, ln2):\n", " for j in range(len(ln1)):\n", " if j % 2 == 1:\n", " ln1[j], ln2[j] = ln2[j], ln1[j]\n", " return ln1, ln2\n", "#swap_lists([1, 2, 3, 4, 5], ['a', 'b', 'c', 'd', 'e'])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def count_capitalletters(str1):\n", " int_count = 0\n", " for i in range(len(str1)):\n", " str2 = str1[i].upper()\n", " str3 = str1[i].lower()\n", " if str1[i] == str2 and str2 != str3:#前者の条件で大文字であることを、後者の条件で句読点などでないことを判定する\n", " int_count += 1\n", " return int_count\n", "#count_capitalletters('Que Será, Será')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def identify_codons(str_augc):\n", " str_codons = []\n", " int_codonnum = int(len(str_augc)/3)\n", " for i in range(int_codonnum):\n", " str_codons.append(str_augc[i*3: i*3+3])\n", " return str_codons\n", "#identify_codons('CCCCCGGCACCT')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def add_commas(int1):\n", " list1 = list(str(int1)) #文字列に変換し、更にそれを1文字ずつリストに格納する\n", " str1 = ''\n", " ccnt = 1 #3の倍数の位を調べるのに使う\n", " for i in range(len(list1)-1, -1, -1): #1の位の値から、大きい方の位の値に向かって処理を行う\n", " str1 = list1[i] + str1\n", " if ccnt % 3 == 0 and i != 0: #3の倍数の位の前であり、一番大きい位でないならば\n", " str1 = ',' + str1 #コンマをうつ\n", " ccnt += 1\n", " return str1\n", "#print(add_commas(14980) == '14,980')\n", "#print(add_commas(2980) == '2,980')\n", "#print(add_commas(298) == '298')\n", "#print(add_commas(1000000) == '1,000,000')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_strings(list_str):\n", " str1 = ''\n", " for i in range(len(list_str)):\n", " if i < len(list_str) - 2:#後ろから3番目までの要素\n", " str1 = str1 + str(list_str[i]) + ', '\n", " elif i == len(list_str) - 2:#後ろから2番目の要素\n", " str1 += str(list_str[i]) + ' and '\n", " else:#一番後ろの要素\n", " str1 += str(list_str[i])\n", " return str1\n", "#sum_strings(['a', 'b', 'c', 'd'])\n", "#sum_strings(['a'])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def handle_collision2(dic1, str1):\n", " n = len(str1)\n", " for i in range(n, 11):\n", " if dic1.get(i) is None:# == None でもよい\n", " dic1[i] = str1\n", " return\n", " for i in range(1, n):\n", " if dic1.get(i) is None:# == None でもよい\n", " dic1[i] = str1\n", " return " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def handle_collision3(list1):\n", " dic1 = {} # 空の辞書を作成する\n", " for i in range(len(list1)):\n", " list2 = list1[i]\n", " if dic1.get(list2[0]) is None:# == None でもよい\n", " dic1[list2[0]] = list2[1]\n", " return dic1\n", "#handle_collision3([[3, 'Richard III'], [1, 'Othello'], [2, 'Tempest'], [3, 'King John'], [4, 'Midsummer'], [1, 'Lear']])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "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.12.4" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: colab/3/3-3.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 3-3. 関数\n", "\n", "関数について改めて説明します。\n", "\n", "参考:\n", "\n", "- https://docs.python.org/ja/3/tutorial/controlflow.html#defining-functions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 関数の定義\n", "**関数**は処理(手続きの流れ)をまとめた再利用可能なコードです。関数には以下の特徴があります。\n", "\n", "* 名前を持つ。\n", "* 手続きの流れを含む。\n", "* 返値(明示的あるいは非明示的に)を返す。\n", "\n", "`len()` や `sum()` などの[組み込み関数](https://docs.python.jp/3/library/functions.html)は関数の例です。\n", "\n", "まず、関数の定義をしてみましょう。関数を定義するには **`def`** を用います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#'Hello'を表示する関数greeting\n", "def greeting():\n", " print('Hello')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数を定義したら、それを呼び出すことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#関数greetingを呼び出し\n", "greeting()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**関数定義**の一般形は以下の通りです。\n", "\n", "```Python\n", "def 関数名(引数):\n", " 関数本体\n", "```\n", "\n", "1行名はヘッダと呼ばれ、***関数名***はその関数を呼ぶのに使う名前、**引数**はその関数へ渡す変数の一覧です。\n", "変数がない場合もあります。\n", "\n", "***関数本体***はインデントした上で、処理や手続きの流れを記述します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 引数\n", "関数を定義する際に、ヘッダの括弧の中に関数へ渡す変数の一覧を記述します。\n", "これらの変数は関数の**ローカル変数**となります。\n", "ローカル変数とはプログラムの一部(ここでは関数内)でのみ利用可能な変数です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#引数greeting_localに渡された値を表示する関数greeting\n", "def greeting(greeting_local):\n", " print(greeting_local)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数を呼び出す際に引数に値を渡すことで、関数は受け取った値を処理することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#関数greetingに文字列'Hello'を渡して呼び出し\n", "greeting('Hello')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このようにして引数に渡される値のことを、**実引数**(**argument**)と呼ぶことがあります。\n", "実引数に対して、ここまで説明してきた引数(ローカル変数である引数)は、**仮引数**(**parameter**)と呼ばれます。\n", "参考:[公式FAQ:実引数と仮引数の違いは何ですか?](https://docs.python.org/ja/3/faq/programming.html#what-is-the-difference-between-arguments-and-parameters)\n", "\n", "実引数のことを引数と呼ぶこともありますので、注意してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 返値\n", "関数は受け取った引数を元に処理を行い、その結果の**返値**(1-2で説明済み)を返すことができます。\n", "\n", "返値は、**`return`** で定義します。関数の返値がない場合は、**`None`** が返されます。\n", "`return` が実行されると、関数の処理はそこで終了するため、次に文があっても実行はされません。\n", "また、ループなどの繰り返し処理の途中でも `return` が実行されると処理は終了します。\n", "関数の処理が最後まで実行され、返値がない場合は最後に `return` を実行したことと同じになります。\n", "\n", "`return` の後に式がない場合は、`None` が返されます。\n", "(`return` が実行されずに関数の最後まで来たときも同様です。)\n", "`return` を式なしで実行することで、関数の処理を途中で抜けることができます。\n", "また、このような関数は、与えられた配列を破壊的に変更するなど、\n", "呼び出した側に何らかの変化を及ぼす際にも用いられます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#引数greeting_localに渡された値を返す関数greeting\n", "def greeting(greeting_local):\n", " return greeting_local\n", "\n", "#関数greetingに文字列'Hello'を渡して呼び出し\n", "greeting('Hello')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#入力の平均を計算して返す関数average\n", "def average(nums):\n", " #組み込み関数のsum()とlen()を利用\n", " return sum(nums)/len(nums)\n", "\n", "#関数averageに数字のリストを渡して呼び出し\n", "average([1,3,5,7,9])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数の返値を変数に代入することもできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#関数greetingの返値を変数greetに代入\n", "greet = greeting('Hello')\n", "greet" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 複数の引数\n", "関数は任意の数の引数を受け取ることができます。\n", "複数の引数を受け取る場合は、引数をコンマで区切ります。\n", "これらの引数名は重複しないようにしましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#3つの引数それぞれに渡された値を表示する関数greeting\n", "def greeting(en, fr, de):\n", " print(en + ', ' + fr + ', ' + de)\n", " \n", "#関数greetingに3つの引数を渡して呼び出し\n", "greeting('Hello', 'Bonjour', 'Guten Tag')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数は異なる型であっても引数として受け取ることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#文字列と数値を引数として受け取る関数greeting\n", "def greeting(en, number, name):\n", " #文字列に数を掛け算すると、文字列を数の回だけ繰り返すことを指定します\n", " print(en*number+','+name)\n", " \n", "#関数greetingに文字列と数値を引数として渡して呼び出し\n", "greeting('Hello',3, 'World')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 変数とスコープ\n", "関数の引数や関数内で定義される変数はローカル変数のため、それらの変数は関数の外からは参照できません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "#引数greeting_localに渡された値を表示する関数greeting\n", "def greeting(greeting_local):\n", " print(greeting_local)\n", " \n", "greeting('Hello') \n", "\n", "#ローカル変数(関数greetingの引数)greeting_localを参照\n", "greeting_local" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一方、変数が**グローバル変数**であれば、それらの変数は関数の外からも中からも参照できます。\n", "グローバル変数とはプログラム全体、どこからでも利用可能な変数です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#グローバル変数greeting_globalの定義\n", "greeting_global = 'Hello'\n", "\n", "#グローバル変数greeting_globalの値を表示する関数greeting\n", "def greeting():\n", " print(greeting_global)\n", " \n", "greeting()\n", "\n", "#グローバル変数greeting_globalを参照\n", "greeting_global" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "グローバル変数と同じ名前の変数を関数内で定義すると、\n", "それは通常はグローバル変数とは異なる、関数内のみで利用可能な**ローカル変数**の定義として扱われます。\n", "グローバル変数と同じ名前の引数を用いる場合も同様です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#グローバル変数greeting_globalと同じ名前の変数に値を代入する関数greeting\n", "def greeting():\n", " greeting_global = 'Bonjour'\n", " print(greeting_global)\n", "\n", "greeting()\n", "\n", "#変数greeting_globalを参照\n", "greeting_global" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "しかし、グローバル変数と同名のローカル変数を定義することは、一般に注意が必要です。\n", "何故なら、ローカル変数としての定義を含む関数内では、同名のグローバル変数を参照できないからです。\n", "たとえば、次のコードは、`Hello` と `Bonjour` が順に印字することを期待するかもしれませんが、" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "def greeting():\n", " print(greeting_global) # 最初の参照\n", " greeting_global = 'Bonjour' # ローカル変数の定義\n", " print(greeting_global)\n", "\n", "greeting()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "最初の `greeting_global` の参照でエラーになります。\n", "これは、関数内に `greeting_global` の定義があると、\n", "その関数内どの場所でも `greeting_global` がローカル変数として参照されるためです。\n", "最初の参照時には、ローカル変数の `greeting_global` が未定義なので、エラーが生じます。\n", "\n", "このように、グローバル変数と同じ名前のローカル変数を使おうとするのは間違いの元です。\n", "グローバル変数と名前が衝突しないように、ローカル変数を定義しましょう。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲ global 宣言\n", "\n", "関数内ではグローバル変数が更新されないのが基本です。\n", "しかし、どうしても関数内でグローバル変数を更新したいときには、\n", "**`global`** 宣言を使って更新したいグローバル変数を指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#グローバル変数greeting_globalに値を代入する関数greeting\n", "def greeting():\n", " global greeting_global\n", " greeting_global = 'Bonjour'\n", " print(greeting_global)\n", "\n", "greeting()\n", "\n", "##変数greeting_globalを参照\n", "greeting_global" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`global` 宣言された変数名は、関数内で常にグローバル変数として参照されます。\n", "これを濫用すると間違いの元になるので、原則として利用しないようにしましょう。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲キーワード引数\n", "上記の一般的な引数(位置引数とも呼ばれます)では、\n", "事前に定義した引数の順番に従って、関数は引数を受け取る必要があります。\n", "\n", "キーワード付き引数(**キーワード引数**)を使うと、関数は引数の変数名とその値の組みを受け取ることができます。\n", "その際、引数は順不同で関数に渡すことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#文字列と数値を引数として受け取る関数greeting\n", "def greeting(en, number, name):\n", " print(en*number+','+name)\n", "\n", "#関数greetingに引数の変数名とその値の組みを渡して呼び出し\n", "greeting(en='Hello', name='Japan', number=2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "位置引数とキーワード引数を合わせて使う場合は、最初に位置引数を指定する必要があります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#位置引数とキーワード引数を組み合わせた関数greetingの呼び出し\n", "greeting('Hello', name='Japan', number=2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲引数の初期値\n", "関数を呼び出す際に、引数が渡されない場合に、**初期値**を引数として渡すことができます。\n", "\n", "初期値のある引数に値を渡したら、関数はその引数の初期値の代わりに渡された値を受け取ります。\n", "\n", "初期値を持つ引数は、位置引数の後に指定する必要があります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#引数の初期値(引数の変数enに対する'Hello')を持つ関数greeting\n", "def greeting(name, en='Hello'):\n", " print(en+', '+name)\n", " \n", "#引数の初期値を持つ関数greetingの呼び出し\n", "greeting('World')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲可変長引数\n", "仮引数の前に **`*`** を付けて関数を定義すると、複数の引数をタプルとして受け取ることができます。\n", "呼び出す側は、引数の個数を変えることができます。\n", "一般に、個数が可変の引数は**可変長引数**と呼ばれます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#可変長の引数を受け取り、それらを表示する関数greeting\n", "def greeting(*args):\n", " print(args)\n", " \n", "#可変長の引数を受け取る関数greetingに複数の引数を渡して呼び出し\n", "greeting('Hello','Bonjour','Guten Tag')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "リストやタプルの要素を可変長引数として関数に渡す場合は、**`*`** をリストやタプルの前につけて渡します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#リスト型オブジェクトgreeting_listを関数greetingに渡して呼び出し\n", "greeting_list = ['Hello','Bonjour','Guten Tag']\n", "greeting(*greeting_list)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲辞書型の可変長引数\n", "仮引数の前に `**` を付けて関数を定義すると、複数のキーワード引数を辞書として受け取ることができます。辞書として受け取られる引数は、**辞書型の可変長引数**と呼ばれます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#可変長のキーワード引数を受け取り、それらを表示する関数greeting\n", "def greeting(**kwargs):\n", " print(kwargs)\n", " \n", "#可変長のキーワード引数を受け取る関数greetingに複数の引数を渡して呼び出し\n", "greeting(en='Hello', fr='Bonjour', de='Guten Tag')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "辞書の各キーと値を複数のキーワード引数として関数に渡す場合は、\n", "`**` をその辞書の前につけて渡します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#辞書型オブジェクトgreeting_dictを関数greetingに渡して呼び出し\n", "greeting_dict = {'en': 'Hello', 'fr': 'Bonjour', 'de': 'Guten Tag'}\n", "greeting(**greeting_dict)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲引数の順番\n", "位置引数、初期値を持つ引数、可変長引数、辞書型の可変長引数は、同時に指定することができますが、\n", "その際、これらの順番で指定する必要があります。\n", "\n", "```Python\n", "def 関数名(位置引数, 初期値を持つ引数, 可変長引数, 辞書型の可変長引数)\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#位置引数、初期値を持つ引数、可変長引数、辞書型の可変長引数\n", "#それぞれを引数として受け取り、それらを表示する関数greeting\n", "def greeting(greet, en='Hello', *args, **kwargs):\n", " print(greet)\n", " print(en)\n", " print(args)\n", " print(kwargs)\n", "\n", "#可変長引数へ渡すリスト\n", "greeting_list = ['Bonjour']\n", "\n", "#辞書型の可変長引数へ渡す辞書\n", "greeting_dict = {'de': 'Guten Tag'}\n", "\n", "#関数greetingに引数を渡して呼び出し\n", "greeting('Hi', 'Hello', *greeting_list, **greeting_dict)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲変数としての関数\n", "関数は変数でもあります。既存の変数と同じ名前の関数を定義すると、\n", "元の変数はその新たな関数を参照するものとして変更されます。\n", "一方、既存の関数と同じ名前の変数を定義すると、元の関数名の変数はその新たな変数を参照するものとして変更されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#グローバル変数greeting_globalの定義と参照\n", "greeting_global = 'Hello'\n", "type(greeting_global)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#グローバル変数greeting_globalと同名の関数の定義\n", "#変数greeting_globalは関数を参照する\n", "def greeting_global():\n", " print('This is the greeting_global function')\n", " \n", "type(greeting_global)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/4/4-1.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/utf-8.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/shift_jis.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/test.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/sample.txt\n", "!wget -P text https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/text/novel.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 4-1. ファイル入出力の基本\n", "ファイル入出力の基本について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/inputoutput.html#reading-and-writing-files\n", "\n", "## ファイルのオープン\n", "**ファイル**から文字列を読み込んだり、ファイルに書き込んだりするには、\n", "まず、**`open()`** という関数によってファイルを**オープン**する(開く)必要があります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = open('sample.txt', 'r')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "変数 `f` には、ファイルを読み書きするためのデータが入ります。\n", "これを**ファイルオブジェクト**と呼びます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`'sample.txt'` はファイル名で、そのファイルの絶対パス名か、このノートブックからの相対パス名を指定します。\n", "\n", "ここでは、`sample.txt` という名前のファイルがこのノートブックと同じディレクトリにあることを想定しています。\n", "\n", "たとえば、`novel.txt` というファイルが、ノートブックの1段上のディレクトリ(このディレクトリが入っているディレクトリ)にあるならば、`'../novel.txt'` と指定します。\n", "ノートブックの1段上のディレクトリに置かれている `data` というディレクトリにあるならば、`'../data/novel.txt'` となります\n", "(4-3にもう少し詳しい解説があります)。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`'r'` はファイルをどのモードで開くかを指しており、`'r'`は**読み込みモード**を意味します。\n", "このモードで開いたファイルに書き込みすることはできません。\n", "\n", "よく使われるモードは、次の3種類です。\n", "\n", "引数 | モード\n", "---|:---\n", "`'r'` | 読み込み\n", "`'w'` | 書き込み\n", "`'a'` | 追記\n", "\n", "モードの引数がなかった場合は、`'r'` であると解釈されます。\n", "書き込みについては後でも説明します。\n", "\n", "モードの詳細は[公式ドキュメント](https://docs.python.org/ja/3/library/functions.html#open)を参照。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ファイルのクローズ\n", "\n", "ファイルオブジェクトを使い終わったら、原則として、**`close()`** メソッドを呼び出して、**クローズ**する(閉じる)必要があります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`close()` を呼び出さずに放置すると、そのファイルがまだ使用中だと認識されてしまいます。\n", "これは、同じファイルを利用しようとする他のプログラムの働きを阻害します。(個室のトイレをイメージしてください。)\n", "\n", "`close()` の呼び出しは重要ですが、忘れがちなものでもあります。\n", "後述するwith文を使うのが安全です。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 行の読み込み\n", "ファイルオブジェクトには、**`readline()`** というメソッドを適用することができます。\n", "ファイルから新たに1行を読んで文字列として返します。\n", "この「1行」というのは、正確には、ファイルの先頭もしくは改行文字の次の文字から、ファイルの終わりもしくは改行文字までの文字列です。\n", "1行は必ずしも改行文字で終わらないという点に注意して下さい。\n", "\n", "ファイルの終わりに来たとき、`readline()` は `''` という空文字列を返します。\n", "\n", "以下のようにして `readline()` を使ってファイルを行単位で読んでみましょう。\n", "\n", "ファイルを読み終わると空文字列が返ることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = open('sample.txt', 'r')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`readline()` メソッドの呼び出しは、ファイルオブジェクトを消費します。\n", "改めて読み出したいときには、再度オープンして新しいオブジェクトを使ってください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "文字列 `name` をファイル名とするファイルの最後の行を文字列として返す関数 `last_line(name)` を定義してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def last_line(name):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(last_line('sample.txt')==\"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\\n\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ファイル全体の読み込み\n", "\n", "ファイル全体を一括で読み込んで、1つの文字列を取得したいときには、**`read()`** メソッドを利用します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = open('sample.txt', 'r')\n", "f.read()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一度 `read()` を呼ぶと、ファイルの終端に達するので、それ以降は空文字列を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.read()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`read()` メソッドは、内部的には `readline()` メソッドを呼んでいます。\n", "したがって、`read()` メソッドも同様にファイルオブジェクトを消費します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `name` をファイル名とするファイルをオープンして、\n", "`read()` メソッドによってファイル全体を文字列として読み込み、\n", "その文字数を返す関数 `number_of_characters(name)` を作成してください。\n", "\n", "注意:`return` する前にファイルをクローズすることを忘れないようにしてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def number_of_characters(name):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(number_of_characters('sample.txt') == 446)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 編集中のファイルの動作\n", "\n", "プログラムでファイルを開くと、そのプログラム内でそのファイルを閉じるまでは、他のプログラムでそのファイルを編集することはできません。 \n", "\n", "下のセルを実行した後で、Windowsならエクスプローラ、macOSならFinderで上のファイルを探して、削除してみてください。\n", "「ファイルを閉じてから再実行してください。(Windowsの場合)」といったメッセージが出て、削除ができないはずです。 " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = open('test.txt', 'r')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "下のセルを実行した後だと削除できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ファイルに対するwith文" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ファイルのオブジェクトは、with文に指定することができます。\n", "\n", "---\n", "```Python\n", "with ファイルオブジェクト as 変数:\n", " ...\n", "\n", "```\n", "---\n", "\n", "**`with`** の次には、`open` によってファイルをオープンする式を書きます。\n", "\n", "また、**`as`** の次には、ファイルのオブジェクトが格納される変数を書きます。\n", "\n", "with文は処理後にファイルのクローズを自動的にやってくれますので、\n", "ファイルに対して `close()` を呼び出す必要がありません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('sample.txt', 'r') as f:\n", " print(f.read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ファイルへの書き込み\n", "\n", "ファイルへの書き込みは、`print` 関数を使って行えます。\n", "`file` 引数に書き込み先のファイルオブジェクトを指定します。\n", "`file` は3.3で説明されているキーワード引数と呼ばれる引数ですので、\n", "以下のように `file=...` という形で指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('print-test.txt', 'w') as f:\n", " print('hello\\nworld', file=f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列の中の `\\n` は改行文字を表します。`\\n` は**エスケープシーケンス**(2-1に説明があります)の一種です。\n", "エスケープシーケンスには、この他に、復帰文字を表す `\\r` やタブを表す `\\t` などがあります。\n", "\n", "ファイルの読み書きのモードとしては、**書き込みモード**を意味する `'w'` を指定しています。既に同じ名前のファイルが存在する場合は上書きされます(以前の内容はなくなります)。ファイルがない場合は、新たに作成されます。\n", "\n", "`'a'` を指定すると、ファイルが存在する場合、既存の内容の後に追記されます。ファイルがない場合は、新たに作成されます。\n", "\n", "`print` 関数は、デフォルトで、与えられた文字列の末尾に改行文字を加えて印字します。\n", "末尾に加える文字は、`end` 引数で指定できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('print-test.txt', 'a') as f:\n", " print('hello', 'world\\n', end='', file=f) # 改行文字を加えない" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "また、複数の印字対象を渡すと、デフォルトで、空白文字で区切って印字します。\n", "この区切り文字は、`sep` 引数で指定できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('print-test.txt', 'a') as f:\n", " print('hello', 'world', sep=', ', file=f) # 'hello, world'が印字される" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この他にも、ファイルオブジェクトには、より原始的な書き込み用メソッドが用意されています。\n", "**`write()`** メソッドは、与えられた1つの文字列を単に書き込みます。\n", "次に示すように、`write()` メソッドと `read()` メソッドは、対で使うことが良くあります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('sample.txt') as src, open('sample.txt.bak', 'w') as dst:\n", " dst.write(src.read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このコードは、`sample.txt` を `sample.txt.bak` にコピーします。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "2つのファイル名 `infile`, `outfile` を引数として、`infile` の半角英文字を全て大文字にした結果を `outfile` に書き込む `file_upper(infile, outfile)` という関数を作成してください。 \n", "\n", "なお、半角英文字の小文字を大文字に変換するには `upper()` というメソッドが使えます。\n", "たとえば `line` という名前の変数に半角文字列が入っている場合、`line.upper()` とすれば大文字に変換した文字列を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def file_upper(infile,outfile):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "with open('print-test.txt', 'w') as f:\n", " print('hello', 'world', file=f)\n", "file_upper('print-test.txt', 'print-test-upper.txt')\n", "with open('print-test-upper.txt', 'r') as f:\n", " print(f.read() == 'HELLO WORLD\\n')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ファイルの読み書きにおける文字コード指定\n", "\n", "`open` でファイルを開くと、通常そのファイルをテキストモードで開きます(テキストモード以外にバイナリモードもあります)。\n", "\n", "テキストモードでファイルを開くときは、さらに特定の**文字コード**によってそのファイルを開こうとします。\n", "文字コードを指定しないと、デフォルトの文字コードでそのファイルを開こうとしますが、\n", "この文字コードがファイルを書き込む際に指定したものと異なる場合、エラーが出たり文字化けしてしまいます。\n", "\n", "デフォルトの文字コードは、WindowsはShift_JIS、macOSやLinuxはUTF-8になっていることが多いです。\n", "UTF-8で文字を記録されたファイルをWindowsで、ただ `open('utf-8.txt', 'w')` のように文字コードを指定せずに開くとエラーが出ます。\n", "同じく、Shift_JISで文字を記録されたファイルをmacOSで `open('shift_jis.txt', 'w')` として開くとエラーが出ます。\n", "\n", "なお、この教材の冒頭で `open('sample.txt', 'r')` と、文字コードを指定せずにファイルを開きましたがエラーは出ませんでしたね。\n", "これは、`sample.txt` では半角英数字しか使われておらず、半角英数字に関しては、Shift_JISもUTF-8も共通のルールでエンコードされているためです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "# macOSならこちらでエラー\n", "with open('shift_jis.txt', 'r') as f:\n", " print(f.read())\n", "\n", "# Windowsならこちらでエラー\n", "with open('utf-8.txt', 'r') as f:\n", " print(f.read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "特に半角英数以外の文字を記録する際は文字コードを指定すること、またそのようなファイルを開くときは、記録するときに指定した文字コードでファイルを開いてください。\n", "\n", "文字コードは、`open` のキーワード引数として\n", "`encoding='utf-8'`(文字コードにUTF-8を指定する場合)のように指定することができます。 \n", "\n", "なお、日本語の文字コードには `UTF-8`, `Shift_JIS`, `EUC-JP` などがありますが、PythonではOSの種類に限らず、UTF-8という文字コードがよく使われます。本授業でもUTF-8を推奨します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "# 文字コードを指定しないとmacOSならこちらでエラー\n", "with open('shift_jis.txt', 'r', encoding='shift_jis') as f:\n", " print(f.read())\n", "\n", "# 文字コードを指定しないとWindowsならこちらでエラー\n", "with open('utf-8.txt', 'r', encoding='utf-8') as f:\n", " print(f.read())\n", "\n", "# 文字コードを指定してファイルに書き込む場合\n", "with open('text.txt', 'w', encoding='utf-8') as f:\n", " f.write('かきくけこ')\n", "with open('text.txt', 'r', encoding='utf-8') as f:\n", " print(f.read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 改行文字の削除\n", "\n", "ファイルをテキストモードで開いて `read()` や `readline()` を呼び出すと、\n", "`str` 型の文字列として読み込まれます。\n", "\n", "文字列の末尾にある改行文字の削除には、2-1で紹介した `rstrip` メソッドが使えます。\n", "ただし、無引数で呼び出すと、改行文字以外の空白文字もまとめて削除されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'あいうえお \\n'.rstrip()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "削除する空白文字を改行文字 `'\\n'` に限定したい場合には、 `rstrip` の引数に指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'あいうえお \\n\\n'.rstrip('\\n')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の例から分かるように、末尾の改行文字をただ1つ削除したい場合には、 `rstrip('\\n')` は適していません。\n", "しかし、 `readline()` の返す文字列には、末尾に高々1つの `'\\n'` しか存在しないので、 `rstrip('\\n')` で問題ありません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('text/novel.txt', 'r', encoding='utf-8') as f:\n", " while True:\n", " line = f.readline()\n", " if line == '':\n", " break\n", " print(line)\n", "\n", "print('------ 末尾の改行文字を削除すると以下のようになります-------')\n", "with open('text/novel.txt', 'r', encoding='utf-8') as f:\n", " while True:\n", " line = f.readline()\n", " if line == '':\n", " break\n", " print(line.rstrip('\\n'))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def number_of_characters(name):\n", " f = open(name, 'r')\n", " s = f.read()\n", " f.close()\n", " return len(s)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def last_line(name):\n", " last = ''\n", " with open(name, 'r') as f:\n", " while True:\n", " line = f.readline()\n", " if line == '':\n", " return last\n", " last = line" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def file_upper(infile,outfile):\n", " with open(infile, 'r') as f:\n", " with open(outfile, 'w') as g:\n", " g.write(f.read().upper())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のように1つのwith文に複数の `open` を書くこともできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def file_upper(infile,outfile):\n", " with open(infile, 'r') as f, open(outfile, 'w') as g:\n", " g.write(f.read().upper())" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/4/4-2.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/utf-8.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/shift_jis.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/test.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/sample.txt\n", "!wget -P text https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/text/novel.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 4-2. イテラブルとイテレータ\n", "\n", "イテラブルとイテレータについて説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/classes.html#iterators\n", "- https://docs.python.org/ja/3/glossary.html#term-iterable\n", "- https://docs.python.org/ja/3/library/stdtypes.html#typeiter" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## for文による繰り返しとファイルオブジェクト\n", "\n", "ファイルオブジェクトは、for文の `in` の後に指定することができます。\n", "このとき、ファイルから各行の文字列(改行文字を含む)を順次取り出します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lines = []\n", "with open('sample.txt', 'r') as f:\n", " for line in f:\n", " lines.append(line)\n", "lines" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "for文による行の取り出しは、`readline` メソッドと同様に、ファイルオブジェクトを消費します。\n", "\n", "ファイルオブジェクト `f` をfor文で処理をすると、`f` が終端に到達するまで繰り返されます。\n", "したがって、再度 `f` をfor文に与えても何も実行されません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('sample.txt', 'r') as f:\n", " print('---- 最初 ----')\n", " for line in f:\n", " print(line)\n", " print('---- もう一度 ----')\n", " for line in f:\n", " print(line)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ファイルをfor文によって二度読みたい場合は、\n", "もう一度ファイルをオープンして、ファイルのオブジェクトを新たに生成してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習\n", "文字列 `name` をファイル名とするファイルの最後の行を文字列として返す関数 `last_line(name)` を、\n", "ファイルオブジェクトに対するfor文を用いて定義してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def last_line(name):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "定義ができたら、次のセルを実行して、エラーがでないことを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "assert last_line('sample.txt') == 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\\n'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## for文とイテラブルとイテレータ\n", "\n", "さて、[3-2](../3/3-2.ipynb)でも示したように、for文は、ファイルオブジェクトを含む様々なオブジェクトに対して繰り返す処理を記述できます\n", "([1-3](../1/1-3.ipynb)で説明があったように、Pythonにおける値はオブジェクトと総称されます。) \n", "\n", "for文によって繰り返すことができるオブジェクトのことを総称して、**イテラブル** (iterable) と呼びます。\n", "\n", "for文が、様々なデータ型をイテラブルとして統一的に扱えるのは、繰り返して取り出す操作を表現する**イテレータ** (iterator) を経由するからです。\n", "\n", "iterateは繰り返すという意味なので、itaratorは繰り返すもの(反復子とも呼ばれる)、iterableは繰り返すことができるもの、という意味です。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `iter`\n", "\n", "組み込み関数 **`iter`** は、イテラブルからイテレータを作ります。たとえば、" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "it = iter([0,1,2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この `it` は、`0` `1` `2` を順に取り出すイテレータです。\n", "\n", "このとき、`iter` に渡されるオブジェクトの種類に応じて、適切なイテレータが構成されます。\n", "この仕組みによって、様々なデータ型を統一的に扱えるわけです。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `next`\n", "\n", "さて、`iter` が返したイテレータは、どのように使うのでしょうか。\n", "\n", "組み込み関数 **`next`** は、イテレータに対して繰り返しを1回分先に進める操作を与えます。具体例を見ましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "it = iter([0,1,2])\n", "next(it)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "next(it)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "next(it)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`next(it)` を呼び出す毎に、`it` から順に要素が取り出されています。\n", "\n", "与えられたイテレータが繰り返しの終端に到達していたときには、`StopIteration` という例外(処理を緊急停止させる割り込み)が発生します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "next(it)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## for文の仕組み\n", "\n", "for文は、実は `iter` `next` `StopIteration` を使ったwhile文の形で表現できます。具体的には、" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for x in [0,1,2]:\n", " print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このfor文は、次のwhile文と等価です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "try:\n", " it = iter([0,1,2])\n", " while True:\n", " x = next(it)\n", " print(x)\n", "except StopIteration:\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このtry-except文は、発生した例外を捉えて、適切に処理するための構文です。\n", "ここでは、発生した `StopIteration` を捉えて、何もせずに(`pass`)次に処理を進めるという意味になります。\n", "結果として、コードセルの実行が成功裡に完了しています。\n", "(例外とtry-except文の詳細は、[公式チュートリアル](https://docs.python.org/ja/3/tutorial/errors.html)を参照してください。)\n", "\n" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## イテレータは特殊なイテラブル\n", "\n", "イテレータ自身も実はイテラブルです。したがって、イテレータをfor文で繰り返すことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "it = iter([0,1,2])\n", "for x in it:\n", " print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "しかし、単なるイテラブルではありません。1つのfor文で使い切りのイテラブルです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for x in it:\n", " print('これは実行されない')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "これは、イテレータ `it` に対して `iter` を適用した時に、`it` 自体が返されるという仕組みによって実現されています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "it = iter([0,1,2])\n", "it is iter(it)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この **`is`** は、[2-2](../2/2-2.ipynb)に説明がありますが、その両辺が同一オブジェクトかどうかを調べる演算子です。\n", "\n", "最初のfor文の繰り返しによって終端に到達したイテレータ `it` は、その後の `next(it)` において `StopIteration` を発生させ続けます。\n", "したがって、後続するfor文では、繰り返し処理に入ることなく即座に終了するわけです。\n", "上に示したwhile文の形で考えると、わかりやすいでしょう。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習\n", "\n", "リストをもらって、そのイテレータを作り、最初の要素だけ取り出した後、\n", "そのイテレータを返す関数 `but_first(ls)` を定義してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def but_first(ls):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "定義ができたら、次のセルを実行して、エラーがでないことを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "it = but_first([0,2,4,6,8])\n", "assert type(it) == type(iter([])) # type(it) では it は消費されない\n", "assert list(it) == [2,4,6,8]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ファイルオブジェクトはイテレータ\n", "\n", "ファイルオブジェクトは `readline` メソッドによって、一行ずつ消費しながら、行の文字列を取り出せます。\n", "そして、for文で末尾まで繰り返すと、for文で繰り返すことはもうできません。\n", "\n", "ここまで読んだ方は既に気付いているでしょうが、ファイルオブジェクトはイテレータです。\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = open('sample.txt', 'r')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "next(f)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "next(f)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "next(f)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "next(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ファイルオブジェクト `f` に対する `f.readline()` と `next(f)` の振舞いは、`f` が終端に到達していないときは同一です。\n", "`f` が終端にあるときは、`f.readline()` は `''` を返しますが、`next(f)` は `StopIteration` を発生させます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## イテラブルはイテレータではない\n", "\n", "イテラブルは一般に、イテレータではありません。\n", "具体的には、リスト・タプル・文字列・辞書はイテラブルですが、イテレータではありません。\n", "[3-2](../3/3-2.ipynb)で紹介した `range` 関数の返す range オブジェクトも、イテラブルですがイテレータではありません。\n", "\n", "したがって、`next` が適用可能ではなく、`iter` の適用によって毎回別のイテレータが返されます。\n", "つまり、これまで見てきたように、複数のfor文で何度も繰り返す処理が実行できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "xs = [1,2,3]\n", "for x in xs:\n", " print(x)\n", "for x in xs:\n", " print(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "r = range(3)\n", "for x in r:\n", " print(x)\n", "for x in r:\n", " print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## イテレータを返す `enumerate`\n", "\n", "[3-2](../3/3-2.ipynb)で紹介した組み込み関数の **`enumerate`** は、イテレータを返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "it = enumerate([10,20,30])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "next(it)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for x in it:\n", " print(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i, c in enumerate('ACDB'):\n", " print(i, '番目の文字 =', c)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一方、`enumerate` はイテラブルを引数として受け取ります。上の例で、リストも文字列もイテラブルです。\n", "\n", "イテレータもイテラブルなので、`enumerate` の引数になり得ます。\n", "したがって、ファイルオブジェクトも、次のように `enumerate` に与えることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('sample.txt', 'r') as f:\n", " for i, s in enumerate(f):\n", " print(i, '行目:')\n", " print(s)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "変数 `i` は `0` から順に増えていきます。変数 `s` には各行の文字列が代入されます。\n", "`i` は `0` から始まりますが、各行の行番号と考えられます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲イテラブルとイテレータの定義\n", "\n", "イテラブルとイテレータの形式的な定義をまとめます。\n", "\n", "* イテラブル:\n", " - `iter` を適用可能。 **`__iter__`** メソッドを持つ。\n", "* イテレータ:\n", " - `next` を適用可能。 **`__next__`** メソッドを持つ。\n", " - `iter` を適用したとき、引数のオブジェクトをそのまま返す。\n", " \n", "`iter(x)` は `x.__iter__()` と等価なので、`iter` を適用可能であることと、`__iter__` メソッドを持つことは同義です。\n", "同様に、`next(x)` は `x.__next__()` と等価なので、 `next` を適用可能であることと、`__next__` メソッドを持つことは同義です。\n", "\n", "`__iter__` メソッドと `__next__` メソッドについては、[6-3](../6/6-3.ipynb)で改めて説明します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def last_line(name):\n", " with open(name, 'r', encoding='utf-8') as f:\n", " for line in f:\n", " pass\n", " return line" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def last_line(name):\n", " f = open(name, 'r', encoding='utf-8')\n", " for line in f:\n", " pass\n", " f.close()\n", " return line" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def but_first(ls):\n", " it = iter(ls)\n", " next(it)\n", " return it" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/4/4-3.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/utf-8.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/shift_jis.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/test.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/sample.txt\n", "!wget -P text https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/4/text/novel.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 4-3. ディレクトリと木構造\n", "\n", "ディレクトリと木構造について説明します。\n", "この内容はPythonというよりも、Windows・macOS・Linuxなどの一般的なOSに共通する概念です。\n", "なお、Colaboratoryは、仮想マシン上のLinuxの上で動作しています。\n", "\n", "## ディレクトリと階層構造\n", "\n", "OS上でのファイルは一般に、階層的に管理されています。\n", "ファイルが置かれる場所のことを、**ディレクトリ**と呼びます。\n", "ファイルをまとめることから、**フォルダ**とも呼ばれます。\n", "\n", "[zip版の教材](https://utokyo-ipp.github.io/IPP_textbook.zip)を、`IPP_textbook` ディレクトリに展開すると、次のような階層構造になります。\n", "\n", "```\n", "IPP_textbook\n", "├── 1\n", "│ ├── 1-0.ipynb\n", "│ ├── 1-1.ipynb\n", "│ ├── 1-2.ipynb\n", "│ ├── 1-3.ipynb\n", "│ ├── 1-4.ipynb\n", "│ ├── colab1.png\n", "│ ├── colab2.png\n", "│ ├── colab3.png\n", "│ ├── colab4.png\n", "│ └── colaboratory.png\n", "├── 2\n", "│ ├── 2-1.ipynb\n", "│ ├── 2-2.ipynb\n", "│ └── 2-3.ipynb\n", "├── 3\n", "│ ├── 3-1.ipynb\n", "│ ├── 3-2.ipynb\n", "│ └── 3-3.ipynb\n", "├── 4\n", "│ ├── 4-1.ipynb\n", "│ ├── 4-2.ipynb\n", "│ ├── 4-3.ipynb\n", "│ ├── sample.txt\n", "│ ├── shift_jis.txt\n", "│ ├── test.txt\n", "│ ├── text\n", "│ │ └── novel.txt\n", "│ └── utf-8.txt\n", "├── 5\n", "│ ├── 5-1.ipynb\n", "│ ├── 5-2.ipynb\n", "│ ├── 5-3.ipynb\n", "│ ├── factorial.py\n", "│ └── fig\n", "│ ├── py_conv_1.png\n", "│ ├── py_conv_2.png\n", "│ ├── py_open_1.png\n", "│ └── py_open_2.png\n", "├── 6\n", "│ ├── 6-1.ipynb\n", "│ ├── 6-2.ipynb\n", "│ ├── 6-3.ipynb\n", "│ └── jugemu.txt\n", "├── 7\n", "│ ├── 7-1.ipynb\n", "│ ├── 7-2.ipynb\n", "│ └── iris.csv\n", "├── appendix\n", "│ ├── 1-jupyter-notebook.ipynb\n", "│ ├── 2-set.ipynb\n", "│ ├── 3-recursion.ipynb\n", "│ ├── 3-visualization.ipynb\n", "│ ├── 4-csv.ipynb\n", "│ ├── 5-bokeh.ipynb\n", "│ ├── 5-command.ipynb\n", "│ ├── 5-matplotlib.ipynb\n", "│ ├── 5-re.ipynb\n", "│ ├── argsprint.py\n", "│ ├── B1S.xml\n", "│ ├── fig\n", "│ │ ├── argsprint.png\n", "│ │ ├── console_in_browser.png\n", "│ │ ├── py_conv_1.png\n", "│ │ ├── py_conv_2.png\n", "│ │ ├── py_open_1.png\n", "│ │ ├── py_open_2.png\n", "│ │ ├── sample_py_browser.png\n", "│ │ ├── sample_py_mac_1.png\n", "│ │ ├── sample_py_mac_2.png\n", "│ │ ├── sample_py_mac_3.png\n", "│ │ ├── sample_py_win_1.png\n", "│ │ ├── sample_py_win2_1.png\n", "│ │ ├── sample_py_win2_2.png\n", "│ │ ├── sample_py_win2_3.png\n", "│ │ ├── sample_py_win_2.png\n", "│ │ ├── sample_py_win_3.png\n", "│ │ └── terminal_in_menu.png\n", "│ ├── sample.py\n", "│ ├── small.csv\n", "│ ├── text-sample.txt\n", "│ ├── tokyo-july-temps.csv\n", "│ └── tokyo-temps.csv\n", "├── index.ipynb\n", "├── index_of_terms.ipynb\n", "└── LICENSE\n", "```\n", "\n", "ここで、末端にあるものがファイルであり、末端以外にあるものがディレクトリ(フォルダ)です。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## カレントワーキングディレクトリ\n", "\n", "プログラムは、必ずどこかのディレクトリで動いています。\n", "このプログラムが動作しているディレクトリのことを、**ワーキングディレクトリ**(もしくは**作業ディレクトリ**)と呼びます。\n", "通例、特にWindowsやmacOSでは、何らかのファイルをクリックしてアプリケーションが起動したとき、その開いたファイルのある場所がワーキングディレクトリになります。\n", "\n", "ワーキングディレクトリは、プログラムの実行中に変更できます。\n", "Python上では [**`os.chdir`**](https://docs.python.org/ja/3/library/os.html#os.chdir) を使うことで変更できます。\n", "\n", "プログラム実行中の現在のワーキングディレクトリのことを、**カレントワーキングディレクトリ**、もしくは単に**カレントディレクトリ**と呼びます。\n", "カレントディレクトリは頻繁に利用するので、 `.` という特別な記号によって表現できます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## パス\n", "\n", "カレントディレクトリに置かれているファイルは、ファイル名を指定するだけで開くことができます。\n", "だから、4-1で示したように、カレントディレクトリにある `sample.txt` は、ファイル名を指定するだけで開けます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "open('sample.txt', 'r', encoding='utf-8')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一方、それ以外の場所にあるファイルについては、そのファイルのディレクトリまで含めて指定しなければ、開くことができません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "open('novel.txt', 'r')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "カレントディレクトリに存在しない `novel.txt` を開こうとしたので `FileNotFoundError` が生じました。\n", "`novel.txt` は、`text` というディレクトリの中にあるので、それ明示するために、`/` で区切って、次のように指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "open('text/novel.txt', 'r', encoding='utf-8')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "実は、カレントディレクトリにあるファイルが、ファイル名の指定だけで開けるのは、自動的に `./` が補われていたからでした。\n", "\n", "`open` の第1引数に渡す文字列ような、ファイルやディレクトリの場所を指定する表記を、**パス**と呼びます。\n", "パス(経路)と呼ぶのは、`/` 区切りで1歩ずつ次に進むディレクトリを指定することに由来しています。\n", "\n", "パスを記述する際、ルートディレクトリは `/` で表されます。\n", "ルートディレクトリから始まるパスを、**絶対パス**と呼びます。\n", "一方、カレントディレクトリからのパスを、**相対パス**と呼びます。\n", "パス表記において `/` 以外から始まる場合は、自動的に先頭に `./` が補われて、相対パスとして扱われます。\n", "\n", "さて、`./text/` というパス表記は、カレントディレクトリにある一段下の `text` ディレクトリに進むことに対応します。\n", "これに、一段上のディレクトリを表す `..` を組み合わせることで、より柔軟にパスを指定できます。\n", "\n", "たとえば、`./text/../` は `./` と同じディレクトリを指します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('sample.txt', 'r', encoding='utf-8') as f:\n", " print(f.read(), end='')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('./text/../sample.txt', 'r', encoding='utf-8') as f:\n", " print(f.read(), end='')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "また、カレントディレクトリを `./text/` に変化させた後に、`sample.txt` を開くときには、`../sample.txt` と指定することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import os\n", "os.chdir('./text') # 1段下の text に行く\n", "with open('../sample.txt', 'r', encoding='utf-8') as f:\n", " print(f.read())\n", "os.chdir('..') # 元のディレクトリに戻る" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 木構造\n", "\n", "ディレクトリの階層構造は、木を逆さにしたような形になっています。\n", "このことから、**木構造**もしくは単に**木**(tree)と呼ばれます。\n", "\n", "木構造の観点で、最上位の階層は**根**(root)と呼ばれ、末端は**葉**(leaf)と呼ばれます。\n", "木構造を成す要素(ここではファイルやディレクトリ)は,一般に**ノード**(node)と呼ばれます。\n", "\n", "階層構造における包含関係は、木構造では親子関係と呼ばれます。\n", "たとえば、教材のディレクトリ階層においては、ディレクトリ `IPP_textbook` の中に、ディレクトリ `1` とファイル `LICENSE` が含まれています。\n", "木構造の観点で、`IPP_textbook` は `1` と `LICENSE` の**親**(parent)と呼ばれ、逆に `1` と `LICENSE` は `IPP_textbook` の**子**(child)と呼ばれます。\n", "また、`1` と `LICENSE` のような共通の親を持つノード集合は、**兄弟**(sibling)と呼ばれます。\n", "親子関係の推移閉包として、**祖先**(ancestor)や**子孫**(descendant)も定義されます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## データ表現としての木構造\n", "\n", "OSのディレクトリ構造に限らず、木構造はデータ表現として広く用いられます。\n", "Pythonにおいても、入れ子のデータ構造は、木構造と見做せます。\n", "\n", "たとえば、教材のディレクトリ構造を、辞書の入れ子で表現すると、次のようになります.\n", "\n", "```python\n", "IPP_textbook = {\n", " '1': {'1-0.ipynb': Data('1-0.ipynb'), \n", " ..., \n", " 'colaboratory.png', Data('colaboratory.png')},\n", " '2': {'2-1.ipynb': Data('2-1.ipynb'),\n", " '2-1.ipynb': Data('2-2.ipynb'),\n", " '2-3.ipynb': Data('2-3.ipynb')},\n", " ...\n", " '5': {'5-1.ipynb': Data('5-1.ipynb'),\n", " '5-1.ipynb': Data('5-2.ipynb'),\n", " '5-3.ipynb': Data('5-3.ipynb'),\n", " 'factorial.py', Data('factorial.py'),\n", " 'fig': {'py_conv_1.png': Data('py_conv_1.png'),\n", " 'py_conv_2.png': Data('py_conv_2.png'),\n", " 'py_open_1.png': Data('py_open_1.png'),\n", " 'py_open_2.png': Data('py_open_2.png')}\n", " },\n", " ...\n", "}\n", "```\n", "\n", "ここで `Data(...)` は、`...` のファイルデータを意味しています。\n", "\n", "このデータ表現では、パス `IPP_textbook/2/2-2.ipynb` へのアクセスが、`IPP_textbook['2']['2-2.ipynb']` と表現されます。\n", "\n", "データを階層的に管理する際は、データ全体を木構造として捉えて表現することを考えましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/4/sample.txt ================================================ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ================================================ FILE: colab/4/shift_jis.txt ================================================ ================================================ FILE: colab/4/test.txt ================================================ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. ================================================ FILE: colab/4/text/novel.txt ================================================ 二人の若い紳士が、すつかりイギリスの兵隊のかたちをして、ぴか/\する鉄砲をかついで、白熊のやうな犬を二疋つれて、だいぶ山奥の、木の葉のかさ/\したとこを、こんなことを云ひながら、あるいてをりました。 「ぜんたい、こゝらの山は怪しからんね。鳥も獣も一疋も居やがらん。なんでも構はないから、早くタンタアーンと、やつて見たいもんだなあ。」 「鹿の黄いろな横つ腹なんぞに、二三発お見舞まうしたら、ずゐぶん痛快だらうねえ。くる/\まはつて、それからどたつと倒れるだらうねえ。」 ================================================ FILE: colab/4/utf-8.txt ================================================ あいうえお ================================================ FILE: colab/5/5-1.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/factorial.py\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 5-1. モジュールの使い方\n", "モジュールの使い方について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/reference/import.html\n", "- https://docs.python.org/ja/3/tutorial/modules.html\n", "- https://docs.python.org/ja/3/library/math.html\n", "\n", "## モジュールのインポート\n", "\n", "Pythonでは特別な関数や値をまとめたもの(これを**モジュール**といいます)を使うために、**`import`** という文を使います(第1回 (1-1) においても説明しました)。具体的には次のように記述します。\n", "\n", "---\n", "```Python\n", "import モジュール名\n", "```\n", "---\n", "\n", "たとえば、数学関係の機能をまとめた `math` というモジュールがあります。これらの関数や値を使いたいときは、以下のようにして `math` モジュールを `import` で**インポート**します。そうすると、`math.関数名` という形で関数を用いることができます。 " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import math# importは大抵セルの一番上に記述します\n", "print(math.sqrt(2)) # sqrt は平方根を計算する関数\n", "print(math.pi) # πの値\n", "print(math.sin(math.pi/4)) # sin関数 \n", "print(math.cos(0)) # cos関数 \n", "print(math.log(32,2)) # 2を底とする32の対数(texで記述すると、$\\log_2 32$)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の例では、`math` モジュールの中の関数や値を使用しています。\n", "\n", "注意しなければならないのは、モジュールの中の関数を使う場合には、\n", "\n", "---\n", "```Python\n", "モジュール名.モジュールの中の関数名\n", "```\n", "---\n", "\n", "とする必要があるということです。\n", "\n", "モジュールの中の値(たとえば `math.pi`)も同様です。\n", "\n", "なお、複数の関数名をコンマ `,` で区切って並べて同時にインポートすることもできます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `from`\n", "\n", "モジュール内で定義されている関数を「モジュールの中の関数名」のようにして、「モジュール名.」を付けずにそのままの名前で、モジュールの読み込み元のプログラムで使いたい場合には、**`from`** を以下のように書くことで利用することができます。\n", "\n", "---\n", "```Python\n", "from モジュール名 import モジュールの中の関数名\n", "```\n", "---\n", "\n", "たとえば、次のようになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from math import sqrt\n", "print(sqrt(2)) # sqrt は平方根を計算する関数 \n", "from math import pi\n", "print(pi) # πの値\n", "from math import sin\n", "print(sin(math.pi/4)) # sin関数 \n", "from math import cos\n", "print(cos(0)) # cos関数 \n", "from math import log\n", "print(log(32,2)) # 2を底とする32の対数(texで記述すると、$\\log_2 32$)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この方法では、関数ごとに `from` を用いてインポートする必要があります。\n", "\n", "なお、関数だけではなく、グローバル変数や後に学習するクラスも、\n", "このようにしてインポートすることができます。\n", "\n", "別の方法として、**ワイルドカード** **`*`** を利用する方法もあります。\n", "\n", "---\n", "```Python\n", "from math import *\n", "```\n", "---\n", "\n", "この方法ではアンダースコア `_` で始まるものを除いた全ての名前が読み込まれるため、明示的に名前を指定する必要はありません。\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from math import *\n", "print(factorial(5)) # 5 の階乗 # import mathを使う場合、math.factorial(5)\n", "print(floor(2.31)) # 2.31以下の最大の整数 # import mathを使う場合、math.floor(2.31)\n", "print(e) # ネイピア数 # import mathを使う場合、math.e" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ただしこの方法は推奨されていません。理由は読み込んだモジュール内の未知の名前とプログラム内の名前が衝突する可能性があるためです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pi = 'パイ' # piという変数に文字列「パイ」を代入する\n", "print(pi) \n", "from math import *\n", "print(pi) # mathモジュールのpiの値で上書きされる(衝突)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `as`\n", "\n", "モジュール名が長すぎるなどの理由から別の名前としたい場合は、**`as`** を利用する方法もあります。\n", "たとえば、5-3において学習するNumPyというライブラリは `numpy` モジュールとして提供されていますが、\n", "次のように、 `numpy` を `np` という略称で使うことがあります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy\n", "print(numpy.ones((3, 5))) # 3×5の行列を表示\n", "import numpy as np\n", "print(np.ones((3, 5))) # np という短い名称で同じ関数を利用する" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "個々の関数ごとに別の名前を付けることもできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import math\n", "print(math.factorial(5)) # 階乗を求める関数factorial # 5の階乗\n", "from math import factorial as fact # fact という名前でmath.factorialを使用したい\n", "print(fact(5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "第1回では、数学関数を以下のようにインポートし、`math.sqrt()` のようにして、数学関数や数学関係の変数を利用していました。\n", "\n", "---\n", "```Python\n", "import math\n", "print(math.sqrt(2))\n", "print(math.sin(math.pi))\n", "```\n", "\n", "---\n", "\n", "以下のセルを、モジュール名を付けないでこれらの関数や変数を参照できるように変更してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "import ...\n", "...\n", "\n", "print(sqrt(2))\n", "print(sin(pi))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答\n", "\n", "`from` を使ってモジュールを指定、参照する関数を `import` でインポートしてください。 " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from math import sqrt, sin, pi\n", "print(sqrt(2))\n", "print(sin(pi))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/5/5-2.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/factorial.py\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 5-2. モジュールの作り方\n", "モジュールの作り方について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/modules.html\n", "- https://docs.python.org/ja/3/reference/import.html\n", "\n", "Pythonではプログラムを**モジュール**という単位で、複数のファイルに分割することができます。\n", "通例、一度定義した便利な関数などを別のプログラムで再利用するときには、再利用される部分をモジュールとして切り出します。\n", "プログラムが大きくなると、このように複数のファイルに分割した方が開発や保守が簡単になります。\n", "\n", "## モジュールファイル\n", "\n", "本授業で扱ってきたノートブックファイル(拡張子 `.ipynb`)は、コードセル(Codeセル)にPythonソースコード、Markdownセルに文書を持ち、内部的に出力結果も保存しています。 一方、モジュールファイル(拡張子 `.py`)は、Pythonソースコードのみを含んだファイルです。\n", "\n", "モジュールファイルを作るときには、Jupyter Notebook におけるコードセルの内容のみをファイルに記述することになります。\n", "\n", "モジュールファイルの文字コードはUTF-8であることが[公式に推奨されています](https://www.python.org/dev/peps/pep-0008/#source-file-encoding)。\n", "原則としてUTF-8でエンコードして保存してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ノートブックファイルをモジュールファイルに変換する\n", "\n", "本授業で利用しているノートブックファイルを `.py` としてセーブするには、\n", "「ファイル」メニューの「.py をダウンロード」項目を選択します。\n", "\n", "そうすると、コードセルだけがプログラム行として有効になり、その他の行はコメントアウトされたモジュールファイルがダウンロードできます。\n", "ダウンロード先はブラウザによって定まりますが、ダウンロードフォルダになることが一般的でしょう。\n", "\n", "この方法では、全てのコードセルの内容を一度に実行するプログラムとして保存されます。\n", "ノートブックのようにセル単位の実行するわけではないことに注意する必要があります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### モジュールファイルをアップロードする\n", "\n", "次に、ダウンロードしたモジュールファイルをColaboratoryで使うには、\n", "Colaboratoryの実行環境の中のファイルシステムのカレントディレクトリに\n", "モジュールファイルをアップロードする必要があります。\n", "このためには、以下のセルを実行してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import sys\n", "if 'google.colab' in sys.modules:\n", " from google.colab import files\n", " uploaded = files.upload() # Upload to the current directory" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 自作モジュールの使い方\n", "\n", "モジュールで定義されている関数を利用するには、**`import`** を用いて `import モジュール名` と書きます。\n", "**モジュール名**は、モジュールファイル名から拡張子 `.py` を除いたものです。\n", "\n", "すると、モジュールで定義されている関数は `モジュール名.関数名` によって参照できます。\n", "\n", "次の関数が記述された `factorial.py` というモジュールを読み込む場合を説明します。\n", "ただし、読み込み元と同じディレクトリに `factorial.py` が存在すると仮定します。\n", "\n", "---\n", "\n", "factorial.py:\n", "\n", "```Python\n", "# 階乗n!を返す\n", "def fact(n):\n", " prod = 1\n", " for i in range(1, n + 1):\n", " prod *= i\n", " return prod\n", "```\n", "\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import factorial\n", "\n", "factorial.fact(6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`from` や `as` の使い方も既存のモジュールと全く同じです。\n", "\n", "モジュール内で定義されている名前を読み込み元のプログラムでそのまま使いたい場合は、**`from`** を用いて以下のように書くことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from factorial import fact\n", "\n", "fact(6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ワイルドカード **`*`** を利用する方法もありますが、推奨されていません。\n", "読み込まれるモジュール内の未知の名前と、読み込み元のプログラム中の名前が衝突する可能性があるためです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from factorial import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "モジュール名が長すぎるなどの理由から別の名前としたい場合は、**`as`** を利用する方法もあります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import factorial as f\n", "\n", "f.fact(6)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/5/5-3.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/factorial.py\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/5/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 5-3. NumPyライブラリ\n", "\n", "NumPyについて説明します。\n", "\n", "参考\n", "\n", "- https://docs.scipy.org/doc/numpy/user/quickstart.html\n", "- https://docs.scipy.org/doc/numpy/user/basics.html\n", "\n", "**NumPy**とは、多次元配列を効率的に扱うライブラリです。\n", "Pythonの標準ライブラリではありませんが、科学技術計算や機械学習など、ベクトルや行列の演算が多用される分野では、事実上の標準ライブラリとしての地位を確立しています。\n", "\n", "NumPyを用いるには、まず、**`numpy`** モジュールをインポートする必要があります。\n", "慣習として、`np` と別名をつけて利用されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NumPyでは、Python標準の数値やリストの代わりに、特別な数値や配列を用いることで、格段に効率的な配列演算を実現します。\n", "以下では、配列の基本的な操作や機能を説明します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 配列の構築\n", "\n", "**配列**とは、特定の型の値の並びです。\n", "**`numpy.array()`** 関数で構築できます。\n", "このとき、配列の要素はPython標準のリストやタプルで指定します。\n", "どちらを用いて作成しても全く同じ配列を作成できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.array([1,2,3]) # リストから配列作成\n", "print(a)\n", "b = np.array((1,2,3)) # タプルからの配列作成\n", "print(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`print` の結果はリストと似ていますが、要素が `,` ではなく空白で区切られているに注意してください。\n", "`print` ではなく、式の評価結果の場合、より違いが明示されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "配列は **`numpy.ndarray`** というデータ型によって実現されています。\n", "組み込み関数 `type()` を使うと、データ型を調べられます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(np.array([1,2,3,4,5])) # 配列の型 " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type([1,2,3,4,5])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`array()` が、リストではなく `ndarray` を返していることがわかります。\n", "\n", "### 要素型\n", "\n", "配列の要素を構成する値には幾つかの型がありますが、次の4つの型を知っていればとりあえずは十分です。\n", "\n", "| 型名 | 説明 |\n", "|--- |--- |\n", "| **`numpy.int32`** | 整数(32-bit)を表す型 |\n", "| **`numpy.float64`** | 実数(64-bit)を表す型 |\n", "| **`numpy.complex128`** | 複素数(64-bit実数の組)を表す型 |\n", "| **`numpy.bool_`** | 真理値を表す型 |\n", "\n", "配列は、リストと異なり、型の異なる要素を混在させることはできません。\n", "\n", "`array()` の `dtype` 引数に、要素型を表すオブジェクトや文字列値を与えることで、指定された要素型の配列を構築できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(np.array([-1,0,1], dtype=np.int32)) # np.int32の代わりに'int32'でも同じ" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "実数には、小数点が付与されて印字されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(np.array([-1,0,1], dtype=np.float64)) # np.float64の代わりに'float64'でも同じ" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "複素数は実部と虚部を表す実数の組であり、虚部には `j` が付与されて印字されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(np.array([-1,0,1], dtype=np.complex128)) # np.complex128の代わりに'complex128'でも同じ" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "数値から真理値への変換では、`0` が `False` で、`0` 以外が `True` になります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(np.array([-1,0,1], dtype=np.bool_)) # np.bool_の代わりに'bool'でも同じ" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 多次元配列\n", "\n", "**多次元配列**は、配列の中に配列がある入れ子の配列です。\n", "入れ子のリストやタプルを `numpy.array()` に渡すことで構築できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(np.array([[1,2],[3,4]])) # 2次元配列の構築" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(np.array([[[1,2],[3,4]],[[5,6],[7,8]]])) # 3次元配列の構築" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の例からわかるように、2次元配列は行列のように、3次元配列は行列の配列のように印字されます。\n", "\n", "多次元配列は、要素となる配列の長さが等しいことが想定されます。\n", "つまり、2次元配列は、行列のように各行の長さが等しくなければなりません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(np.array([[1,2],[3]])) # 行の長さが異なる場合" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように行の長さが異なる場合は、多次元配列とは見做されません。\n", "\n", "多次元配列の各次元の長さの組を、多次元配列の**形** (shape) と呼びます。\n", "特に2次元配列の場合、行列と同様に、行数(内側にある配列の数)と列数(内側にある配列の要素数)の組を使って、行数×列数で形を表記します。\n", "\n", "1次元配列に対して **`reshape()`** メソッドを使うと、引数で指定された形の多次元配列に変換することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a1 = np.array([0, 1, 2, 3, 4, 5]) # 1次元配列\n", "a2 = a1.reshape(2,3) # 2×3の2次元配列\n", "a2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここで、`reshape()` を適用する前後の配列(ここでは `a1` と `a2`)は、内部的にデータを共有していることに注意してください。\n", "つまり、`a1` の要素を更新すると、`a2` にも影響を及ぼします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a1[1] = 6\n", "print(a1)\n", "print(a2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`ravel()`** メソッドを使うと、多次元配列を1次元配列に戻すことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.array([0, 1, 2, 3, 4, 5]).reshape(2,3)\n", "print(a)\n", "print(a.ravel())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`ravel()` の結果も、`reshape()` と同様に、元の配列と要素を共有します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "elems = np.array([0, 1, 2, 3, 4, 5])\n", "a = elems.reshape(2,3).ravel() # ravel()は要素をelemsと共有\n", "elems[1] = 6\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、要素をコピーして変換する **`flatten()`** メソッドもありますが、コピーしない `ravel()` の方が効率的です。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ▲**配列のデータ属性**\n", "\n", "配列はオブジェクトであり、その配列に関する様々な情報を属性として保持します。\n", "(オブジェクトの属性については6-3に簡単な説明があります。)\n", "配列が持つ代表的なデータ属性(メソッド以外の属性)を次の表にまとめます。\n", "\n", "| 属性 | 意味 |\n", "|--- |--- |\n", "| `a.dtype` | 配列 `a` の要素型 |\n", "| `a.shape` | 配列 `a` の形(各次元の長さのタプル)|\n", "| `a.ndim` | 配列 `a` の次元数(`len(a.shape)` と等しい)|\n", "| `a.size` | 配列 `a` の要素数(`a.shape` の総乗と等しい)|\n", "| `a.flat` | 配列 `a` の1次元表現(`a.ravel()` と等しい)|\n", "| `a.T` | 配列 `a` を転置した配列(`a` と要素を共有)|" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 配列要素を生成する構築関数\n", "\n", "要素を生成して配列を構築する代表的な関数を紹介します。\n", "特に断りが無い場合、ここで紹介する関数は、`array()` と同様に `dtype` 引数で要素型を指定可能です。\n", "\n", "### `arange`\n", "\n", "**`numpy.arange()`** は、組み込み関数 `range()` の配列版です(`arange` は array range の略)。\n", "開始値・終了値・刻み幅を引数にとります。\n", "デフォルトの開始値は `0`、刻み幅は `1` です。\n", "`range()` と違って、引数の値は整数に限定されません。\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(np.arange(3)) # range(3)に対応する配列\n", "print(np.arange(0, 1, 0.2)) # 0を開始値として0.2刻みで1未満の要素を生成" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `linspace`\n", "**`numpy.linspace()`** 関数は、範囲を等分割した値からなる配列を生成します。\n", "第1引数と第2引数には、それぞれ範囲の開始値と終了値、第3引数には分割数を指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(np.linspace(0, 1, 4)) # 0から1の値を4分割した値を要素に持つ配列" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `zeros` と `ones`\n", "**`numpy.zeros()`** 関数は、`0` からなる配列を生成します。\n", "同様に、**`numpy.ones()`** 関数は、`1` からなる配列を生成します。\n", "どちらも、生成される形を第1引数に取ります。\n", "デフォルトの要素型は、実数です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(np.zeros(4)) # 長さ4の1次元配列\n", "print(np.zeros((2,3))) # 2×3の2次元配列を生成\n", "print(np.ones(4)) # 長さ4の1次元配列\n", "print(np.ones((2,3))) # 2×3の2次元配列を生成" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `random.rand`\n", "**`numpy.random.rand()`** 関数は、0 以上 1 未満の乱数からなる配列を生成します。\n", "引数には生成される配列の形を指定します。\n", "要素型は実数に限定されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(np.random.rand(4)) # 長さ4の1次元配列\n", "print(np.random.rand(2,3)) # 2×3の2次元配列を生成" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この他にも、**`numpy.random.randn()`**・**`numpy.random.binomial()`**・**`numpy.random.poisson()`** は、それぞれ、正規分布・二項分布・ポアソン分布の乱数からなる配列を生成します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "引数に整数 $n$ を取り、$i$ から始まる連番の整数からなる配列を$i$番目 ($i\\ge 0$) の行として持つ $n\\times n$ の2次元配列を返す関数 `range_square_matrix()` を、`arange()` を用いて定義してください。\n", "\n", "たとえば、`range_square_matrix(3)` は、\n", "```\n", "[[0 1 2]\n", " [1 2 3]\n", " [2 3 4]]\n", "```\n", "と印字されるような2次元配列を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def arange_square_matrix(n):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のセルを実行して、`True` が表示されることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(all(map(all,(arange_square_matrix(3) == np.array([[0,1,2],[1,2,3],[2,3,4]])))))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 配列要素の操作\n", "\n", "### インデックスアクセス\n", "\n", "配列の要素には、リストの場合と同様に、`0` から始まるインデックスを使って参照できます。\n", "リストと同じく、配列の先頭要素のインデックスは `0`、最後の要素のインデックスは `-1` となります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.arange(3)\n", "print(a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a[0]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a[-1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a[-1] = 3 # 要素への代入もできる\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "多次元配列では、高次元(入れ子の外側)から順にインデックスを指定します。\n", "特に2次元配列、すなわち行列の場合は、行インデックスと列インデックスを順に指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.arange(6).reshape(2,3)\n", "print(a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a[1,2] # 行と列のインデックスをまとめて指定" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a[1,2] = 6 # 要素への代入もできる\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### スライス\n", "\n", "リストと同様に、配列の**スライス**を構築できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.arange(5)\n", "print(a)\n", "print(a[1:4])\n", "print(a[1:])\n", "print(a[:-2])\n", "print(a[::2])\n", "print(a[::-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "配列のスライスに対して代入すると、右辺の値がコピーされて、スライス元の配列にまとめて代入されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.arange(5)\n", "print(a)\n", "a[1:4] = 6\n", "print(a)\n", "a = np.arange(5)\n", "a[::2] = 6\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一方、リストに対しては、以下はエラーになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "a = [0,1,2,3,4]\n", "print(a)\n", "a[1:4] = 6" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = [0,1,2,3,4]\n", "print(a)\n", "a[1:4] = [6]\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように、配列のスライスに対する代入の振舞いは、リストの場合と異なることに注意してください。\n", "\n", "多次元配列に対しては、インデックスの参照と同様に、高い次元のスライスから順に並べて指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.arange(9).reshape(3,3)\n", "print(a)\n", "print(a[:2,:2])\n", "print(a[1:,1:])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "多次元配列に対するスライスは、入れ子リストに対するスライスとは意味が異なることに注意してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### for文\n", "\n", "リストと同様に、for文を用いて、配列要素への反復処理を記述できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for v in np.arange(3):\n", " print(v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "多次元配列の場合は、最外の配列に対して反復します。\n", "つまり、2次元配列の場合、行の配列に対する反復処理となります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for row in np.arange(6).reshape(2,3):\n", " print(row)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "for文と併用される `enumerate()` の多次元配列版として、`numpy.ndenumerate()` 関数が提供されています。\n", "`numpy.ndenumerate()` は、(多次元)インデックスと要素の組を列挙します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for idx, e in np.ndenumerate(np.arange(6).reshape(2,3)):\n", " print(idx, e)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for idx, e in np.ndenumerate(np.arange(3)):\n", " print(idx, e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 要素毎の演算\n", "\n", "配列に対する要素毎の演算は、簡潔に記述できます。\n", "しかも、for文で記述するより、効率がよいです。\n", "要素毎の演算を上手く使えるかどうかが、NumPyプログラミングの肝と言っても過言ではないでしょう。\n", "\n", "### **配列のスカラ演算**\n", "\n", "配列とスカラとの算術演算を記述すると、要素毎のスカラ演算となります。\n", "演算結果として、新しい配列が返ります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.arange(4)\n", "print(a)\n", "\n", "print(a + 1) # 各要素に1を加算\n", "print(a - 1) # 各要素に1を減算\n", "print(a * 2) # 各要素に2を乗算\n", "print(a / 2) # 各要素を2で除算\n", "print(a // 2) # 各要素を2で整数除算\n", "print(a % 2) # 各要素に2の剰余演算\n", "print(a ** 2) # 各要素を2乗\n", "\n", "print(1 + a) # 左側がスカラでもよい\n", "print(1 - a) # 左側がスカラでもよい\n", "print(2 * a) # 左側がスカラでもよい\n", "b = a + 1\n", "print(1 / b) # 左側がスカラでもよい\n", "print(9 // b) # 左側がスカラでもよい" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **配列同士の演算**\n", "\n", "形が同じ配列同士の算術演算は、同じ位置の要素同士の演算となります。\n", "演算結果として、新しい配列が返ります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.arange(4).reshape(2,2)\n", "b = np.arange(1,5).reshape(2,2)\n", "print(a)\n", "print(b)\n", "print(a + b) \n", "print(a - b)\n", "print(a * b)\n", "print(a / b)\n", "c = 3 * a\n", "print(c // b)\n", "print(a % b)\n", "print(a ** b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "実は、形が同じでない配列同士の算術演算も可能ですが、振舞いが複雑なので間違いやすいです。\n", "配列同士の算術演算は、形が同じ配列に限定する方が賢明です。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ユニバーサル関数\n", "\n", "NumPyには**ユニバーサル関数**と呼ばれる、任意の形の配列を取り、各要素に所定の演算を与えた結果を返す関数があります。\n", "その代表例は、**`numpy.sqrt()`** 関数です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.zeros(3) + 2\n", "print(a)\n", "print(np.sqrt(a)) # 各要素はsqrt(2)\n", "b = np.zeros((2,2)) + 2\n", "print(np.sqrt(b)) # 各要素はsqrt(2)\n", "print(np.sqrt(2)) # スカラ(0次元配列)も扱える" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この他にも、多数のユニバーサル関数が提供されています。\n", "詳しくは、[ユニバーサル関数の一覧](https://docs.scipy.org/doc/numpy-1.14.0/reference/ufuncs.html#available-ufuncs)を参照してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## よく使われる配列操作\n", "### `dot`\n", "\n", "**`numpy.dot()`** は、2つの配列を引数に取り、そのドット積を返します。\n", "両者が1次元配列のときは、ベクトル内積と等しいです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.dot(np.arange(4), np.arange(1,5)) # 0*1 + 1*2 + 2*3 + 3*4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2次元配列同士だと、行列乗算と等しいです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# [[0 1] [[1 2]\n", "# [2 3]] と [3 4]] の行列積\n", "print(np.dot(np.arange(4).reshape(2,2), np.arange(1,5).reshape(2,2)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `sort`\n", "\n", "**`numpy.sort()`** 関数は、昇順でソートされた新しい配列を返します。\n", "これは、組み込み関数 `sorted()` の配列版です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.array([3, 4, -1, 0, 2])\n", "print(a)\n", "print(np.sort(a))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一方、配列の **`sort()`** メソッドは、配列を破壊的に(インプレースで)ソートします。\n", "これは、リストの `sort()` メソッドの配列版です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.array([3, 4, -1, 0, 2])\n", "print(a)\n", "a.sort()\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `sum`, `max`, `min`, `mean`\n", "\n", "配列のメソッド **`sum()`**・**`max()`**・**`min()`**・**`mean()`** は、それぞれ総和・最大値・最小値・算術平均を返します。\n", "これらのメソッドは、引数が与えられない場合、全要素を集計した結果を返します。\n", "多次元配列の場合、集計する次元を指定できます。\n", "具体的には、2次元配列の場合、`0` を指定すると各列に、`1` を指定すると各行に、対応するメソッドを適用した結果が返されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.arange(6).reshape(2,3)\n", "print(a)\n", "print(a.sum())\n", "print(a.sum(0))\n", "print(a.sum(1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この他にも、多数の数学・統計関連のメソッドや関数が提供されています。\n", "詳しくは、[数学関数](https://docs.scipy.org/doc/numpy/reference/routines.math.html)や[統計関数](https://docs.scipy.org/doc/numpy/reference/routines.statistics.html)を参照してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 配列の保存と復元\n", "\n", "配列は、ファイルに保存したり、ファイルから読み出したりすることが、簡単にできます。\n", "\n", "**`numpy.savetxt()`** 関数は、与えられた配列を指定されたファイル名をつけてテキスト形式で保存します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.savetxt('arange3.txt', np.arange(3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この `arange3.txt` は、次のような内容になっているはずです。\n", "```\n", "0.000000000000000000e+00\n", "1.000000000000000000e+00\n", "2.000000000000000000e+00\n", "```\n", "2次元配列は、列が空白区切りで保存されます" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.savetxt('arange2x3.txt', np.arange(6).reshape(2,3))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この `arange2x3.txt` は、次のような内容になっているはずです。\n", "```\n", "0.000000000000000000e+00 1.000000000000000000e+00 2.000000000000000000e+00\n", "3.000000000000000000e+00 4.000000000000000000e+00 5.000000000000000000e+00\n", "```\n", "\n", "一方、**`numpy.loadtxt()`** 関数は、与えられた名前のファイルに保存された配列を復元します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.loadtxt('arange2x3.txt')\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "保存するときに、列の区切り文字をデフォルトの `' '` 以外にしたい場合、`savetxt()` の `delimiter` 引数に区切り文字(列)を指定します。これを復元するときには、`loadtxt()` の `delimiter` 引数に同じ値を指定する必要があります。\n", "ただし、区切り文字列はASCII(正確にはLatin-1)で解釈可能でなければなりません。\n", "\n", "大規模な配列をテキスト形式で保存すると、ファイルサイズがとても大きくなります。\n", "そういう場合、圧縮保存が有用です。\n", "\n", "保存するファイル名の拡張子を `.gz` とすることで、`savetxt()` は自動的にGZip形式で圧縮して保存します。\n", "復元するファイル名の拡張子が `.gz` であれば、`loadtxt()` はGZip形式だと判断して、自動的に解凍して復元します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲**真理値配列によるインデックスアクセス**\n", "\n", "配列に対して、比較演算を適用すると、算術演算と同様に要素毎に演算されて、真理値の配列が返ります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.arange(6)\n", "print(a)\n", "print(a < 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように作られた真理値配列は、インデックスとして利用することができます。\n", "これによって、条件を満たす範囲を取り出すような記述が可能になります。\n", "次の具体例を見てみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a = np.array([0,1,2,-3,-4,5,-6,-7])\n", "print(a)\n", "print(a[a < 0]) # 負の要素を取り出し\n", "print(a[(a < 0) & (a % 2 == 0)]) # 負で偶数の要素を取り出し\n", "a[a < 0] = 8 # 負の要素を8に上書き\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一見すると単なる条件式のように見えますが、インデックスとなるのは真理値ではなく真理値の配列です。\n", "したがって、真理値を返す `and`・`or`・`not` の代わりに、要素毎の演算を行う `&`・`|`・`~` を用いる必要があります。\n", "\n", "同様の記法は、7-1で扱うpandasライブラリでも利用されます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲線形代数の演算\n", "\n", "`numpy.dot()` は、2次元配列を与えたときには、行列積となりました。\n", "それだけでなく、行列積専用の **`numpy.matmul()`** も提供されています。\n", "\n", "また、単位行列は **`numpy.identity()`** 関数で作成することができます。\n", "引数に行列のサイズを指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "I = np.identity(3)\n", "print(I)\n", "a = np.arange(9).reshape(3,3)\n", "print(a)\n", "print(np.matmul(a, I))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`numpy.linalg.norm()`** 関数は、与えられたベクトル(1次元配列)もしくは行列(2次元配列)のノルムを返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.linalg.norm(np.ones(3)) # ユークリッドノルムを計算するのでsqrt(3)と等しい" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NumPyでは、行列の分解、転置、行列式などの計算を含む線形代数の演算は、**`numpy.linalg`** モジュールで提供されています。\n", "詳しくは、[線形代数関連関数](https://docs.scipy.org/doc/numpy/reference/routines.linalg.html)を参照してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def arange_square_matrix(n):\n", " return np.array([np.arange(i, n+i) for i in range(n)])" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/5/factorial.py ================================================ # 階乗n!を返す def fact(n): prod = 1 for i in range(1, n + 1): prod *= i return prod ================================================ FILE: colab/6/6-1.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/6/jugemu.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 6-1. 内包表記\n", "\n", "**内包表記**について説明します。\n", "\n", "参考:\n", "\n", "- https://docs.python.org/ja/3/tutorial/datastructures.html#list-comprehensions\n", "- https://docs.python.org/ja/3/tutorial/datastructures.html#nested-list-comprehensions\n", "\n", "## リスト内包表記\n", "\n", "Pythonでは各種の**内包表記** (comprehension) が利用できます。\n", "\n", "以下のような整数の自乗を要素に持つリストを作るプログラムでは、" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "squares1 = []\n", "for x in range(6):\n", " squares1.append(x**2)\n", "squares1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`squares1` として `[0, 1, 4, 9, 16, 25]` が得られます。\n", "これを内包表記を用いて書き換えると、以下のように一行で書け、プログラムが読みやすくなります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "squares2 = [x**2 for x in range(6)]\n", "squares2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数 **`sum`** は与えられた数のリストの総和を求めます。\n", "(2-2の練習にあった `sum_list` と同じ機能を持つ組み込みの関数です。)\n", "内包表記に対して `sum` を適用すると以下のようになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sum([x**2 for x in range(6)])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下の内包表記は3-2で用いられていました。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[chr(i + ord('a')) for i in range(26)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "文字列のリストが変数 `strings` に与えられたとき、\n", "それぞれの文字列の長さからなるリストを返す内包表記を記述してください。\n", "\n", "`strings = ['The', 'quick', 'brown']` のとき、結果は `[3, 5, 5]` となります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "strings = ['The', 'quick', 'brown']\n", "[ここに内包表記を書く]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "コンマで区切られた10進数からなる文字列が変数 `str1` に与えられたとき、\n", "それぞれの10進数を数に変換して得られるリストを返す内包表記を記述してください。\n", "\n", "`str1 = '123,45,-3'` のとき、結果は `[123, 45, -3]` となります。\n", "\n", "なお、コンマで区切られた10進数からなる文字列を、10進数の文字列のリストに変換するには、メソッド `split` を用いることができます。\n", "また、10進数の文字列を数に変換するには、**`int`** を関数として用いることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "str1 = '123,45,-3'\n", "[ここに内包表記を書く]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "数のリストが与えらえたとき、リストの要素の分散を求める関数 `var` を\n", "内包表記と関数 `sum` を用いて定義してください。\n", "以下のセルの `...` のところを書き換えて `var` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def var(lst):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(var([3,4,1,2]) == 1.25)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 内包表記の入れ子\n", "また内包表記を**入れ子**(**ネスト**)にすることも可能です:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[[x*y for y in range(x+1)] for x in range(4)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ネストした内包表記は、外側から読むとわかりやすいです。\n", "`x` を `0` から `3` まで動かしてリストが作られます。\n", "そのリストの要素1つ1つは内包表記によるリストになっていて、\n", "それぞれのリストは `y` を 0 から `x` まで動かして得られます。\n", "\n", "以下のリストは、上の2重のリストをフラットにしたものです。\n", "この内包表記では、`for` が2重になっていますが、自然に左から読んでください。\n", "`x` を `0` から `3` まで動かし、そのそれぞれに対して `y` を `0` から `x` まで動かします。\n", "その各ステップで得られた `x*y` の値をリストにします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[x*y for x in range(4) for y in range(x+1)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下の関数は、与えられた文字列の全ての空でない部分文字列からなるリストを返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def allsubstrings(s):\n", " return [s[i:j] for i in range(len(s)) for j in range(i+1,len(s)+1)]\n", "\n", "allsubstrings('abc')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "次のような関数 `sum_lists` を作成してください。\n", "\n", "- `sum_lists` はリスト `list1` を引数とします。\n", "- `list1` の各要素はリストであり、そのリストの要素は数です。\n", "- `sum_lists` は、`list1` の各要素であるリストの総和を求め、それらの総和を足し合せて返します。\n", "\n", "ここでは、内包表記と関数 `sum` を用いて `sum_lists` を定義してください。\n", "以下のセルの `...` のところを書き換えて `sum_lists` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_lists(list1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(sum_lists([[20, 5], [6, 16, 14, 5], [16, 8, 16, 17, 14], [1], [5, 3, 5, 7]]) == 158)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "リスト `list1` と `list2` が引数として与えられたとき、次のようなリスト `list3` を返す関数 `sum_matrix` を作成してください。\n", "\n", "- `list1`, `list2`, `list3` は、3つの要素を持ちます。\n", "- 各要素は大きさ 3 のリストになっており、そのリストの要素は全て数です。\n", "- `list3[i][j]` (ただし、`i` と `j` は共に、0 以上 2 以下の整数)は `list1[i][j]` と `list2[i][j]` の値の和になっています。\n", "\n", "ここでは、内包表記を用いて`sum_matrix` を定義してください。以下のセルの `...` のところを書き換えて `sum_matrix` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_matrix(list1, list2):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(sum_matrix([[1,5,3],[4,5,6],[7,8,9]], [[1,4,7],[2,5,8],[3,6,9]])==[[2, 9, 10], [6, 10, 14], [10, 14, 18]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲**条件付き内包表記**\n", "\n", "内包表記は `for` に加えて `if` を使うこともできます:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "words = ['cat', 'dog', 'elephant', None, 'giraffe']\n", "length = [len(w) for w in words if w != None]\n", "print(length)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この場合、`length` として要素が `None` の場合を除いた `[3, 3, 8, 7]` が得られます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲**セット内包表記**\n", "\n", "内包表記はセット(集合)に対しても使うことができます:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "words = ['cat', 'dog', 'elephant', 'giraffe']\n", "length_set = {len(w) for w in words}\n", "print(length_set)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`length_set` として `{3, 7, 8}` が得られます。\n", "セット型なので、リストと異なり重複する要素は除かれます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲**辞書内包表記**\n", "さらに、内包表記は辞書型でも使うことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "words = ['cat', 'dog', 'elephant', 'giraffe']\n", "length_dic = {w:len(w) for w in words}\n", "print(length_dic)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`length_dic` として `{'cat': 3, 'dog': 3, 'elephant': 8, 'giraffe': 7}` が得られます。\n", "\n", "長さと文字列を逆にするとどうなるでしょうか。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "length_rdic = {len(w): w for w in words}\n", "print(length_rdic)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲**ジェネレータ式**\n", "\n", "内包表記と似たものとして、ジェネレータ式というものがあります。\n", "リスト内包表記の `[]` を `()` に置き換えれば、ジェネレータ式になります。\n", "ジェネレータ式は、4-2で説明した**イテレータ**を構築します。\n", "4-2で説明したように、イテレータは、for文で走査(全要素を訪問)できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "it = (x * 3 for x in 'abc')\n", "for x in it:\n", " print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "イテレータを組み込み関数 `list()` や `tuple()` に渡すと、対応するリストやタプルが構築されます。\n", "なお、ジェネレータ式を直接引数とするときには、ジェネレータ式の外側の `()` は省略可能です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list(x ** 2 for x in range(5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "tuple(x ** 2 for x in range(5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "総和を計算する組み込み関数 `sum()` など、リストやタプルを引数に取れる大抵の関数には、イテレータも渡せます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sum(x ** 2 for x in range(5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の例において、ジェネレータ式の代わりにリスト内包表記を用いても同じ結果を得ますが、\n", "計算の途中で実際にリストを構築するので、メモリ消費が大きいです。\n", "ジェネレータ式では、リストのように走査できるイテレータを構築するだけなので、リスト内包表記よりメモリ効率がよいです。\n", "したがって、関数に渡すだけの一時オブジェクトには、リスト内包表記ではなくジェネレータ式を用いるのが有効です。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "strings = ['The', 'quick', 'brown']\n", "[len(x) for x in strings]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "str1 = '123,45,-3'\n", "[int(x) for x in str1.split(',')]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def var(lst):\n", " n = len(lst)\n", " av = sum(lst)/n\n", " return sum([(x - av)*(x - av) for x in lst])/n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def var(lst):\n", " n = len(lst)\n", " av = sum(lst)/n\n", " return sum([x*x for x in lst])/n - av*av" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_lists(list1):\n", " return sum([sum(lst) for lst in list1])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def sum_matrix(list1,list2):\n", " return [[list1[i][j] + list2[i][j] for j in range(3)] for i in range(3)]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/6/6-2.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/6/jugemu.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 6-2. 高階関数\n", "\n", "Pythonにおける高階関数について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/howto/functional.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `max`\n", "\n", "例として、関数 **`max`** について考察します。`max` は与えられたリストの要素のうち、最大のものを返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ls = [3,-8,1,0,7,-5]\n", "max(ls)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`max` に **`key`** というキーワード引数として、たとえば関数 `abs` を与えることができます。\n", "(キーワード引数について詳しくは、3-3を参照してください。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "max(ls, key=abs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この場合、各要素に関数 `abs` が適用されて、その結果が最も大きい要素が返ります。\n", "(各要素に `abs` 適用した結果の中の最大値が返るわけではないことに注意してください。)\n", "なお、`abs(x)` は `x` の絶対値を返します。\n", "\n", "この場合、`max` という関数は、関数を引数として受け取っています。\n", "\n", "一般に、関数を引数として受け取ったり返値として返したりする関数を**高階関数**といいます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `sorted`\n", "\n", "**`sorted`** も高階関数で、`max` と同様に **`key`** というキーワード引数を取ります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sorted(ls, key=abs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように、各要素に関数 `abs` を適用した結果によって、各要素をソートします。\n", "\n", "リストを降順にソートするには、次のような関数を用いればよいです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def invert(x):\n", " return -x" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sorted(ls, key=invert)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "なお、リストを降順にソートするには、**`reverse`** というキーワード引数に `True` を指定するという方法もあります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sorted(ls, reverse=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ラムダ式\n", "\n", "上の `invert` のような簡単な関数の場合、\n", "いちいち `def` で定義するのは面倒と思いませんか。\n", "\n", "そのようなときは、**`lambda`** を使った**ラムダ式**(または**無名関数**)を用いることができます。\n", "上の例は、以下のように書くことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sorted(ls, key=lambda x: -x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`lambda x: -x` という式は、`x` をもらって `-x` を返す関数を表します。\n", "`return` は書かないことに注意してください。\n", "\n", "さて、ここまで関数と呼んでいたものは、Pythonでは、オブジェクトの一種に他なりません。\n", "実際に、`abs` や `lambda x: -x` という式の値を調べてみてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "abs" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "lambda x: -x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "したがって、Pythonでは、関数を他の種類のデータ(数やリストや文字列など)と同様に、\n", "関数の引数にしたり、リストの要素にしたり、することができます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## リストからイテラブルへ\n", "\n", "以上の例では、`max` や `sorted` はリストを受け取っていましたが、\n", "リストではなく、タプルでもいいですし、文字列でも構いません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "max((3,-8,1,0,7,-5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sorted((3,-8,1,0,7,-5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "max('hello world')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sorted('hello world')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "すなわち、`max` や `sorted` は、一般にイテラブルを引数に取ることができます。\n", "\n", "イテラブルについては4-2に説明がありましたが、\n", "簡単に言うと、**イテラブル**とはfor文の `in` の後に来ることができるものです。\n", "`max` や `sorted` は、イテラブルの各要素を次々と求めて、\n", "その中の最大値を求めたり、整列した結果をリストとして返したりします。\n", "\n", "以下の例では、`max` にファイルオブジェクトが渡されます。\n", "ファイルオブジェクトはイテレータですので、イテラブルでもあります。\n", "ファイルオブジェクトをfor文の `in` の後に指定すると、\n", "ファイルの各行が文字列として得られます。\n", "以下の例では、`key` として関数 `len` が指定されていますので、\n", "ファイルの中で最も長い行が表示されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('jugemu.txt', 'r', encoding='utf-8') as f:\n", " print(max(f, key=len))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "辞書もイテラブルです。`max` に辞書与えると、最大のキーが返ります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "max({3:10, 5:2, 9:1})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "辞書 `d` が与えられたとき、\n", "最大の値を持つキー(複数個ならばそのいずれか)を返す関数 `max_value_key(d)` を、\n", "`max` を使って定義してください。\n", "\n", "ヒント:辞書 `d` のキー `k` に対して、`k` に対応する値を返す関数は `lambda k: d[k]` という式で表すことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def max_value_key(d):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(max_value_key({3:10, 5:2, 9:1}) == 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `map`\n", "\n", "以下は内包表記の例です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[abs(x) for x in [3,-8,1,0,7,-5]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "リストの各要素に関数 `abs` が適用された結果がリストになります。\n", "\n", "同様のことを、高階関数 **`map`** を用いて行うことができます。\n", "関数 `map` は、2番目の引数としてイテラブルを取ります。1番目の引数は関数です。\n", "例を見ましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "map(abs, [3,-8,1,0,7,-5])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "何が返ったか、よくわからないと思います。\n", "以下のように、`map` の結果をfor文の `in` の後に指定してみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for x in map(abs, [3,-8,1,0,7,-5]):\n", " print(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "すなわち、`map` が返すものは**イテレータ**です。\n", "このイテレータは、2番目の引数のイテラブル(この例ではリスト)の各要素に\n", "関数 `abs` を適用したものを、次々と返すようなイテレータです。\n", "\n", "内包表記を使えば、以下のようにリストにまとめることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[x for x in map(abs, [3,-8,1,0,7,-5])]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数 `list` をイテレータに適用してもよいです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list(map(abs, [3,-8,1,0,7,-5]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "しかし、これでは、イテレータがどのように動くのか、よくわからないと思います。\n", "\n", "以下では、呼ばれるたびにメッセージを出力する関数 `abs1` を用います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def abs1(x):\n", " print('abs called on', x)\n", " return abs(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "it = map(abs1, [3,-8,1,0,7,-5])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このように、`map` がイテレータを返した時点では、各要素に対する計算は何も行われません。\n", "\n", "このイテレータに `next` を適用するとどうなるか、見てください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "next(it)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "next(it)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "関数 `next` が呼ばれるたびに、次の要素を求める計算が行われていることがわかります。\n", "\n", "イテレータはイテラブルですから、`map` の結果にさらに `map` を適用することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list(map(lambda x: x+1, map(abs, [3,-8,1,0,7,-5])))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`lambda x: x+1` は、`x` をもらって `x+1` を返す関数です。\n", "すなわち、引数に `1` を足した結果を返します。\n", "\n", "関数 `sum` は、`max` と同様に、イテラブルを受け取って、その要素の総和を返します。\n", "したがって、`map` が返したイテレータに対しても適用できます。\n", "(イテレータをリストに変換する必要はありません。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sum(map(lambda x: x+1, map(abs, [3,-8,1,0,7,-5])))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "数のリストが与えられたとき、その要素の絶対値の最大値を返す関数 `max_abs` を、\n", "`map` と `max` を使って定義してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def max_abs(ln):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(max_abs([3,-8,1,0,7,-5]) == 8)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `filter`\n", "\n", "関数 **`filter`** もイテラブルをもらってイテレータを返します。\n", "最初の引数としては、真理値を返す関数を指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def pos(x):\n", " if x>0:\n", " return True\n", " else:\n", " return False" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この関数 `pos` は、引数が正ならば `True`、そうでなければ `False` を返します。\n", "\n", "すると、以下のように、`filter` は `pos` を適用すると `True` が返る要素のみからなるイテレータを返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list(filter(pos, [3,-8,1,0,7,-5]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`filter` は、条件付き内包表記に対応しています。\n", "同じ計算を以下のようにして行うことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "[x for x in [3,-8,1,0,7,-5] if pos(x)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "数のリスト `ln` と数 `n` を受け取って、`ln` の要素のうち、`n` より大きい個数を返す関数\n", "`number_of_big_numbers(ln, n)` を、for文やwhile文を用いずに、`filter` を用いて定義してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def number_of_big_numbers(ln, n):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(number_of_big_numbers([10, 0, 7, 1, 5, 2, 9], 5) == 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "ファイル名 `file` と整数 `n` を受け取って、そのファイルをオープンし、\n", "(改行文字も含めて)長さが `n` より長い行の数を返す関数 `number_of_long_lines(file,n)` を定義してください。\n", "(ファイルは `encoding='utf-8'` でオープンしてください。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def number_of_long_lines(file, n):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(number_of_long_lines('jugemu.txt', 10) == 6)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def max_value_key(d):\n", " return max(d, key=lambda k: d[k])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def max_abs(ln):\n", " return max(map(abs, ln))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def number_of_big_numbers(ln, n):\n", " return sum(map(lambda x: 1, filter(lambda x: x>n, ln)))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def number_of_long_lines(file, n):\n", " with open(file, 'r', encoding='utf-8') as f:\n", " return sum(map(lambda x: 1, filter(lambda x: len(x)>n, f)))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/6/6-3.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/6/jugemu.txt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 6-3. クラス\n", "\n", "Pythonにおけるオブジェクト指向プログラミングのうち、クラスを定義する方法について簡単に説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/classes.html\n", "- https://docs.python.org/ja/3/reference/datamodel.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## クラス定義\n", "\n", "Pythonでは全てのデータはオブジェクトなのですが、\n", "以下では特に、クラス定義によって作成されたクラスを型とするデータを扱います。\n", "このようなデータは、**オブジェクト指向プログラミング**における典型的な**オブジェクト**です。\n", "そこで以下では、オブジェクトという用語をもっぱら使います。\n", "\n", "4-1で見たように、ファイルオブジェクトに対して `readline()` というメソッドを呼び出すと、\n", "ファイルの行が文字列として次々と返されます。\n", "ここでは、ファイルオブジェクトのようなオブジェクトで、\n", "`readline()` というメソッドが呼び出されると、常に `'Hello.\\n'` という文字列を返すようなものを作ってみましょう。\n", "\n", "そのためには、新しいクラスを定義します。\n", "**クラス**とは、オブジェクトの種類を意味します。\n", "新しいクラスを定義すると、そのクラスに属するオブジェクトを作ることができるようになります。\n", "それらのオブジェクトの型は、その新しいクラスになります。\n", "\n", "ここでは、ずっと `'Hello.\\n'` を返し続けるので、\n", "`HelloForEver` という名前を持つクラスを定義しましょう。\n", "そして、`HelloForEver` というクラスを型とするオブジェクトを作ります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class HelloForEver:\n", " def readline(self):\n", " return 'Hello.\\n'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一般にクラス定義は、以下のような形をしています。\n", "\n", "---\n", "```Python\n", "class クラス名:\n", " def メソッド名(self, 引数, ...):\n", " 実行文\n", " def メソッド名(self, 引数, ...):\n", " 実行文\n", " ...\n", "```\n", "---\n", "メソッド定義は関数定義と同じ形をしていますが、\n", "クラス定義の中に入っています。\n", "メソッド定義において、その最初の引数には慣例として `self` という名前を付けます。\n", "この引数には、メソッドが呼び出されたオブジェクト自身が渡されます。\n", "\n", "上の例では、`readline` というメソッドが1つ定義されています。\n", "\n", "以下のようにして、このクラスのオブジェクトを作ることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = HelloForEver()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`HelloForEver` を型とする新しいオブジェクトが作られて変数 `f` の値となります。\n", "\n", "一般に、オブジェクトの生成は、\n", "\n", "---\n", "```Python\n", "クラス名(式, ...)\n", "```\n", "---\n", "という式で行います。このようにオブジェクトを生成する式は**コンストラクタ**と呼ばれます。\n", "なお、上の例では、括弧の中に式は1つもありません。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このようにして作ったオブジェクトの型を確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`__main__.HelloForEver` と表示されたでしょう。\n", "`__main__` は、ノートブックの式が評価されているモジュールを指すので、\n", "このオブジェクトの型が、上で定義した `HelloForEver` クラスであることがわかります。\n", "クラスのコンストラクタによって生成されたオブジェクトを、そのクラスの**インスタンス**と言います。\n", "上のオブジェクトは `HelloForEver` クラスのインスタンスです。\n", "\n", "オブジェクトそのものは以下のように表示されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このオブジェクトに対して、`readline` というメソッドを呼び出すことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この例では、`f` という変数に入っているオブジェクトが `self` という引数に渡されて、\n", "`readline` の本体である以下の文が実行されました。\n", "\n", "---\n", "```Python\n", " return 'Hello.\\n'\n", "```\n", "---\n", "(この例では `self` は参照されていません。)\n", "\n", "何回やっても同じです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 初期化と属性\n", "\n", "以下の例では、初期化のメソッドが定義され、オブジェクトに属性が与えられます。\n", "\n", "**初期化**のメソッドは **`__init__`** という名前を持ち、\n", "オブジェクトが作られたときに自動的に呼び出されます。\n", "`__init__` の引数は、オブジェクト自身と、クラス名の後に与えられる式の値です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class HelloFile:\n", " def __init__(self, n):\n", " self.n = n\n", " def readline(self):\n", " if self.n == 0:\n", " return ''\n", " self.n = self.n - 1\n", " return 'Hello.\\n'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この例では、以下のようにしてオブジェクトが作られます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = HelloFile(3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "すると、`HelloFile` を型とする新しいオブジェクトが作られて、\n", "そのオブジェクト自身が `self` に、`3` が `n` に渡されて、\n", "`self.n = n` という文が実行されます。\n", "\n", "`self.n` という式は、このオブジェクトの `n` という名前の属性を表します。\n", "\n", "一般に、`class` の構文によって定義されたクラスを型とするオブジェクトは、\n", "属性を持つことができます。\n", "**属性**とは、個々のオブジェクトごとに記録される値であり、\n", "オブジェクト内の変数と考えられます。\n", "オブジェクトの属性は、オブジェクトに対してその**属性名**を指定して、参照したり設定したりできます。\n", "オブジェクトの属性は、`self.属性名` という式で参照されます。\n", "`self.属性名` を代入文の左辺に書けば、属性を設定することができます。\n", "\n", "`self.n = n` のうち、`self.` の次の `n` は属性を表し、\n", "右辺の `n` は、`__init__` メソッドの引数を表していますので、\n", "混同しないようにしてください。\n", "\n", "この例では、新しく作られたオブジェクトの `n` という属性が、引数 `n` の値である `3` に設定されます。\n", "\n", "`readline` メソッドは以下のように定義されています。\n", "\n", "---\n", "```Python\n", " def readline(self):\n", " if self.n == 0:\n", " return ''\n", " self.n = self.n - 1\n", " return 'Hello.\\n'\n", "```\n", "---\n", "オブジェクトの属性 `n` を参照して、それが `0` ならば空文字列を返します。\n", "そうでなければ、属性 `n` を `1` 減らしてから文字列 `'Hello.\\n'` を返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "変数 `f` の値であるオブジェクトの属性 `n` は、`f.n` という式によって参照できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここでは詳しく説明しませんが、オブジェクトのメソッドも属性の一種です。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 継承\n", "\n", "**継承**は、既存のクラスをもとにして、変更部分だけを与えることにより、\n", "新たなクラスを定義する機能です。\n", "\n", "以下の例では、`HelloForEver` をもとにして `HelloFile` を定義しています。\n", "一般に、新しく定義されるクラスを**子クラス**、そのもとになるクラスを**親クラス**と言います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class HelloFile(HelloForEver):\n", " def __init__(self, n):\n", " self.n = n\n", " def readline(self):\n", " if self.n == 0:\n", " return ''\n", " self.n = self.n - 1\n", " return super().readline()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここでは、`__init__` と `readline` を新たに定義しています。\n", "\n", "`HelloForEver` にも `readline` があります。\n", "こちらの `readline` は、`super().readline()` という式で呼び出すことができます。\n", "**`super()`** は、子クラスのオブジェクトに対して親クラスのメソッドを呼び出すための構文です。\n", "実際に、`HelloFile` の `readline` の中で、\n", "`HelloForEver` の `readline` を呼び出しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = HelloFile(3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.readline()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 特殊メソッド\n", "\n", "Pythonでは、**特殊メソッド**と呼ばれるメソッドが多数あります。\n", "これらのメソッドの名前は `__` で始まり `__` で終わります。\n", "\n", "クラス定義の中で特殊メソッドを定義すると、そのクラスのオブジェクトに対して、\n", "その特殊メソッドに対応する機能が付与されます。\n", "初期化メソッド `__init__` も特殊メソッドですが、\n", "以下のクラス `HelloFileIterator` では、**`__iter__`** と **`__next__`** という特殊メソッドが定義されています。\n", "このクラスは、`HelloFile` を継承して定義されています。\n", "\n", "`__iter__` メソッドは、オブジェクトに対して関数 `iter` が適用されたときに呼び出されます。\n", "`__iter__` メソッドの値が関数 `iter` の値となります。\n", "以下の例では、`__iter__` はオブジェクト自身を返しています。\n", "したがって、オブジェクトに `iter` が適用されると、オブジェクト自身が返ります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class HelloFileIterator(HelloFile):\n", " def __iter__(self):\n", " return self\n", " def __next__(self):\n", " line = self.readline()\n", " if line == '':\n", " raise StopIteration\n", " return line" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = HelloFileIterator(3)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(f is iter(f))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上の例で、`iter(f)` として関数 `iter` を呼び出すと、\n", "`f.__iter__()` としてメソッド `__iter__` が `f` に対して呼び出され、\n", "その結果が `iter(f)` の値となります。\n", "したがって、`iter(f)` は `f` と同じ値を返します。\n", "\n", "`__next__` メソッドも、オブジェクトに対して関数 `next` が適用されたときに呼び出されます。\n", "`__next__` メソッドの値が `next` の値となります。\n", "\n", "上の例では、`self.readline()` として、オブジェクト自身に対してメソッド `readline` を呼び出しています。\n", "その値が空文字列ならば、\n", "\n", "---\n", "```Python\n", " raise StopIteration\n", "```\n", "---\n", "という文を実行して、**`StopIteration`** というエラーを投げます。\n", "実は、このエラーは、for文が捕まえて繰り返しを止める効果を持ちます。\n", "なお、**`raise`** は強制的にエラーを発生させる構文です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for line in f:\n", " print(line)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "4-2で説明したように、上のfor文では、\n", "まず `f` のオブジェクトに対して関数 `iter` が適用されます。\n", "すると `f` のオブジェクト自身が返ります。\n", "そして、このオブジェクトに対して関数 `next` が繰り返し適用されて、\n", "その結果が変数 `line` の値となります。\n", "`StopIteration` のエラーが検知されると、for文が終了します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 継承による振舞いの改変\n", "\n", "上で示された、`HelloFileIterator` の `__next__` メソッドでは、`self.readline()` というメソッド呼び出しがありました。\n", "上の例の振舞いから、そのメソッド呼び出しは、`HelloFileIterator` には `readline` メソッドが定義されていないので、親の `HelloFile` を見に行って、そこで定義された `readline` メソッドが使われたように見えます。\n", "しかし、それは正確ではありません。\n", "\n", "`self.readline()` では、その呼び出し場所がどこであるかに関わらず、常にオブジェクト `self` の中のメソッドを探索します。\n", "そして、継承があるために、`__next__(self)` における `self` が、`HelloFileIterator` のインスタンスであるとも限りません。\n", "次を見てみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class EmptyFile(HelloFileIterator):\n", " def readline(self):\n", " return ''\n", " \n", "f = EmptyFile(3)\n", "next(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "コンストラクタに `3` を与えているので、`HelloFileIterator` と同様に `next` を3回適用できてもよさそうですが、即座に `StopIteration` が生じました。\n", "これは、`__next__(self)` における `self` が、`EmptyFile` のインスタンスであり、`self.readline()` が常に `''` を返すからです。\n", "\n", "このように、継承は、メソッドの部分的な再定義を通じて、再定義されたメソッドを呼び出しているメソッドの振舞いを、間接的に改変することを可能にします。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "`'Hello.\\n'` ではなくて、初期時に指定された文字列を繰り返し返すように、\n", "新たなクラス `StringFileIterator` を定義してください。\n", "\n", "`StringFileIterator` は `HelloFileIterator` を継承し、\n", "初期化メソッドには、文字列と回数を指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class StringFileIterator(HelloFileIterator):\n", " def __init__(self, s, n):\n", " ...\n", " ... " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "f = StringFileIterator('abc', 3)\n", "print(list(f) == ['abc','abc','abc'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲with文への対応\n", "\n", "ここでは詳しく説明しませんが、さらに特殊メソッドである **`__enter__`** と **`__exit__`** を定義すると、\n", "**with文**にも対応できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class HelloFileIterator(HelloFile):\n", " def __enter__(self):\n", " return self\n", " def __exit__(self,exception_type,exception_value,traceback):\n", " pass\n", " def __next__(self):\n", " line = self.readline()\n", " if line == '':\n", " raise StopIteration\n", " return line\n", " def __iter__(self):\n", " return self" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with HelloFileIterator(3) as f:\n", " for line in f:\n", " print(line)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class StringFileIterator(HelloFileIterator):\n", " def __init__(self, s, n):\n", " self.s = s\n", " self.n = n\n", " def readline(self):\n", " if self.n == 0:\n", " return ''\n", " self.n = self.n - 1\n", " return self.s" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/6/jugemu.txt ================================================ 寿限無、寿限無、 五劫の擦り切れ、 海砂利水魚の、 水行末・雲来末・風来末、 食う寝る処に住む処、 やぶら小路の藪柑子、 パイポ・パイポ・パイポのシューリンガン、 シューリンガンのグーリンダイ、 グーリンダイのポンポコピーのポンポコナーの、 長久命の長助 ================================================ FILE: colab/7/7-1.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/7/iris.csv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 7-1. pandasライブラリ\n", "\n", "pandasライブラリについて説明します。\n", "\n", "参考\n", "\n", "- http://pandas.pydata.org/pandas-docs/stable/getting_started/index.html\n", "- http://pandas.pydata.org/pandas-docs/stable/\n", "\n", "**pandas**ライブラリにはデータ分析作業を支援するためのモジュールが含まれています。以下では、pandasライブラリのモジュールの基本的な使い方について説明します。\n", "\n", "pandasライブラリを使用するには、まず `pandas` モジュールをインポートします。慣例として、同モジュールを `pd` と別名をつけてコードの中で使用します。データの生成に用いるため、ここでは `numpy` モジュールも併せてインポートします。\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## シリーズとデータフレーム\n", "`pandas` モジュールは、リスト、配列や辞書などのデータを**シリーズ** (**`Series`**) あるいは**データフレーム** (**`DataFrame`**) のオブジェクトとして保持します。シリーズは列、データフレームは複数の列で構成されます。シリーズやデータフレームの行は**インデックス** `index` で管理され、インデックスには `0` から始まる番号、または任意のラベルが付けられています。インデックスが番号の場合は、シリーズやデータフレームはそれぞれNumPyの配列、2次元配列とみなすことができます。また、インデックスがラベルの場合は、ラベルをキー、各行を値とした辞書としてシリーズやデータフレームをみなすことができます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## シリーズ (`Series`) の作成\n", "シリーズのオブジェクトは、以下のように、リスト、配列や辞書から作成することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# リストからシリーズの作成\n", "s1 = pd.Series([0,1,2])\n", "print(s1)\n", "\n", "# 配列からシリーズの作成\n", "s2 = pd.Series(np.random.rand(3))\n", "print(s2)\n", "\n", "# 辞書からシリーズの作成\n", "s3 = pd.Series({0:'boo',1:'foo',2:'woo'})\n", "print(s3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下では、シリーズ(列)より一般的なデータフレームの操作と機能について説明していきますが、データフレームオブジェクトの多くの操作や機能はシリーズオブジェクトにも適用できます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## データフレーム (`DataFrame`) の作成\n", "データフレームのオブジェクトは、以下のように、リスト、配列や辞書から作成することができます。行のラベルは、`DataFrame` の `index` 引数で指定できますが、以下のデータフレーム作成の例、`d2`, `d3`、 では同インデックスを省略しているため、`0` から始まるインデックス番号がラベルとして行に自動的に付けられます。列のラベルは `columns` 引数で指定します。辞書からデータフレームを作成する際は、`columns` 引数で列の順番を指定することになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 多次元リストからデータフレームの作成\n", "d1 = pd.DataFrame([[0,1,2],[3,4,5],[6,7,8],[9,10,11]], index=[10,11,12,13], columns=['c1','c2','c3'])\n", "print(d1)\n", "\n", "# 多次元配列からデータフレームの作成\n", "d2 = pd.DataFrame(np.random.rand(12).reshape(4,3), columns=['c1','c2','c3'])\n", "print(d2)\n", "\n", "# 辞書からデータフレームの作成\n", "d3 = pd.DataFrame({'Initial':['B','F','W'], 'Name':['boo', 'foo', 'woo']}, columns=['Name','Initial'])\n", "print(d3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CSVファイルからのデータフレームの作成\n", "`pandas` モジュールの **`read_csv()`** 関数を用いて、以下のように**CSVファイル**を読み込んで、データフレームのオブジェクトを作成することができます。`read_csv()` 関数の `encoding` 引数にはファイルの文字コードを指定します。CSVファイル `iris.csv` には、以下のようにアヤメの種類 (species) と花弁 (petal)・がく片 (sepal) の長さ (length) と幅 (width) のデータが含まれています。\n", "```Python\n", "sepal_length, sepal_width, petal_length, petal_width, species\n", "5.1, 3.5, 1.4, 0.2, setosa\n", "4.9, 3.0, 1.4, 0.2, setosa\n", "4.7, 3.2, 1.3, 0.2, setosa\n", "...\n", "```\n", "**`head()`** メソッドを使うとデータフレームの先頭の複数行を表示させることができます。引数には表示させたい行数を指定し、行数を指定しない場合は、5行分のデータが表示されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# CSVファイルの読み込み\n", "iris_d = pd.read_csv('iris.csv')\n", "\n", "# 先頭10行のデータを表示\n", "iris_d.head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "データフレームオブジェクトの **`index`** 属性により、データフレームのインデックスの情報が確認できます。`len()` 関数を用いると、データフレームの行数が取得できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(iris_d.index) #インデックスの情報\n", "len(iris_d.index) #インデックスの長さ" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## データの参照\n", "シリーズやデータフレームでは、行の位置(行は `0` から始まります)を**スライス**として指定することで任意の行を抽出することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームの先頭5行のデータ\n", "iris_d[:5]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームの終端5行のデータ\n", "iris_d[-5:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "データフレームから任意の列を抽出するには、`DataFrame.列名` のように、データフレームオブジェクトに `.` で列名をつなげることで、その列を指定してシリーズオブジェクトとして抽出することができます。なお、列名を文字列として、`DataFrame['列名']` のように添字指定しても同様です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームの'species'の列の先頭10行のデータ\n", "iris_d['species'].head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "データフレームの添字として、列名のリストを指定すると複数の列をデータフレームオブジェクトとして抽出することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームの'sepal_length'とspecies'の列の先頭10行のデータ\n", "iris_d[['sepal_length','species']].head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `iloc` と `loc`\n", "データフレームオブジェクトの **`iloc`** 属性を用いると、NumPyの多次元配列のスライスと同様に、行と列の位置を指定して任意の行と列を抽出することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームの2行のデータ\n", "iris_d.iloc[1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームの2行,2列目のデータ\n", "iris_d.iloc[1, 1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームの1から5行目と1から2列目のデータ\n", "iris_d.iloc[0:5, 0:2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "データフレームオブジェクトの **`loc`** 属性を用いると、抽出したい行のインデックス・ラベルや列のラベルを指定して任意の行と列を抽出することができます。複数のラベルはリストで指定します。行のインデックスは各行に割り当てられた番号で、`iloc` で指定する行の位置とは必ずしも一致しないことに注意してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームの行インデックス5のデータ\n", "iris_d.loc[5]" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームの行インデックス5と'sepal_length'と列のデータ\n", "iris_d.loc[5, 'sepal_length']" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームの行インデックス1から5と'sepal_length'とspecies'の列のデータ\n", "iris_d.loc[1:5, ['sepal_length','species']]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## データの条件取り出し\n", "データフレームの列の指定と併せて条件を指定することで、条件にあった行からなるデータフレームを抽出することができます。NumPyの多次元配列の**真理値配列によるインデックスアクセス**と同様に、条件式のブール演算では、`and`, `or`, `not` の代わりに `&`, `|`, `~` を用います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームの'sepal_length'列の値が7より大きく、'species'列の値が3より小さいデータ\n", "iris_d[(iris_d['sepal_length'] > 7.0) & (iris_d['sepal_width'] < 3.0)]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 列の追加と削除\n", "データフレームに列を追加する場合は、以下のように、追加したい新たな列名を指定し、値を代入すると新たな列を追加できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームに'mycolumn'という列を追加\n", "iris_d['mycolumn']=np.random.rand(len(iris_d.index))\n", "iris_d.head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`del`** 文を用いると、以下のようにデータフレームから任意の列を削除できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームから'mycolumn'という列を削除\n", "del iris_d['mycolumn']\n", "iris_d.head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`assign()`** メソッドを用いると、追加したい列名とその値を指定することで、以下のように新たな列を追加したデータフレームを新たに作成することができます。この際、元のデータフレームは変更されないことに注意してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームに'mycolumn'という列を追加し新しいデータフレームを作成\n", "myiris1 = iris_d.assign(mycolumn=np.random.rand(len(iris_d.index)))\n", "myiris1.head(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`drop()`** メソッドを用いると、削除したい列名を指定することで、以下のように任意の列を削除したデータフレームを新たに作成することができます。列を削除する場合は、**`axis`** 引数に `1` を指定します。この際、元のデータフレームは変更されないことに注意してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームから'mycolumn'という列を削除し、新しいデータフレームを作成\n", "myiris2 = myiris1.drop('mycolumn',axis=1)\n", "myiris2.head(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 行の追加と削除\n", "`pandas` モジュールの **`concat()`** 関数を用いると、データフレームに新たな行を追加することができます。以下では、`iris_d` データフレームの最終行に新たな行を追加しています。`ignore_index` 引数を `True` にすると追加した行に新たなインデックス番号がつけられます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 追加する行のデータフレーム\n", "row = pd.DataFrame([[1,1,1,1, 'setosa']], columns=iris_d.columns)\n", "\n", "# データフレームに行を追加し新しいデータフレームを作成\n", "myiris4 = pd.concat([iris_d, row], ignore_index=True)\n", "myiris4[-2:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`drop()`** メソッドを用いると、行のインデックスまたはラベルを指定することで行を削除することもできます。このときに、`axis` 引数は省略することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# データフレームから行インデックス150の行を削除し、新しいデータフレームを作成\n", "myiris4 = myiris4.drop(150)\n", "myiris4[-2:]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## データの並び替え\n", "データフレームオブジェクトの **`sort_index()`** メソッドで、データフレームのインデックスに基づくソートができます。また、**`sort_values()`** メソッドで、任意の列の値によるソートができます。列は複数指定することもできます。いずれのメソッドでも、**`inplace`** 引数により、ソートにより新しいデータフレームを作成する (`False`) か、元のデータフレームを更新する (`True`) を指定できます。デフォルトは `inplace` は `False` になっており、これらのメソッドは新しいデータフレームを作成します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# iris_dデータフレームの4つ列の値に基づいて昇順にソート\n", "sorted_iris = iris_d.sort_values(['sepal_length', 'sepal_width', 'petal_length', 'petal_width'])\n", "sorted_iris.head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "列の値で降順にソートする場合は、`sort_values()` メソッドの **`ascending`** 引数を `False` にしてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# iris_dデータフレームの4つ列の値に基づいて降順にソート\n", "sorted_iris = iris_d.sort_values(['sepal_length', 'sepal_width', 'petal_length', 'petal_width'],ascending=False)\n", "sorted_iris.head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## データの統計量\n", "データフレームオブジェクトの **`describe()`** メソッドで、データフレームの各列の要約統計量を求めることができます。要約統計量には平均、標準偏差、最大値、最小値などが含まれます。その他の統計量を求める `pandas` モジュールのメソッドは以下を参照してください。\n", "\n", "[pandasでの統計量計算](https://pandas.pydata.org/pandas-docs/stable/reference/frame.html#computations-descriptive-stats)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# iris_dデータフレームの各数値列の要約統計量を表示\n", "iris_d.describe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲データの連結\n", "`pandas` モジュールの **`concat()`** 関数を用いると、データフレームを連結して新たなデータフレームを作成することができます。以下では、`iris_d` データフレームの先頭5行と最終5行を連結して、新しいデータフレームを作成しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# iris_dデータフレームの先頭5行と最終5行を連結\n", "concat_iris = pd.concat([iris_d[:5],iris_d[-5:]])\n", "concat_iris" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`concat()` 関数の `axis` 引数に `1` を指定すると、以下のように、データフレームを列方向に連結することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# iris_dデータフレームの'sepal_length'列と'species'列を連結\n", "sepal_len = pd.concat([iris_d.loc[:, ['sepal_length']],iris_d.loc[:, ['species']]], axis=1)\n", "sepal_len.head(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲データの結合\n", "`pandas` モジュールの **`merge()`** 関数を用いると、任意の列の値をキーとして異なるデータフレームを結合することができます。結合のキーとする列名は **`on`** 引数で指定します。以下では、`species` の列の値をキーに、2つのデータフレーム、`sepal_len`, `sepal_wid`、を結合して新しいデータフレーム `sepal` を作成しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 'sepal_length'と'species'列からなる3行のデータ\n", "sepal_len = pd.concat([iris_d.loc[[0,51,101],['sepal_length']],iris_d.loc[[0,51,101], ['species']]], axis=1)\n", "# 'sepal_width'と'species'列からなる3行のデータ\n", "sepal_wid = pd.concat([iris_d.loc[[0,51,101],['sepal_width']],iris_d.loc[[0,51,101], ['species']]], axis=1)\n", "\n", "# sepal_lenとsepal_widを'species'をキーにして結合\n", "sepal = pd.merge(sepal_len, sepal_wid, on='species')\n", "sepal" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲データのグループ化\n", "データフレームオブジェクトの **`groupby()`** メソッドを使うと、データフレームの任意の列の値に基づいて、同じ値を持つ行をグループにまとめることができます。列は複数指定することもできます。`groupby()` メソッドを適用するとグループ化オブジェクト (`DataFrameGroupBy`) が作成されますが、データフレームと同様の操作を多く適用することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# iris_dデータフレームの'species'の値で行をグループ化\n", "iris_d.groupby('species')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# グループごとの先頭5行を表示\n", "iris_d.groupby('species').head(5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# グループごとの'sepal_length'列,'sepal_width'列の値の平均を表示\n", "iris_d.groupby('species')[['sepal_length','sepal_width']].mean()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ▲欠損値、時系列データの処理\n", "pandasでは、データ分析における欠損値、時系列データの処理を支援するための便利な機能が提供されています。詳細は以下を参照してください。\n", "\n", "[欠損値の処理](https://pandas.pydata.org/pandas-docs/stable/missing_data.html#missing-data)\n", "\n", "[時系列データの処理](https://pandas.pydata.org/pandas-docs/stable/timeseries.html)" ] } ], "metadata": { "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.12.4" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: colab/7/7-2.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/7/iris.csv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 7-2. scikit-learnライブラリ\n", "\n", "scikit-learnライブラリについて説明します。\n", "\n", "参考\n", "\n", "- https://scikit-learn.org/stable/tutorial/index.html\n", "- https://scikit-learn.org/stable/getting_started.html\n", "\n", "機械学習の各手法の詳細については以下を参考にしてください\n", "\n", "- https://elf-c.he.u-tokyo.ac.jp/courses/364 (線形回帰)\n", "- https://elf-c.he.u-tokyo.ac.jp/courses/365 (ロジスティック回帰)\n", "- https://elf-c.he.u-tokyo.ac.jp/courses/360 (クラスタリング)\n", "- https://elf-c.he.u-tokyo.ac.jp/courses/363 (次元削減(主成分分析))\n", "\n", "**scikit-learn**ライブラリには分類、回帰、クラスタリング、次元削減、前処理、モデル選択などの機械学習の処理を行うためのモジュールが含まれています。以下では、scikit-learnライブラリのモジュールの基本的な使い方について説明します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 機械学習について\n", "**機械学習**では、観察されたデータをよく表すようにモデルのパラメータの調整を行います。パラメータを調整することでモデルをデータに適合させるので、「学習」と呼ばれます。学習されたモデルを使って、新たに観測されたデータに対して予測を行うことが可能になります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 教師あり学習\n", "機械学習において、観測されたデータの特徴(特徴量)に対して、そのデータに関するラベルが存在する時、**教師あり学習**と呼びます。教師あり学習では、ラベルを教師として、データからそのラベルを予測するようなモデルを学習することになります。この時、ラベルが連続値であれば回帰、ラベルが離散値であれば分類の問題となります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 教師なし学習\n", "ラベルが存在せず、観測されたデータの特徴のみからそのデータセットの構造やパターンをよく表すようなモデルを学習することを**教師なし学習**と呼びます。クラスタリングや次元削減は教師なし学習です。クラスタリングでは、観測されたデータをクラスタと呼ばれる集合にグループ分けします。次元削減では、データの特徴をより簡潔に(低い次元で)表現します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## データ\n", "機械学習に用いるデータセットは、データフレームあるいは2次元の配列として表すことができます。行はデータセットの個々のデータを表し、列はデータが持つ特徴を表します。以下では、例として `pandas` モジュールの説明で用いたアイリスデータセットを表示しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "iris = pd.read_csv('iris.csv')\n", "iris.head(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "データセットの各行は1つの花のデータに対応しており、行数はデータセットの花データの総数を表します。また、1列目から4列目までの各列は花の特徴(特徴量)に対応しています。scikit-learnでは、このデータと**特徴量**からなる2次元配列(行列)をNumPy配列または `pandas` のデータフレームに格納し、入力データとして処理します。5列目は、教師あり学習におけるデータのラベルに対応しており、ここでは各花データの花の種類(全部で3種類)を表しています。ラベルは通常1次元でデータの数だけの長さを持ち、NumPy配列または `pandas` のシリーズに格納します。先に述べた通り、ラベルが連続値であれば回帰、ラベルが離散値であれば分類の問題となります。機械学習では、特徴量からこのラベルを予測することになります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "アイリスデータセットはscikit-learnが持つデータセットにも含まれており、`load_iris` 関数によりアイリスデータセットの特徴量データとラベルデータを以下のようにNumPyの配列として取得することもできます。この時、ラベルは数値 (`0`, `1`, `2`) に置き換えられています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from sklearn.datasets import load_iris\n", "iris = load_iris()\n", "X_iris = iris.data\n", "y_iris = iris.target" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## モデル学習の基礎\n", "\n", "scikit-learnでは、以下の手順でデータからモデルの学習を行います。\n", "\n", "- 使用するモデルのクラスの選択\n", "- モデルのハイパーパラメータの選択とインスタンス化\n", "- データの準備\n", " - 教師あり学習では、特徴量データとラベルデータを準備\n", " - 教師あり学習では、特徴量・ラベルデータをモデル学習用の訓練データとモデル評価用のテストデータに分ける\n", " - 教師なし学習では、特徴量データを準備\n", "- モデルをデータに適合(`fit()` メソッド)\n", "- モデルの評価\n", " - 教師あり学習では、`predict()` メソッドを用いてテストデータの特徴量データからラベルデータを予測しその精度の評価を行う\n", " - 教師なし学習では、`transform()` または `predict()` メソッドを用いて特徴量データのクラスタリングや次元削減などを行う\n", "\n", "## 教師あり学習・分類の例\n", "\n", "以下では、アイリスデータセットを用いて花の4つの特徴から3つの花の種類を分類する手続きを示しています。scikit-learnでは、全てのモデルはPythonクラスとして実装されており、ここでは分類を行うモデルの1つである**ロジスティック回帰** (**`LogisticRegression`**) クラスをインポートしています。\n", "\n", "[LogisticRegressionクラス](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html)\n", "\n", "`train_test_split()` はデータセットを訓練データとテストデータに分割するための関数、`accuracy_score()` はモデルの予測精度を評価するための関数です。\n", "\n", "特徴量データ (`X_irist`) とラベルデータ (`y_iris`) からなるデータセットを訓練データ (`X_train`, `y_train`) とテストデータ (`X_test`, `y_test`) に分割しています。ここでは、`train_test_split()` 関数の `test_size` 引数にデータセットの30%をテストデータとすることを指定しています。また、`stratify` 引数にラベルデータを指定することで、訓練データとテストデータ、それぞれでラベルの分布が同じになるようにしています。\n", "\n", "ロジスティック回帰クラスのインスタンスを作成し、**`fit()`** メソッドによりモデルを訓練データに適合させています。そして、**`predict()`** メソッドを用いてテストデータの特徴量データ (`X_test`) のラベルを予測し、`accuracy_score()` 関数で実際のラベルデータ (`y_test`) と比較して予測精度の評価を行なっています。97%の精度で花の4つの特徴から3つの花の種類を分類できていることがわかります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from sklearn.linear_model import LogisticRegression\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.metrics import accuracy_score\n", "from sklearn.datasets import load_iris\n", "\n", "iris = load_iris()\n", "X_iris = iris.data # 特徴量データ\n", "y_iris = iris.target # ラベルデータ\n", "\n", "# 訓練データとテストデータに分割\n", "X_train, X_test, y_train, y_test = train_test_split(X_iris, y_iris, test_size=0.3, random_state=1, stratify=y_iris)\n", "\n", "# ロジスティック回帰モデル:solver引数には最適化手法を指定\n", "model=LogisticRegression(solver='lbfgs')\n", "\n", "model.fit(X_train, y_train) # モデルを訓練データに適合\n", "y_predicted=model.predict(X_test) # テストデータでラベルを予測\n", "accuracy_score(y_test, y_predicted) # 予測精度(accuracy)の評価" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "アイリスデータセットの2つの特徴量、`petal_length` と ` petal_width`、から2つの花の種類、`versicolor` か `virginica`、を予測するモデルをロジスティック回帰を用いて学習し、その予測精度を評価してください。以下では `pandas` データフレームの `values` 属性を用いてNumPy配列を取得しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from sklearn.linear_model import LogisticRegression\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.metrics import accuracy_score\n", "\n", "iris = pd.read_csv('iris.csv')\n", "iris2=iris[(iris['species']=='versicolor')|(iris['species']=='virginica')]\n", "X_iris=iris2[['petal_length','petal_width']].values\n", "y_iris=iris2['species'].values\n", "\n", "### your code here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上記のコードが完成したら、以下のコードを実行して、2つの特徴量、`petal_length` と `petal_width`、から2つの花の種類、`versicolor` か `virginica`、を分類するための決定境界を可視化してみてください。`model` は上記の練習で学習されたモデルとします。決定境界は、学習の結果得られた、特徴量の空間においてラベル(クラス)間を分離する境界を表しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", " \n", "w2 = model.coef_[0,1]\n", "w1 = model.coef_[0,0]\n", "w0 = model.intercept_[0]\n", "\n", "line=np.linspace(3,7)\n", "plt.plot(line, -(w1*line+w0)/w2)\n", "y_c = (y_iris=='versicolor').astype(int)\n", "plt.scatter(iris2['petal_length'],iris2['petal_width'],c=y_c);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 教師あり学習・回帰の例\n", "以下では、アイリスデータセットを用いて花の特徴の1つ、`petal_length`、からもう1つの特徴、`petal_width`、を回帰する手続きを示しています。この時、`petal_length` は特徴量、`petal_width` は連続値のラベルとなっています。まず、`matplotlib` の散布図を用いて `petal_length` と `petal_width` の関係を可視化してみましょう。関係があるといえそうでしょうか。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "iris = pd.read_csv('iris.csv')\n", "X=iris[['petal_length']].values\n", "y=iris['petal_width'].values\n", "plt.scatter(X,y);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次に、回帰を行うモデルの1つである**線形回帰** (**`LinearRegression`**) クラスをインポートしています。\n", "\n", "[LinearRegressionクラス](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html)\n", "\n", "`mean_squared_error()` は平均二乗誤差によりモデルの予測精度を評価するための関数です。\n", "\n", "データセットを訓練データ (`X_train`, `y_train`) とテストデータ (`X_test`, `y_test`) に分割し、線形回帰クラスのインスタンスの `fit()` メソッドによりモデルを訓練データに適合させています。そして、`predict()` メソッドを用いてテストデータの `petal_length` の値から `petal_width` の値を予測し、`mean_squared_error()` 関数で実際の `petal_widthの値` (`y_test`) と比較して予測精度の評価を行なっています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from sklearn.linear_model import LinearRegression\n", "from sklearn.metrics import mean_squared_error\n", "\n", "# 訓練データとテストデータに分割\n", "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1)\n", "\n", "model=LinearRegression() # 線形回帰モデル\n", "model.fit(X_train,y_train) # モデルを訓練データに適合\n", "y_predicted=model.predict(X_test) # テストデータで予測\n", "mean_squared_error(y_test,y_predicted) # 予測精度(平均二乗誤差)の評価" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下では、線形回帰モデルにより学習された `petal_length` と `petal_width` の関係を表す回帰式を可視化しています。学習された回帰式が実際のデータに適合していることがわかります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x_plot=np.linspace(1,7)\n", "X_plot=x_plot[:,np.newaxis]\n", "y_plot=model.predict(X_plot)\n", "plt.scatter(X,y)\n", "plt.plot(x_plot,y_plot);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 教師なし学習・クラスタリングの例\n", "以下では、アイリスデータセットを用いて花の2つの特徴量、`petal_lenghとpetal_width`、を元に花のデータをクラスタリングする手続きを示しています。ここでは**クラスタリング**を行うモデルの1つである **`KMeans`** クラスをインポートしています。\n", "\n", "[KMeansクラス](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html)\n", "\n", "特徴量データ (`X_irist`) を用意し、引数 `n_clusters` にハイパーパラメータとしてクラスタ数、ここでは `3`、を指定して `KMeans` クラスのインスタンスを作成しています。そして、`fit()` メソッドによりモデルをデータに適合させ、`predict()` メソッドを用いて各データが所属するクラスタの情報 (`y_km`) を取得しています。\n", "\n", "学習された各花データのクラスタ情報を元のデータセットのデータフレームに列として追加し、クラスタごとに異なる色でデータセットを可視化しています。2つの特徴量、`petal_lengh` と `petal_width`、に基づき、3つのクラスタが得られていることがわかります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from sklearn.cluster import KMeans\n", "\n", "iris = pd.read_csv('iris.csv')\n", "X_iris=iris[['petal_length', 'petal_width']].values\n", "\n", "model = KMeans(n_clusters=3) # k-meansモデル\n", "model.fit(X_iris) # モデルをデータに適合\n", "y_km=model.predict(X_iris) # クラスタを予測\n", "\n", "iris['cluster']=y_km\n", "iris.plot.scatter(x='petal_length', y='petal_width', c='cluster', colormap='viridis');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "3つのクラスタと3つの花の種類の分布を2つの特徴量、`petal_lengh` と `petal_width`、の空間で比較してみると、クラスタと花の種類には対応があり、2つの特徴量から花の種類をクラスタとしてグループ分けできていることがわかります。以下では可視化に `seaborn` モジュールを用いています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import seaborn as sns\n", "sns.lmplot(x='petal_length',y='petal_width',hue='cluster',data=iris,fit_reg=False);\n", "sns.lmplot(x='petal_length',y='petal_width',hue='species',data=iris,fit_reg=False);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "アイリスデータセットの2つの特徴量、`sepal_length` と `sepal_width`、を元に、`KMeans` モデルを用いて花のデータをクラスタリングしてください。クラスタの数は任意に設定してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from sklearn.cluster import KMeans\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "\n", "iris = pd.read_csv('iris.csv')\n", "X_iris=iris[['sepal_length', 'sepal_width']].values\n", "\n", "### your code here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 教師なし学習・次元削減の例\n", "以下では、アイリスデータセットを用いて花の4つの特徴量を元に花のデータを**次元削減**する手続きを示しています。ここでは次元削減を行うモデルの1つである **`PCA`** クラスをインポートしています。\n", "\n", "[PCAクラス](https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html)\n", "\n", "特徴量データ (`X_irist`) を用意し、引数 `n_components` にハイパーパラメータとして削減後の次元数、ここでは `2`、を指定して `PCA` クラスのインスタンスを作成しています。そして、`fit()` メソッドによりモデルをデータに適合させ、**`transform()`** メソッドを用いて4つの特徴量を2次元に削減した特徴量データ (`X_2d`) を取得しています。\n", "\n", "学習された各次元の値を元のデータセットのデータフレームに列として追加し、データセットを削減して得られた次元の空間において、データセットを花の種類ごとに異なる色で可視化しています。削減された次元の空間において、花の種類をグループ分けできていることがわかります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from sklearn.decomposition import PCA\n", "\n", "iris = pd.read_csv('iris.csv')\n", "X_iris=iris[['sepal_length', 'sepal_width', 'petal_length', 'petal_width']].values\n", "\n", "model = PCA(n_components=2) # PCAモデル\n", "model.fit(X_iris) # モデルをデータに適合\n", "X_2d=model.transform(X_iris) # 次元削減" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import seaborn as sns\n", "iris['pca1']=X_2d[:,0]\n", "iris['pca2']=X_2d[:,1]\n", "sns.lmplot(x='pca1',y='pca2',hue='species',data=iris,fit_reg=False);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答例" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from sklearn.linear_model import LogisticRegression\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.metrics import accuracy_score\n", "\n", "iris = pd.read_csv('iris.csv')\n", "iris2=iris[(iris['species']=='versicolor')|(iris['species']=='virginica')]\n", "X_iris=iris2[['petal_length','petal_width']].values\n", "y_iris=iris2['species'].values\n", "\n", "X_train, X_test, y_train, y_test = train_test_split(X_iris, y_iris, test_size=0.3, random_state=1, stratify=y_iris)\n", "\n", "model=LogisticRegression(solver='lbfgs')\n", "model.fit(X_train, y_train)\n", "y_model=model.predict(X_test)\n", "accuracy_score(y_test, y_model)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from sklearn.cluster import KMeans\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "\n", "iris = pd.read_csv('iris.csv')\n", "X_iris=iris[['sepal_length', 'sepal_width']].values\n", "\n", "model = KMeans(n_clusters=3)\n", "model.fit(X_iris)\n", "y_km=model.predict(X_iris)\n", "\n", "iris['cluster']=y_km\n", "iris.plot.scatter(x='sepal_length', y='sepal_width', c='cluster', colormap='viridis');" ] } ], "metadata": { "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.12.4" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: colab/7/iris.csv ================================================ sepal_length,sepal_width,petal_length,petal_width,species 5.1,3.5,1.4,0.2,setosa 4.9,3,1.4,0.2,setosa 4.7,3.2,1.3,0.2,setosa 4.6,3.1,1.5,0.2,setosa 5,3.6,1.4,0.2,setosa 5.4,3.9,1.7,0.4,setosa 4.6,3.4,1.4,0.3,setosa 5,3.4,1.5,0.2,setosa 4.4,2.9,1.4,0.2,setosa 4.9,3.1,1.5,0.1,setosa 5.4,3.7,1.5,0.2,setosa 4.8,3.4,1.6,0.2,setosa 4.8,3,1.4,0.1,setosa 4.3,3,1.1,0.1,setosa 5.8,4,1.2,0.2,setosa 5.7,4.4,1.5,0.4,setosa 5.4,3.9,1.3,0.4,setosa 5.1,3.5,1.4,0.3,setosa 5.7,3.8,1.7,0.3,setosa 5.1,3.8,1.5,0.3,setosa 5.4,3.4,1.7,0.2,setosa 5.1,3.7,1.5,0.4,setosa 4.6,3.6,1,0.2,setosa 5.1,3.3,1.7,0.5,setosa 4.8,3.4,1.9,0.2,setosa 5,3,1.6,0.2,setosa 5,3.4,1.6,0.4,setosa 5.2,3.5,1.5,0.2,setosa 5.2,3.4,1.4,0.2,setosa 4.7,3.2,1.6,0.2,setosa 4.8,3.1,1.6,0.2,setosa 5.4,3.4,1.5,0.4,setosa 5.2,4.1,1.5,0.1,setosa 5.5,4.2,1.4,0.2,setosa 4.9,3.1,1.5,0.1,setosa 5,3.2,1.2,0.2,setosa 5.5,3.5,1.3,0.2,setosa 4.9,3.1,1.5,0.1,setosa 4.4,3,1.3,0.2,setosa 5.1,3.4,1.5,0.2,setosa 5,3.5,1.3,0.3,setosa 4.5,2.3,1.3,0.3,setosa 4.4,3.2,1.3,0.2,setosa 5,3.5,1.6,0.6,setosa 5.1,3.8,1.9,0.4,setosa 4.8,3,1.4,0.3,setosa 5.1,3.8,1.6,0.2,setosa 4.6,3.2,1.4,0.2,setosa 5.3,3.7,1.5,0.2,setosa 5,3.3,1.4,0.2,setosa 7,3.2,4.7,1.4,versicolor 6.4,3.2,4.5,1.5,versicolor 6.9,3.1,4.9,1.5,versicolor 5.5,2.3,4,1.3,versicolor 6.5,2.8,4.6,1.5,versicolor 5.7,2.8,4.5,1.3,versicolor 6.3,3.3,4.7,1.6,versicolor 4.9,2.4,3.3,1,versicolor 6.6,2.9,4.6,1.3,versicolor 5.2,2.7,3.9,1.4,versicolor 5,2,3.5,1,versicolor 5.9,3,4.2,1.5,versicolor 6,2.2,4,1,versicolor 6.1,2.9,4.7,1.4,versicolor 5.6,2.9,3.6,1.3,versicolor 6.7,3.1,4.4,1.4,versicolor 5.6,3,4.5,1.5,versicolor 5.8,2.7,4.1,1,versicolor 6.2,2.2,4.5,1.5,versicolor 5.6,2.5,3.9,1.1,versicolor 5.9,3.2,4.8,1.8,versicolor 6.1,2.8,4,1.3,versicolor 6.3,2.5,4.9,1.5,versicolor 6.1,2.8,4.7,1.2,versicolor 6.4,2.9,4.3,1.3,versicolor 6.6,3,4.4,1.4,versicolor 6.8,2.8,4.8,1.4,versicolor 6.7,3,5,1.7,versicolor 6,2.9,4.5,1.5,versicolor 5.7,2.6,3.5,1,versicolor 5.5,2.4,3.8,1.1,versicolor 5.5,2.4,3.7,1,versicolor 5.8,2.7,3.9,1.2,versicolor 6,2.7,5.1,1.6,versicolor 5.4,3,4.5,1.5,versicolor 6,3.4,4.5,1.6,versicolor 6.7,3.1,4.7,1.5,versicolor 6.3,2.3,4.4,1.3,versicolor 5.6,3,4.1,1.3,versicolor 5.5,2.5,4,1.3,versicolor 5.5,2.6,4.4,1.2,versicolor 6.1,3,4.6,1.4,versicolor 5.8,2.6,4,1.2,versicolor 5,2.3,3.3,1,versicolor 5.6,2.7,4.2,1.3,versicolor 5.7,3,4.2,1.2,versicolor 5.7,2.9,4.2,1.3,versicolor 6.2,2.9,4.3,1.3,versicolor 5.1,2.5,3,1.1,versicolor 5.7,2.8,4.1,1.3,versicolor 6.3,3.3,6,2.5,virginica 5.8,2.7,5.1,1.9,virginica 7.1,3,5.9,2.1,virginica 6.3,2.9,5.6,1.8,virginica 6.5,3,5.8,2.2,virginica 7.6,3,6.6,2.1,virginica 4.9,2.5,4.5,1.7,virginica 7.3,2.9,6.3,1.8,virginica 6.7,2.5,5.8,1.8,virginica 7.2,3.6,6.1,2.5,virginica 6.5,3.2,5.1,2,virginica 6.4,2.7,5.3,1.9,virginica 6.8,3,5.5,2.1,virginica 5.7,2.5,5,2,virginica 5.8,2.8,5.1,2.4,virginica 6.4,3.2,5.3,2.3,virginica 6.5,3,5.5,1.8,virginica 7.7,3.8,6.7,2.2,virginica 7.7,2.6,6.9,2.3,virginica 6,2.2,5,1.5,virginica 6.9,3.2,5.7,2.3,virginica 5.6,2.8,4.9,2,virginica 7.7,2.8,6.7,2,virginica 6.3,2.7,4.9,1.8,virginica 6.7,3.3,5.7,2.1,virginica 7.2,3.2,6,1.8,virginica 6.2,2.8,4.8,1.8,virginica 6.1,3,4.9,1.8,virginica 6.4,2.8,5.6,2.1,virginica 7.2,3,5.8,1.6,virginica 7.4,2.8,6.1,1.9,virginica 7.9,3.8,6.4,2,virginica 6.4,2.8,5.6,2.2,virginica 6.3,2.8,5.1,1.5,virginica 6.1,2.6,5.6,1.4,virginica 7.7,3,6.1,2.3,virginica 6.3,3.4,5.6,2.4,virginica 6.4,3.1,5.5,1.8,virginica 6,3,4.8,1.8,virginica 6.9,3.1,5.4,2.1,virginica 6.7,3.1,5.6,2.4,virginica 6.9,3.1,5.1,2.3,virginica 5.8,2.7,5.1,1.9,virginica 6.8,3.2,5.9,2.3,virginica 6.7,3.3,5.7,2.5,virginica 6.7,3,5.2,2.3,virginica 6.3,2.5,5,1.9,virginica 6.5,3,5.2,2,virginica 6.2,3.4,5.4,2.3,virginica 5.9,3,5.1,1.8,virginica ================================================ FILE: colab/LICENSE ================================================ Copyright (c) 2020-2021 Mathematics and Informatics Center, The University of Tokyo. Attribution-NonCommercial-NoDerivatives 4.0 International ======================================================================= Creative Commons Corporation ("Creative Commons") is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an "as-is" basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. Using Creative Commons Public Licenses Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC- licensed material, or material used under an exception or limitation to copyright. More considerations for licensors: wiki.creativecommons.org/Considerations_for_licensors Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor's permission is not necessary for any reason--for example, because of any applicable exception or limitation to copyright--then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public: wiki.creativecommons.org/Considerations_for_licensees ======================================================================= Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. Section 1 -- Definitions. a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. b. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. c. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. d. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. e. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. f. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. g. Licensor means the individual(s) or entity(ies) granting rights under this Public License. h. NonCommercial means not primarily intended for or directed towards commercial advantage or monetary compensation. For purposes of this Public License, the exchange of the Licensed Material for other material subject to Copyright and Similar Rights by digital file-sharing or similar means is NonCommercial provided there is no payment of monetary compensation in connection with the exchange. i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. Section 2 -- Scope. a. License grant. 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: a. reproduce and Share the Licensed Material, in whole or in part, for NonCommercial purposes only; and b. produce and reproduce, but not Share, Adapted Material for NonCommercial purposes only. 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. 3. Term. The term of this Public License is specified in Section 6(a). 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a) (4) never produces Adapted Material. 5. Downstream recipients. a. Offer from the Licensor -- Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. b. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). b. Other rights. 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. 2. Patent and trademark rights are not licensed under this Public License. 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties, including when the Licensed Material is used other than for NonCommercial purposes. Section 3 -- License Conditions. Your exercise of the Licensed Rights is expressly made subject to the following conditions. a. Attribution. 1. If You Share the Licensed Material, You must: a. retain the following if it is supplied by the Licensor with the Licensed Material: i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); ii. a copyright notice; iii. a notice that refers to this Public License; iv. a notice that refers to the disclaimer of warranties; v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; b. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and c. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. For the avoidance of doubt, You do not have permission under this Public License to Share Adapted Material. 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. Section 4 -- Sui Generis Database Rights. Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database for NonCommercial purposes only and provided You do not Share Adapted Material; b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. Section 5 -- Disclaimer of Warranties and Limitation of Liability. a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. Section 6 -- Term and Termination. a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or 2. upon express reinstatement by the Licensor. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. c. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. d. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. Section 7 -- Other Terms and Conditions. a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. Section 8 -- Interpretation. a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. ======================================================================= Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” The text of the Creative Commons public licenses is dedicated to the public domain under the CC0 Public Domain Dedication. Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark "Creative Commons" or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. Creative Commons may be contacted at creativecommons.org. ================================================ FILE: colab/appendix/1-jupyter-notebook.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/text-sample.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/small.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-july-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/argsprint.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/B1S.xml\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sample.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sin.html\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/console_in_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/argsprint.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/terminal_in_menu.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ▲Jupyter Notebook の使い方\n", "\n", "Jupyter Notebook について説明します。\n", "\n", "参考\n", "\n", "- https://jupyter.readthedocs.io/en/latest/\n", "\n", "教材等の既存のノートブックは、\n", "ディレクトリのページで選択することによって開くことができます。\n", "ノートブックには `ipynb` という拡張子(エクステンション)が付きます。\n", "\n", "ノートブックを新たに作成するには、ディレクトリが表示されているページで、\n", "`New` のメニューで `Python3` を選択してください。\n", "`Untitled`(`1` などが付くことあり)というノートブックが作られます。\n", "タイトルをクリックして変更することができます。\n", "\n", "ノートブックの上方には、`File` や `Edit` などのメニュー、\n", "`↓` や `↑` や `■` などのアイコンが表示されています。\n", "\n", "右上に `Python 3` と表示されていることに注意してください。\n", "\n", "Ctrl+s(Macの場合は Cmd+s)を入力することによって、\n", "ノートブックをファイルにセーブできます。\n", "オートセーブもされますが、適当なタイミングでセーブしましょう。\n", "\n", "ノートブックはセルから成り立っています。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## セル\n", "主に次の二種類のセルを使います。\n", "\n", "* Code:\n", "Pythonのコードが書かれたセルです。\n", "Codeセルの横には `In [ ]:` と表示されています。\n", "コードを実行するには、Shift+Enter(または Return)を押します。\n", "このセルの次のセルはCodeセルです。Shift+Enterを押してみてください。\n", "* Markdown:\n", "説明が書かれたセルです。\n", "このセル自身はMarkdownセルです。\n", "\n", "セルの種類はノートブックの上のメニューで変更できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## コマンドモード\n", "セルを選択するとコマンドモードになります。\n", "ただし、Codeセルを選択したとき、\n", "マウスカーソルが入力フィールドに入っていると、\n", "編集モードになってしまいます。\n", "\n", "コマンドモードでは、セルの左の線が青色になります。\n", "\n", "コマンドモードで Enter を入力すると、編集モードになります。\n", "Markdownのセルでは、ダブルクリックでも編集モードになります。\n", "\n", "コマンドモードでは、一文字コマンドが有効なので注意してください。\n", "\n", "* a: 上にセルを挿入 (above)\n", "* b: 下にセルを挿入 (below)\n", "* x: セルを削除(そのセルが削除されてしまいますので注意!)\n", "* l: セルの行に番号を振るか振らないかをスイッチ\n", "\n", "* s または Ctrl+s: ノートブックをセーブ (checkpoint)\n", "* Enter: 編集モードに移行\n", "* Shift+Enter: セルを実行して次のセルに" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 編集モード\n", "編集モードでは文字カーソルが表示されて、セルの編集が可能です。\n", "Ctrl の付かない文字はそのまま挿入されます。\n", "\n", "編集モードでは、セルの左の線が緑色になります。\n", "\n", "編集モードでは、以下のような編集コマンドが使えます。\n", "\n", "* Ctrl+c: copy\n", "* Ctrl+x: cut\n", "* Ctrl+v: paste\n", "* Ctrl+z: undo\n", "* …\n", "\n", "Codeセルでは、編集モードでも Shift+Enter を入力すると、\n", "セルの中のコードが実行されて、次のセルに移動します。\n", "Markdownセルはフォーマットされて、次のセルに移動します。\n", "次のセルではコマンドモードになっています。\n", "\n", "Esc でコマンドモードになります。\n", "\n", "Ctrl+s でノートブックをセーブ (checkpoint)。\n", "これはコマンドモードの場合と同じです。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "次のセルを編集モードにして `10/3` と入力して実行してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## (注意)Shift-Enterに反応がなくなったとき\n", "CodeセルでShift-Enterをしても反応がないとき、\n", "特にセルの左の部分が\n", "```Python\n", "\tIn [*]:\n", "```\n", "\n", "となったままで、\\* が数に置き換わらないとき、\n", "`■` のアイコンを押して、 kernel(Pythonのインタープリタ)を停止させてください。\n", "\n", "それでも反応がないときは、右回りの矢印のアイコンを押して、\n", "kernel(Pythonのインタープリタ)を起動し直してください。\n", "\n", "たとえば、次のような例です。`■` のアイコンを押してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "while True:\n", " pass" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" }, "nbsphinx": { "execute": "never" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/appendix/2-set.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/text-sample.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/small.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-july-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/argsprint.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/B1S.xml\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sample.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sin.html\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/console_in_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/argsprint.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/terminal_in_menu.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ▲セット (set)\n", "セットについて説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/datastructures.html#sets\n", "\n", "**セット**(**集合**)は、リストと同様に複数の要素から構成されるデータです。\n", "セットでは、リストと異なり要素の重複がありません、また要素の順番もありません。\n", "\n", "セットを作成するには、次のように波括弧で要素を囲みます。\n", "辞書と似ていますが、辞書では `:` でキーと値を対応させる必要がありました。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1= {2, 1, 2, 3, 2, 3, 1, 3, 3, 1}\n", "set1 " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "type(set1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "セットのデータ型は **`set`** であり、`set` は組み込み関数でもあります。\n", "\n", "組み込み関数 `set` を用いてもセットを作成することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set([2, 1, 2, 3, 2, 3, 1, 3, 3, 1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "空のセットを作成する場合、次のようにします。( `{}` では空の辞書が作成されます。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set2 = set() # 空のセット\n", "set2" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set2 = {} # 空の辞書\n", "set2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`set` を用いて、文字列、リストやタプルなどからセットを作成することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set([1,1,2,2,2,3])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set((1,1,2,2,2,3))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set('aabdceabdae')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set({'apple' : 3, 'pen' : 5})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## セットの組み込み関数\n", "リストなどと同様に、次の関数などはセットにも適用可能です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "len(set1) # 集合を構成する要素数" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x,y,z = set1 # 多重代入\n", "x" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "2 in set1 # 指定した要素を集合が含むかどうかの判定" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "10 in set1 # 指定した要素を集合が含むかどうかの判定" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "10 not in set1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "セットの要素は、順序付けられていないのでインデックスを指定して取り出すことはできません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "set1[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `str1` が引数として与えられたとき、`str1` に含まれる要素(文字、すなわち長さ1の文字列)の種類を返す関数 `check_characters` を作成してください(大文字と小文字は区別し、スペースや句読点も1つと数えます)。\n", "たとえば、`'aabccc'` には `'a'` と `'b'` と `'c'` が含まれるので、\n", "`check_characters('aabccc')` は 3 を返します。\n", "\n", "以下のセルの `...` のところを書き換えて `check_characters(str1)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def check_characters(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_characters('Onde a terra acaba e o mar começa') == 13)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "辞書 `dic1` が引数として与えられたとき、`dic1` に登録されているキーの数を返す関数 `check_dicsize` を作成してください。\n", "\n", "以下のセルの `...` のところを書き換えて `check_dicsize(dic1)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def check_dicsize(dic1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_dicsize({'apple': 0, 'orange': 2, 'pen': 1}) == 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **集合演算**\n", "複数のセットから、**和集合**・**積集合**・**差集合**・**対称差**を求める集合演算が存在します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1 = {1, 2, 3, 4}\n", "set2 = {3, 4, 5, 6}" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1 | set2 # 和集合" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1 & set2 # 積集合" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1 - set2 # 差集合" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1 ^ set2 # 対称差" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **比較演算**\n", "数値などを比較するのに用いた比較演算子を用いて、2つのセットを比較することもできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print({1, 2, 3} == {1, 2, 3})\n", "print({1, 2} == {1, 2, 3})" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print({1, 2, 3} != {1, 2, 3})\n", "print({1, 2} != {1, 2, 3})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`<=` や `<` は、集合の間の包含関係を判定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print({1, 2, 3} <= {1, 2, 3})\n", "print({1, 2, 3} < {1, 2, 3})\n", "print({1, 2} < {1, 2, 3})" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print({1, 2} <= {2, 3, 4})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## セットのメソッド\n", "セットにも様々なメソッドが存在します。なお、以下のメソッドは全て破壊的です。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **add**\n", "指定した要素を新たにセットに追加します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1 = {1, 2, 3}\n", "set1.add(4)\n", "set1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **remove**\n", "指定した要素をセットから削除します。\n", "その要素がセットに含まれていない場合、エラーになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1.remove(1)\n", "set1" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "set1.remove(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **discard**\n", "指定した要素をセットから削除します。\n", "その要素がセットに含まれていなくともエラーになりません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1 = {1, 2, 3, 4}\n", "set1.discard(1)\n", "set1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1.discard(5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **clear**\n", "全ての要素を削除して対象のセットを空にします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1 = {1, 2, 3, 4}\n", "set1.clear()\n", "set1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **pop**\n", "セットからランダムに1つの要素を取り出します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1 = {1, 2, 3, 4}\n", "print(set1.pop())\n", "print(set1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### **union**, **intersection**, **difference**\n", "**和集合**・**積集合**・**差集合**・**対称差**を求めるメソッドも存在します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1 = {1, 2, 3, 4}\n", "set2 = {3, 4, 5, 6}\n", "set1.union(set2) # 和集合" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1.intersection(set2) # 積集合" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1.difference(set2) # 差集合" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "set1.symmetric_difference(set2) # 対称差" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "英語の文章からなる文字列 `str_engsentences` が引数として与えられたとき、`str_engsentences` 中に含まれる単語の種類数を返す関数 `count_words2` を作成してください。\n", "\n", "以下のセルの `...` のところを書き換えて `count_words2(str_engsentences)` を作成してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def count_words2(str_engsentences):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(count_words2('From Stettin in the Baltic to Trieste in the Adriatic an iron curtain has descended across the Continent.') == 15)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def check_characters(str1):\n", " set1 = set(str1)\n", " return len(set1)\n", "#check_characters('Onde a terra acaba e o mar começa') " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def check_dicsize(dic1):\n", " return len(set(dic1))\n", "#check_dicsize({'apple': 0, 'orange': 2, 'pen': 1})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "実は `len` は辞書に対してキーの数を返すので、セットを使う必要はありません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def check_dicsize(dic1):\n", " return len(dic1)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def count_words2(str_engsentences):\n", " str1 = str_engsentences.replace('.', '') # 句読点を削除する\n", " str1 = str1.replace(',', '')\n", " str1 = str1.replace(':', '')\n", " str1 = str1.replace(';', '')\n", " str1 = str1.replace('!', '')\n", " str1 = str1.replace('?', '')\n", " list1 = str1.split(' ') # 句読点を削除した文字列を、単語ごとにリストに格納する\n", " set1 = set(list1) # リストを集合に変換して同じ要素を1つにまとめる\n", " return len(set1)\n", "#count_words2('From Stettin in the Baltic to Trieste in the Adriatic an iron curtain has descended across the Continent.')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/appendix/3-recursion.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/text-sample.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/small.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-july-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/argsprint.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/B1S.xml\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sample.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sin.html\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/console_in_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/argsprint.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/terminal_in_menu.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ▲再帰\n", "**再帰**について説明します。\n", "\n", "関数の**再帰呼び出し**とは、定義しようとしている関数を、その定義の中で呼び出すことです。\n", "定義の中で直接呼び出す場合に限らず、他の関数を経由して間接的に呼び出す場合も、再帰呼び出しに含まれます。\n", "再帰呼び出しを行う関数を、**再帰関数**といいます。\n", "\n", "再帰関数は、**分割統治**アルゴリズムの記述に適しています。\n", "分割統治とは、問題を容易に解ける小さな粒度まで分割していき、\n", "個々の小さな問題を解いて、その部分解を合成することで問題全体を解くような方法を指します。\n", "分割統治の考え方は、関数型プログラミングにおいてもよく用いられます。\n", "再帰関数による分割統治の典型的な形は、次の通りです。\n", "\n", "```Python\n", "def recursive_function(...):\n", " if 問題粒度の判定:\n", " 再帰呼び出しを含まない基本処理\n", " else:\n", " 再帰呼び出しを含む処理(問題の分割や部分解の合成を行う)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下で、再帰関数を使った処理の例をいくつか見ていきましょう。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 再帰関数の例:接頭辞リストと接尾辞リスト" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 入力の文字列の接頭辞リストを返す関数prefixes\n", "def prefixes(s):\n", " if s == '':\n", " return []\n", " else:\n", " return [s] + prefixes(s[:-1])\n", "\n", "prefixes('aabcc')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 入力の文字列の接尾辞リストを返す関数suffixes\n", "def suffixes(s):\n", " if s == '':\n", " return []\n", " else:\n", " return [s] + suffixes(s[1:])\n", "\n", "suffixes('aabcc')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 再帰関数の例:べき乗の計算" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 入力の底baseと冪指数exptからべき乗を計算する関数power\n", "def power(base, expt):\n", " if expt == 0:\n", " # exptが0ならば1を返す\n", " return 1\n", " else:\n", " # exptを1つずつ減らしながらpowerに渡し、再帰的にべき乗を計算\n", " # (2*(2*(2*....*1)))\n", " return base * power(base, expt - 1)\n", " \n", "power(2,10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "一般に、再帰処理は、繰り返し処理としても書くことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# べき乗の計算を繰り返し処理で行った例\n", "def power(base, expt):\n", " e = 1\n", " for i in range(expt):\n", " e *= base\n", " return e\n", "\n", "power(2,10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "単純な処理においては、繰り返しの方が効率的に計算できることが多いですが、\n", "特に複雑な処理になってくると、再帰的に定義した方が読みやすいコードで効率的なアルゴリズムを記述できることもあります。\n", "たとえば、次に示すべき乗計算は、上記よりも高速なアルゴリズムですが、計算の見通しは明快です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# べき乗を計算する高速なアルゴリズム\n", "def power(base, expt):\n", " if expt == 0:\n", " return 1\n", " elif expt % 2 == 0:\n", " return power(base * base, expt // 2) # x**(2m) == (x*x)**m\n", " else:\n", " return base * power(base, expt - 1)\n", " \n", "power(2,10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 再帰関数の例:マージソート\n", "\n", "マージソートは、典型的な分割統治アルゴリズムで、以下のように再帰関数で実装することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# マージソートを行い、比較回数 n を返す\n", "def merge_sort_rec(data, l, r, work):\n", " n = 0\n", " if r - l <= 1:\n", " return n\n", " m = l + (r - l) // 2\n", " n1 = merge_sort_rec(data, l, m, work)\n", " n2 = merge_sort_rec(data, m, r, work)\n", " i1 = l\n", " i2 = m\n", " for i in range(l, r):\n", " from1 = False\n", " if i2 >= r:\n", " from1 = True\n", " elif i1 < m:\n", " n = n + 1\n", " if data[i1] <= data[i2]:\n", " from1 = True\n", " if from1:\n", " work[i] = data[i1]\n", " i1 = i1 + 1\n", " else:\n", " work[i] = data[i2]\n", " i2 = i2 + 1\n", " for i in range(l, r):\n", " data[i] = work[i]\n", " return n1 + n2 + n\n", "\n", "def merge_sort(data):\n", " return merge_sort_rec(data, 0, len(data), [0]*len(data))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`merge_sort` は、与えられた配列をインプレースでソートするとともに、比較の回数を返します。\n", "`merge_sort` は、再帰関数 `merge_sort_rec` を呼び出します。\n", "\n", "`merge_sort_rec(data, l, r, work)` は、配列 `data` のインデックスが `l` 以上で `r` より小さいところをソートします。\n", "\n", "- 要素が1つかないときは何もしません。\n", "- そうでなければ、`l` から `r` までの要素を半分にしてそれぞれを再帰的にソートします。\n", "- その結果を作業用の配列 `work` に順序を保ちながらコピーします。この操作はマージ(併合)と呼ばれます。\n", "- 最後に、`work` から `data` に要素を戻します。\n", "\n", "`merge_sort_rec` は自分自身を2回呼び出していますので、繰り返しでは容易には実装できません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import random\n", "a = [random.randint(1,10000) for i in range(100)]\n", "merge_sort(a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/appendix/3-visualization.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/text-sample.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/small.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-july-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/argsprint.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/B1S.xml\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sample.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sin.html\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/console_in_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/argsprint.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/terminal_in_menu.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ▲簡単なデータの可視化\n", "第3回までに学んだ各種のデータに対する簡単な可視化について触れます。\n", "\n", "参考\n", "\n", "- https://matplotlib.org/tutorials/introductory/pyplot.html#sphx-glr-tutorials-introductory-pyplot-py (English Only)\n", "\n", "`matplotlib` については、5-matplotlib に詳しい説明があります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **`matplotlib`**\n", "\n", "Pythonでは可視化のための様々な仕組みが用意されています。\n", "ここでは最も広く利用され、ノートブック上で容易に動作を確認できる `matplotlib` について触れます。\n", "`matplotlib` を利用するには第5回で取り上げるモジュールについても知る必要がありますが、\n", "第2回と第3回でデータについてだけ学ぶのでは、みなさんのモチベーションの維持が難しいと思われますので、\n", "この段階でリスト・辞書だけで2次元グラフを表示させてみます。\n", "したがって、ここではモジュールの使い方については説明しません。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`matplotlib` の出力をノートブックで表示させるには、以下をCodeセルで1回だけ実行します。\n", "`%matplotlib` のように `%` で始まる文を**マジックコマンド**と呼びます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "さらに `matplotlib` モジュールを読み込む次の処理もプログラムの冒頭で行う必要があります。\n", "\n", "```Python\n", "import matplotlib.pyplot as plt\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 折れ線グラフ\n", "\n", "`ls1 = [1, 4, 9, 16]` といった数を要素とするリストを折れ線グラフで表示するには、次のように行います。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "ls1 = [1, 4, 9, 16]\n", "plt.plot(ls1)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "折れ線グラフを複数表示させるには、`plt.plot` を繰り返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "ls1 = [1, 4, 9, 16]\n", "ls2 = [8, 7, 6, 5]\n", "plt.plot(ls1, label='1st plot')\n", "plt.plot(ls2, label='2nd plot')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 散布図\n", "散布図を表示させるには、`plt.scatter` にそれぞれの点に対応する水平、垂直座標をリストで与えます。\n", "この2つのリストの要素数は同じでなければなりません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "x = [5, 10, 15, 10]\n", "y = [10, 5, 10, 15]\n", "plt.scatter(x,y)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 棒グラフ\n", "棒グラフを表示させるには、`plt.bar` に水平座標、高さをリストで与えます。\n", "この2つのリストの要素数は同じでなければなりません。\n", "以下の例では、等間隔でグラフを表示させるため水平軸に整数列を使っています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "x = [1, 2, 3, 4]\n", "y = [10, 30, 40, 15]\n", "plt.bar(x,y)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "第2回と第3回では文字列、辞書について学びました。\n", "文字列をキー、整数を値とする辞書を棒グラフで可視化します。\n", "さらに、水平軸にはキーをラベルとして表示されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "d = {'apple':10, 'banana':30, 'orange': 40, 'kiwi': 15}\n", "x = [1,2,3,4]\n", "plt.bar(x, d.values(), tick_label=list(d.keys()))\n", "plt.show()" ] } ], "metadata": { "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.12.4" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: colab/appendix/4-csv.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/text-sample.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/small.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-july-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/argsprint.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/B1S.xml\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sample.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sin.html\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/console_in_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/argsprint.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/terminal_in_menu.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ▲CSVファイルの入出力\n", "CSVファイルの入出力について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/library/csv.html\n", "\n", "## CSV形式とは\n", "\n", "**CSV**形式とは \"comma-separated values\" の略で、\n", "複数の値をコンマで区切って記録するファイル形式です。\n", "\n", "みなさんExcelを使ったことがあると思いますが、\n", "Excelでは1つのセルに1つの値(数値や文字など)が入っていて、\n", "その他のセルの値とは独立に扱えますよね。\n", "\n", "それと同じように、CSV形式では、`,`(コンマ)で区切られた要素はそれぞれ独立の値として扱われます。\n", "\n", "たとえばサークルのメンバーデータを作ることを考えましょう。\n", "メンバーは「鈴木一郎」と「山田花子」の2名で、\n", "それぞれ『氏名』『ニックネーム』『出身地』を記録しておきたいと思います。\n", "\n", "表で表すとこんなデータです。\n", "\n", "|ID| 氏名 | ニックネーム | 出身地 | \n", "|---:|:--------|:---------------|:-------|\n", "|user1| 鈴木一郎 | イチロー | 広島 |\n", "|user2| 山田花子 | はなこ | 名古屋 |\n", "\n", "これをCSV形式で表すと次のようになります。" ] }, { "cell_type": "raw", "metadata": {}, "source": [ "'user1','鈴木一郎','イチロー','広島'\n", "'user2','山田花子','はなこ','名古屋'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CSVファイルの読み込み\n", "CSVファイルを読み書きするには、\n", "ファイルをオープンして、そのファイルオブジェクトから、\n", "CSVリーダを作ります。\n", "\n", "**CSVリーダ**とは、CSVファイルからデータを読み込むためのオブジェクトで、\n", "このオブジェクトのメソッドを呼び出すことにより、CSVファイルからデータを読み込むことができます。\n", "\n", "CSVリーダを作るには、\n", "**`csv`** というモジュールの **`csv.reader`** という関数にファイルオブジェクトを渡します。\n", "\n", "たとえば、次のような表で表されるCSVファイル `small.csv` を読み込んでみましょう。\n", "\n", " 0列目 | 1列目 | 2列目 | 3列目 | 4列目 \n", "---|---|---|---|---\n", " 11 | 12 | 13 | 14 | 15 \n", " 21 | 22 | 23 | 24 | 25 \n", " 31 | 32 | 33 | 34 | 35 \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import csv\n", "f = open('small.csv', 'r')\n", "dataReader = csv.reader(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このオブジェクトもイテレータで、`next` という関数を呼び出すことができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "next(dataReader)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このようにして CSVファイルを読むと、\n", "CSVファイルの各行のデータが文字列のリストとなって返されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "next(dataReader)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "row = next(dataReader)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "row" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "row[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "数値が `''` で囲われている場合、数値ではなく文字列として扱われているので、そのまま計算に使用することができません。\n", "\n", "文字列が整数を表す場合、**`int`** 関数によって文字列を整数に変換することができます。\n", "文字列が小数を含む場合は **`float`** 関数で浮動小数点数型に変換、文字列が複素数を表す場合は **`complex`** 関数で複素数に変換します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "int(row[2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ファイルの終わりまで達した後に `next` 関数を実行すると、下のようにエラーが返ってきます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "next(dataReader)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ファイルを使い終わったらクローズすることを忘れないようにしましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CSVファイルに対するfor文\n", "CSVリーダもイテレータですので、for文の `in` の後に書くことができます。\n", "\n", "---\n", "```Python\n", "for row in dataReader:\n", " ...\n", "```\n", "---\n", "\n", "繰り返しの各ステップで、`next(dataReader)` が呼び出されて、\n", "`row` にその値が設定され、for文の中身が実行されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = open('small.csv', 'r')\n", "dataReader = csv.reader(f)\n", "for row in dataReader:\n", " print(row)\n", "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CSVファイルに対するwith文\n", "以下はwith文を使った例です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('small.csv', 'r') as f:\n", " dataReader = csv.reader(f)\n", " for row in dataReader:\n", " print(row)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## CSVファイルの書き込み" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "CSVファイルを作成して書き込むには、CSVライターを作ります。\n", "\n", "**CSVライター**とは、CSVファイルを作ってデータを書き込むためのオブジェクトで、\n", "このオブジェクトのメソッドを呼び出すことにより、データがCSV形式でファイルに書き込まれます。\n", "\n", "CSVライターを作るには、\n", "**`csv`** というモジュールの **`csv.writer`** という関数にファイルオブジェクトを渡します。\n", "ここで、半角英数文字以外の文字(たとえば日本語文字や全角英数文字)を書き込み・書き出しする際には、\n", "文字コード(たとえば `encoding='utf-8'`)を指定し、\n", "また書き出しの際にはさらに改行コードとして `newline=''` を指定しないと文字化けが生じる可能性があります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f = open('out.csv', 'w', encoding='utf-8', newline='')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dataWriter = csv.writer(f)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dir(dataWriter)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dataWriter.writerow([1,2,3])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dataWriter.writerow([21,22,23])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "書き込みモードの場合も、ファイルを使い終わったらクローズすることを忘れないようにしましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "f.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "読み込みのときと同様、with文を使うこともできます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('out.csv', 'w', encoding='utf-8', newline='') as f:\n", " dataWriter = csv.writer(f)\n", " dataWriter.writerow([1,2,3])\n", " dataWriter.writerow([21,22,23])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 東京の7月の気温\n", "`tokyo-temps.csv` には、気象庁のオープンデータからダウンロードした、\n", "東京の7月の平均気温のデータが入っています。\n", "\n", "http://www.data.jma.go.jp/gmd/risk/obsdl/\n", "\n", "48行目の第2列に1875年7月の平均気温が入っており、\n", "以下、2016年まで、12行ごとに7月の平均気温が入っています。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下は、これを取り出すPythonの簡単なコードです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import csv\n", "\n", "with open('tokyo-temps.csv', 'r', encoding='shift_jis') as f:\n", " dataReader = csv.reader(f) # csvリーダを作成\n", " n=0\n", " year = 1875\n", " years = []\n", " july_temps = []\n", " for row in dataReader: # CSVファイルの中身を1行ずつ読み込み\n", " n = n+1\n", " if n>=48 and (n-48)%12 == 0: # 48行目からはじめて12か月ごとにif内を実行\n", " years.append(year)\n", " july_temps.append(float(row[1]))\n", " year = year + 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ファイルをオープンするときに、キーワード引数の **`encoding`** が指定されています。\n", "このファイルはShift_JISという文字コードで書かれているため、\n", "この引数で、ファイルの符号(**文字コード**)を指定します。\n", "`'shift_jis'` はShift_JISを意味します。この他に、`'utf-8'`(UTF-8、すなわちビットのUnicode)があります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "変数 `years` に年の配列、変数 `july_temps` に対応する年の7月の平均気温の配列が設定されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "years" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "july_temps" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ここでは詳しく説明しませんが、**線形回帰**によるフィッティングを行ってみましょう。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "\n", "fitp = numpy.poly1d(numpy.polyfit(years, july_temps, 1))\n", "ma = max(years)\n", "mi = min(years)\n", "xp = numpy.linspace(mi, ma, (ma - mi))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(years, july_temps, '.', xp, fitp(xp), '-')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "1. `tokyo-temps.csv` を読み込んで、各行が西暦年と7月の気温のみからなる `'tokyo-july-temps.csv'` という名前のCSVファイルを作成してください。\n", "西暦年は1875から2016までとします。\n", "\n", "2. 作成したCSVファイルをExcelで読み込むとどうなるか確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のセルによってテストしてください。(`years` と `july_temps` の値がそのままと仮定しています。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "with open('tokyo-july-temps.csv', 'r', encoding='shift_jis') as f:\n", " i = 0\n", " dataReader = csv.reader(f)\n", " for row in dataReader:\n", " if int(row[0]) != years[i] or abs(float(row[1])-july_temps[i])>0.000001:\n", " print('error', int(row[0]), float(row[1]))\n", " i += 1\n", "print(i== 142) # 1875年から2016年まで142年間分のデータがあるはずです" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "整数データのみからなるCSVファイルの名前を受け取ると、そのCSVファイルの各行を読み込んで整数のリストを作り、\n", "ファイル全体の内容を、そのようなリストのリストとして返す関数 `csv_matrix(name)` を定義してください。\n", "\n", "たとえば上で用いた `small.csv` には次のようなデータが入っています。\n", "\n", "\n", " 0列目 | 1列目 | 2列目 | 3列目 | 4列目 \n", "---|---|---|---|---\n", " 11 | 12 | 13 | 14 | 15 \n", " 21 | 22 | 23 | 24 | 25 \n", " 31 | 32 | 33 | 34 | 35 \n", "\n", "この `small.csv` の名前が引数として与えられた場合、\n", "\n", "```Python\n", "[[11, 12, 13, 14, 15], [21, 22, 23, 24, 25], [31, 32, 33, 34, 35]]\n", "```\n", "\n", "というリストを返します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def csv_matrix(name):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のセルによってテストしてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(csv_matrix('small.csv') == [[11, 12, 13, 14, 15], [21, 22, 23, 24, 25], [31, 32, 33, 34, 35]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "with open('tokyo-july-temps.csv', 'w', encoding='utf-8', newline='') as f:\n", " i = 0\n", " dataWriter = csv.writer(f)\n", " for i in range(len(years)):\n", " dataWriter.writerow([years[i],july_temps[i]])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def csv_matrix(name):\n", " rows = []\n", " with open(name, 'r') as f:\n", " dataReader = csv.reader(f)\n", " for row in dataReader:\n", " rows.append([int(x) for x in row])\n", " return rows " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/appendix/5-bokeh.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/text-sample.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/small.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-july-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/argsprint.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/B1S.xml\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sample.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sin.html\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/console_in_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/argsprint.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/terminal_in_menu.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ▲Bokehライブラリ\n", "Bokehライブラリについて説明します。\n", "\n", "参考\n", "\n", "* https://bokeh.pydata.org/\n", "\n", "[Bokeh](https://bokeh.pydata.org/)は、データを可視化するためのライブラリです。\n", "**`bokeh`** モジュールを使った、基本的なグラフの描画について説明します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 線グラフ\n", "Bokehライブラリ使用してグラフを描画するには、**`bokeh.plotting`** のモジュールをインポートします。\n", "基本的なグラフの描画をノートブック上で行うには、図形を生成する **`bokeh.plotting.figure()`**、図形を表示する **`bokeh.plotting.show()`**、出力先をノートブック上に設定する **`bokeh.plotting.output_notebook()`** があれば充分です。\n", "通例、`output_notebook()` は最初に呼び出されます。\n", "\n", "グラフで可視化するデータは配列を用いることが多いため、`numpy` モジュールも併せてインポートします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from bokeh.plotting import figure, output_notebook, show\n", "output_notebook()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次は、`figure()` が返す `Figure` クラスの **`line()`** メソッドを使って、リストの要素の数値をy軸の値としてグラフを描画しています。\n", "y軸の値に対応するx軸の値は、リストの各要素のインデックスとしています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# プロットするデータ\n", "d = [0, 1, 4, 9, 16]\n", "p = figure()\n", "p.line(list(range(len(d))), d) # 第1引数がx軸、第2引数がy軸\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`line()` メソッド(及び他の描画用メソッド)では、キーワード引数も使えます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "p = figure()\n", "p.line(y=d, x=list(range(len(d))))\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "次に示すように、複数のグラフをまとめてプロットして表示することもできます。\n", "プロットするメソッドではグラフの線の色や線の種類を、`line_color` 引数や `line_dash` 引数で指定できます。\n", "また、`legend_label` 引数に値を設定すると、プロットしたグラフが凡例に現れます。\n", "引数の詳細は[Figure.line](https://bokeh.pydata.org/en/latest/docs/reference/plotting.html#bokeh.plotting.figure.Figure.line)のページ(英語)を参照してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "data = [0, 1, 4, 9, 16]\n", "x = list(range(len(data)))\n", "p = figure()\n", "p.line(x, x, line_color='blue', legend_label='linear', line_dash='dashed')\n", "p.line(x, data, line_color='green', legend_label='quad', line_dash='dotted')\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`figure()` 関数の引数に、軸のラベルや、グラフのタイトルを設定できます。\n", "プロット点を線グラフ上に重ねたいときには、**`circle()`** メソッドや **`cross()`** メソッドで同色の円や十字を追加で描けばよいです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "p = figure(x_axis_label='x', y_axis_label='y', title='Linear vs. Quadratic')\n", "p.line(x, x, line_color='blue', legend_label='linear', line_dash='dashed')\n", "p.circle(x, x, color='blue', line_width=5)\n", "p.line(x, data, line_color='green', legend_label='quad', line_dash='dotted')\n", "p.cross(x, data, color='green', size=16)\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "色の使い分けを全て自分で決めるのは面倒です。\n", "良く使われる色のリストがパレットとして、提供されています。\n", "次は、`d3` の `Category10` という種類の3色パレットを用いています。\n", "詳細は、[palette](https://bokeh.pydata.org/en/latest/docs/reference/palettes.html)のページを参照してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from bokeh.palettes import d3\n", "c = d3['Category10'][3]\n", "p = figure(x_axis_label='x', y_axis_label='y', title='Linear vs. Quadratic')\n", "p.line(x, x, line_color=c[0], legend_label='linear', line_dash='dashed')\n", "p.circle(x, x, color=c[0], line_width=5)\n", "p.line(x, data, line_color=c[1], legend_label='quad', line_dash='dotted')\n", "p.cross(x, data, color=c[1], size=16)\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "グラフを描画するときのプロット数を増やすことで任意の曲線のグラフを作成することもできます。\n", "次の例では、`numpy` モジュールの `arange()` 関数を用いて、$- \\pi$ から $\\pi$ の範囲を `0.1` 刻みでx軸の値を配列として準備しています。\n", "そのx軸の値に対して、`numpy` モジュールの `cos()` 関数と `sin()` 関数を用いて、y軸の値をそれぞれ準備し、cosカーブとsinカーブを描画しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# グラフのx軸の値となる配列\n", "x = np.arange(-np.pi, np.pi, 0.1)\n", "\n", "# 上記配列をcos, sin関数に渡し, y軸の値として描画\n", "p = figure(title='cos and sin Curves', x_axis_label='x', y_axis_label='y')\n", "p.line(x, np.cos(x), line_color=c[0])\n", "p.line(x, np.sin(x), line_color=c[1])\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "プロットの数を少なくすると、曲線は直線をつなぎ合わせることで描画されていることがわかります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = np.arange(-np.pi, np.pi, 0.5)\n", "p = figure(title='cos and sin Curves', x_axis_label='x', y_axis_label='y')\n", "p.line(x, np.cos(x), line_color=c[0])\n", "p.line(x, np.sin(x), line_color=c[1])\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### グラフの例:ソートアルゴリズムにおける比較回数" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import random\n", "\n", "def bubble_sort(lst):\n", " n = 0\n", " for j in range(len(lst) - 1):\n", " for i in range(len(lst) - 1 - j):\n", " n = n + 1\n", " if lst[i] > lst[i+1]:\n", " lst[i + 1], lst[i] = lst[i], lst[i+1]\n", " return n\n", "\n", "def merge_sort_rec(data, l, r, work):\n", " if l+1 >= r: \n", " return 0\n", " m = l+(r-l)//2\n", " n1 = merge_sort_rec(data, l, m, work)\n", " n2 = merge_sort_rec(data, m, r, work)\n", " n = 0\n", " i1 = l\n", " i2 = m\n", " for i in range(l, r):\n", " from1 = False\n", " if i2 >= r:\n", " from1 = True\n", " elif i1 < m:\n", " n = n + 1\n", " if data[i1] <= data[i2]:\n", " from1 = True\n", " if from1:\n", " work[i] = data[i1]\n", " i1 = i1 + 1\n", " else:\n", " work[i] = data[i2]\n", " i2 = i2 + 1\n", " for i in range(l, r):\n", " data[i] = work[i]\n", " return n1+n2+n\n", "\n", "def merge_sort(data):\n", " return merge_sort_rec(data, 0, len(data), [0]*len(data))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = np.arange(100, 1100, 100)\n", "bdata = np.array([bubble_sort([random.randint(1,10000) for i in range(k)]) for k in x])\n", "mdata = np.array([merge_sort([random.randint(1,10000) for i in range(k)]) for k in x])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "p = figure(title='bubble sort vs. merge sort', x_axis_label='number of items', y_axis_label='number of comparisons')\n", "p.line(x, bdata, line_color=c[0])\n", "p.circle(x, bdata, color=c[0], line_width=5)\n", "p.line(x, mdata, line_color=c[1])\n", "p.circle(x, mdata, color=c[1], line_width=5)\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 散布図\n", "\n", "散布図の描画には、点のプロットを `marker` 引数で指定できる **`scatter()`** メソッドが便利です。\n", "以下では、ランダムに生成した20個の要素からなる配列 `x`、`y` の各要素の値の組みを点としてプロットした散布図を表示します。\n", "プロットする点のマーカは円とし、`size` 引数で大きさを、`alpha` 引数で透明度を設定しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# グラフのx軸の値となる配列\n", "x = np.random.rand(20)\n", "# グラフのy軸の値となる配列\n", "y = np.random.rand(20)\n", "\n", "p = figure()\n", "p.scatter(x, y, marker='circle', size=16, alpha=0.5)\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "これと同じグラフは、単に `circle()` メソッドでプロットをすることでも描画できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "p = figure()\n", "p.circle(x, y, size=16, alpha=0.5)\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 棒グラフ\n", "\n", "棒グラフは、**`vbar()`** メソッドを用いて描画できます。\n", "次の例では、ランダムに生成した10個の要素からなる配列 `y` の各要素の値を縦の棒グラフで表示しています。\n", "`x` は、x軸上で棒グラフのバーの並ぶ位置を示しています。\n", "ここでは、`numpy` モジュールの `arange()` 関数を用いて、`1` から `10` の範囲を `1` 刻みでx軸上のバーの並ぶ位置として配列を準備しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# x軸上で棒の並ぶ位置となる配列\n", "x = np.arange(1, 11, 1)\n", "# グラフのy軸の値となる配列\n", "y = np.random.rand(10)\n", "\n", "p = figure()\n", "p.vbar(x, 0.5, y) # 第2引数は幅\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ヒストグラム\n", "\n", "ヒストグラムの描画には、**`quad()`** メソッドが便利です。\n", "次の例では、`numpy.random.randn()` 関数を用いて、正規分布に基づく 1000 個の数値の要素からなる配列を用意し、**`numpy.histogram()`** 関数を使って20個のビンに分類したヒストグラムを計算しています。\n", "その計算結果を、`quad()` メソッドを使って、描画しています。\n", "ビンの境界を見やすくするように、`line_color` と `fill_color`(デフォルト色)を別の色にしています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 正規分布に基づく1000個の数値の要素からなる配列 \n", "d = np.random.randn(1000)\n", "# numpy.histogramで20のビンに分割\n", "hist, bin_edges = np.histogram(d, 20)\n", "p = figure()\n", "p.quad(top=hist, bottom=0, left=bin_edges[:-1], right=bin_edges[1:], line_color='white', alpha=0.5)\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ヒートマップ\n", "\n", "最後に、複雑な応用例として、ヒートマップの描画方法を示します。\n", "次の例は、10x10 のマスに `0.0` 以上 `1.0` 未満の乱数の温度を割り当て、その値に応じた色で塗ったヒートマップです。\n", "ここでは、これまでと違って、x軸、y軸、温度の3つの値が必要になります。\n", "そこで、**`bokeh.models.ColumnDataSource`** 型を用いて、その3つ組を、`'x'`・`'y'`・`'T'` の属性を持った表データを構築しています。\n", "この表データの構築には、7-1で説明するpandasも使えます。\n", "\n", "ヒートマップでは、温度に応じた階調のある色選択が必要です。\n", "そこで、色階調と値を対応付ける **`bokeh.models.LinearColorMapper`** 型の `mapper` を準備します。\n", "`rect()` メソッドでは、表データの属性を参照して描画しています。\n", "色は、表データの値を `mapper` に適用して色に変化させたものを用いることで、温度に応じた色選択を実現しています。\n", "最後に、目盛り付きのカラーバーを生成して、右に配置しています。\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from bokeh.models import LinearColorMapper, BasicTicker, PrintfTickFormatter, ColorBar, ColumnDataSource\n", "from bokeh.transform import transform\n", "\n", "# 10行10列のランダム要素からなる行列\n", "n = 10\n", "data = np.random.rand(n*n)\n", "src = ColumnDataSource({'x': [yx % n for yx in range(n*n)], 'y': [yx // n for yx in range(n*n)], 'T' : data})\n", "\n", "colors = ['#75968f', '#a5bab7', '#c9d9d3', '#e2e2e2', '#dfccce', '#ddb7b1', '#cc7878', '#933b41', '#550b1d']\n", "mapper = LinearColorMapper(palette=colors, low=data.min(), high=data.max())\n", "p = figure()\n", "p.rect('x', 'y', 1, 1, source=src, line_color=None, fill_color=transform('T', mapper))\n", "color_bar = ColorBar(color_mapper=mapper, location=(0, 0),\n", " ticker=BasicTicker(desired_num_ticks=len(colors)),\n", " formatter=PrintfTickFormatter(format='%2.1f'))\n", "p.add_layout(color_bar, 'right')\n", "show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## グラフのファイル出力\n", "\n", "これまで表示されてきたグラフには画像保存ボタンがあるので、それをクリックすればPNG形式の画像を保存できます。\n", "\n", "**`bokeh.plotting.output_file()`** を用いると、グラフ単独をHTMLファイルとして保存できるようになります。\n", "ただし、既に `output_notebook()` を読んでいる場合、**`bokeh.plotting.reset_output()`** で状態をリセットする必要があります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from bokeh.plotting import save, output_file, reset_output\n", "x = np.arange(-2*np.pi, 2*np.pi, 0.1)\n", "p = figure(title='sin Curves', x_axis_label='x', y_axis_label='y')\n", "p.line(x, np.sin(x))\n", "\n", "reset_output() # output_notebook()の効果を消す\n", "output_file('sin.html') # 出力先の設定\n", "save(p) # グラフを保存するだけ\n", "show(p) # 保存した上でブラウザを開く" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "***注意***:`output_notebook()` を呼んだ状態と `output_file()` を呼んだ状態が重なると、`show()` でエラーが起きます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "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.12.4" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: colab/appendix/5-command.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/text-sample.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/small.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-july-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/argsprint.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/B1S.xml\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sample.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sin.html\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ▲Pythonスクリプトとコマンドライン実行\n", "Pythonスクリプトとコマンドライン実行について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.org/ja/3/tutorial/interpreter.html\n", "- https://docs.python.org/ja/3/tutorial/modules.html\n", "- https://docs.python.org/ja/3/tutorial/appendix.html\n", "- https://docs.python.org/ja/3/library/sys.html\n", "- https://docs.python.org/ja/3/reference/import.html\n", "\n", "実は、第4回で紹介したモジュールファイル(拡張子 `.py`)は、それ単独で直接実行可能な自己完結したプログラムです。\n", "直接実行されるPythonプログラムコードのことを指して特に、**Pythonスクリプト**と呼びます。\n", "モジュールかスクリプトかを区別しないときには、Pythonソースファイルや `.py` ファイル等と呼ばれます。\n", "\n", "たとえば、次のコードセルを実行してみてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "a1 = 10\n", "print('a1 contains the value of', a1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この内容と全く同じコードを記述したPythonスクリプトファイル `sample.py` を教材として用意しました。 \n", "\n", "オペレーティングシステム(実際にはシェル)から `sample.py` を実行するには、以下のようにします。\n", "\n", "```console\n", ">>> python sample.py\n", "```\n", "\n", "あるいは\n", "\n", "```console\n", ">>> python3 sample.py\n", "```\n", "\n", "ここで、`>>> ` は、シェルのプロンプト(コマンド入力を促す記号)を意味します。\n", "後に示す具体例を見るとわかるように、環境によっては `>` であったり、`$` であったりします。\n", "\n", "このようにスクリプトをシェルから実行することを、**コマンドライン実行**と呼びます。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## コマンドライン実行の具体例\n", "\n", "`sample.py` をコマンドライン実行する具体例を、実行環境毎に説明します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Jupyter Notebook での実行方法\n", "\n", "ファイルマネージャ画面で、\n", "\n", "New ⇒ Terminal\n", "\n", "を選択すると、ターミナルのタブが生成されます。\n", "\n", "![ターミナルタブ](https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/./appendix/fig/terminal_in_menu.png)\n", "\n", "Windows 10 の環境(ユーザーアカウント名 `sato`)では、次のように表示されます。\n", "\n", "![コンソール](https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/./appendix/fig/console_in_browser.png)\n", "\n", "次の例では、`cd` コマンドで `sample.py` が存在するディレクトリ `materials/5/` に移動し、その上で `sample.py` を実行しています。\n", "\n", "![sample.py](https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/./appendix/fig/sample_py_browser.png)\n", "\n", "Jupyter Notebook 上で開かれるターミナルは、環境によって違います。\n", "デフォルトでは、Windows 10 ではPowerShellが起動し、macOSならばbashが起動するでしょう。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Windowsでの実行方法\n", "\n", "以下をクリックすれば、ターミナルが開いて `python` をコマンドとして実行できます。\n", "\n", "Start メニュー ⇒ Anaonda3(64-bit) ⇒ Anaconda Prompt \n", "\n", "![Anaconda Prompt](https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/./appendix/fig/sample_py_win_1.png)\n", "\n", "下記のようなウインドウが表示されます。\n", "\n", "![Anaconda Prompt2](https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/./appendix/fig/sample_py_win_2.png)\n", "\n", "Windowsのユーザーアカウント名のついたフォルダ(画像では、KMK)の中に `pythontest` というフォルダを作成し、その中に `sample.py` を格納した場合の実行例を示します。\n", "\n", "例では、`cd` というコマンドで `sample.py` を格納したフォルダ `pythontest` に移動し、その上で `sample.py` を実行しています。\n", "\n", "![Anaconda sample](https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/./appendix/fig/sample_py_win_3.png)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### macOS での実行方法\n", "\n", "Application ⇒ Utilities ⇒ Terminal.app を起動します。\n", "\n", "アプリケーション ⇒ ユーティリティ ⇒ ターミナル.app を起動します。(日本語の場合)\n", " \n", "![MacOS FInder](https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/./appendix/fig/sample_py_mac_1.png)\n", "\n", "下記のようなウインドウが表示されます。\n", "\n", "![Terminal.app](https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/./appendix/fig/sample_py_mac_2.png)\n", "\n", "\n", "ダウンロードフォルダ (`Downloads`) に `sample.py` を格納した場合の実行例を示します。\n", "\n", "例では、`cd` というコマンドで `sample.py` を格納した `Downloads` フォルダに移動し、その上で `sample.py` を実行しています。\n", "\n", "![MacOS Sample](https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/./appendix/fig/sample_py_mac_3.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## コマンドライン引数\n", "\n", "コマンドライン実行時には、実行スクリプト名の後に、文字列を書き込むことにより、実行スクリプトへ引数を与えることができます。 \n", "この引数のことを、**コマンドライン引数**と呼びます。\n", "\n", "たとえば、`argsprint.py` というスクリプトファイルをコマンドライン実行することを考えます。\n", "\n", "```console\n", ">>> python argsprint.py\n", "```\n", "\n", "ここで、 `argsprint.py` の後ろに、適当な文字列を付け加えます。たとえば、以下のように3つの文字列 `firstvalue` `secondvalue` `thirdvalue` をスペースで区切って付け加えてみます。 \n", "\n", "```console\n", ">>> python argsprint.py firstvalue secondvalue thirdvalue\n", "```\n", "\n", "このとき、この3つの文字列が `argsprint.py` にコマンドライン引数として与えられることになります。\n", "\n", "この引数は、`sys` モジュールの `argv` という変数 (`sys.argv`) にリストとして格納されます。\n", "\n", " `argsprint.py` を次のようなコードからなるファイルとしましょう。\n", "\n", "---\n", "\n", "argsprint.py:\n", "\n", "```Python\n", "import sys\n", "print(sys.argv) # リスト sys.argv の中身を印字\n", "```\n", "\n", "---\n", "\n", "このような `argsprint.py` を先の例のように実行すると、以下の画像のような結果が得られます。リスト `sys.argv` に2番目の要素として文字列 `firstvalue` が、3番目の要素として文字列 `secondvalue` が、4番目の要素として文字列 `thirdvalue` が格納されていることを確認してください。また、リストの最初の要素には、実行したスクリプト名(ここでは `argsprint.py`)が格納されることに注意してください。\n", "\n", "![argsprint](https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/./appendix/fig/argsprint.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習\n", "\n", "上記に従って `argsprint.py` ファイルを作成して、引数を変更したり、引数の数を増やしたり減らしたりして、表示がどう変わるか調べてください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習\n", "\n", "コマンドライン実行時に、コマンドライン引数の1番目を印字 (print) する `arg1.py` を作成せよ。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習\n", "\n", "コマンドライン実行時に、スクリプト名を印字する `scriptname.py` を作成してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習\n", "\n", "コマンドライン実行時に、コマンドライン引数の数を印字する `numargs.py` を作成してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 練習\n", "\n", "コマンドライン引数として与えられた任意個の整数の和を印字する `sum.py` を作成してください。 \n", "\n", "たとえば、次のように実行すると、 \n", "\n", "```console\n", ">>> python sum.py 1 2 3\n", "```\n", "\n", "`6` と印字されます。\n", "\n", "なお、コマンドライン引数は文字列型であることに注意してください。。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "v1 = '100'\n", "v2 = '200'\n", "int(v1) + int(v2) # 整数加算" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "v1 + v2 # 文字列結合" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## モジュールのコマンドライン実行\n", "\n", "さて、モジュールファイルは、それ自体が単独で実行可能であると述べました。\n", "つまり、Pythonソースファイルは、モジュールとしてインポートされる場合と、スクリプトとしてコマンドライン実行される場合の2通りが考えられるわけです。\n", "\n", "あるモジュールが、インポートされたのか、スクリプトとしてコマンドライン実行されたのかは、プログラム中の **`__name__`** という組み込み変数を参照することで区別できます。\n", "\n", "具体的には、モジュール `mod.py` がコマンドライン実行されたとき、`__name__` の値は `'__main__'` になります。\n", "一方、`import mod` されたとき、`__name__` の値は `'mod'` になります。\n", "\n", "これを利用することで、インポートされた場合とコマンドライン実行された場合で、モジュールの振舞いを変えることができます。\n", "たとえば、次に示す `factorial.py` モジュールを考えます。\n", "\n", "---\n", "\n", "factorial.py:\n", "\n", "```Python\n", "import sys\n", "\n", "# 階乗n!を返す\n", "def fact(n):\n", " prod = 1\n", " for i in range(1, n + 1):\n", " prod *= i\n", " return prod\n", "\n", "if __name__ == '__main__':\n", " n = int(sys.argv[1]) # 整数nが1番目のコマンドライン引数で与えられる\n", " print(fact(n)) # n!を印字 \n", "```\n", "\n", "---\n", "\n", "これに対して、`import factorial` すると、階乗を計算する関数 `factorial.fact()` が利用できるようになります。\n", "一方、`python factorial.py 6` とコマンドライン実行すると、6の階乗である `720` が印字されます。\n", "つまり、このモジュールは、階乗を計算するライブラリとしても、階乗を計算するスクリプトとしても利用できるわけです。\n", "\n", "もし `if __name__ == '__main__'` の条件分岐が無かったら、モジュールとしてインポートしたときに、インポート元のスクリプトのために与えられたコマンドライン引数を使って、階乗を計算・印字しようとします。\n", "これは一般に、望ましい振舞いではありません。\n", "\n", "このように、`if __name__ == '__main__'` の分岐中には、自己完結したスクリプトとしての振舞いが記述されます。\n", "\n", "ライブラリモジュールとして使うことのみが想定されている場合、テストコードが記述されることもあります。\n", "たとえば、次のように記述すると、\n", "\n", "---\n", "\n", "factorial.py:\n", "\n", "```Python\n", "import sys\n", "\n", "# 階乗n!を返す\n", "def fact(n):\n", " prod = 1\n", " for i in range(1, n + 1):\n", " prod *= i\n", " return prod\n", "\n", "if __name__ == '__main__':\n", " print('test n = 6:', fact(6) == 720) \n", " print('test n = 0:', fact(0) == 1) \n", "```\n", "\n", "---\n", "\n", "コマンドライン実行したときには、`fact()` が正しく計算されているかテストした結果が印字されます。\n", "このテストコードは、ライブラリモジュールとしてimportして利用するときには実行されません。\n", "このようにすると、1つのPythonソースファイルの中で、ライブラリ実装とテストをひとまとめにできて、保守しやすくなります。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ソースファイル先頭部分にある宣言\n", "\n", "### 文字コード宣言\n", "\n", "PythonソースコードはUTF-8で記述することが[公式に推奨されています](https://www.python.org/dev/peps/pep-0008/#source-file-encoding)。\n", "\n", "しかし、特にWindows環境では、歴史的事情からShift_JIS (shift_jis) が使われることがあります。\n", "このとき、Pythonソースファイルの先頭部分には、次のような**文字コード宣言**が必要です。\n", "\n", "```Python\n", "# -*- coding: shift_jis -*-\n", "```\n", "\n", "これがないと、Pythonインタプリタがエラーを出して止まります。\n", "\n", "なお、UTF-8で記述されている場合には、文字コード宣言を記述しないことが[公式に推奨されています](https://www.python.org/dev/peps/pep-0008/#source-file-encoding)。\n", "\n", "### shebang\n", "\n", "Unix環境(macOSを含む)では、スクリプトファイルの先頭行には、そのスクリプトを実行するコマンドを指定できるようになっています。\n", "この先頭行のことは、**shebang**と呼ばれます。\n", "\n", "Unix環境でPythonスクリプトに用いられる標準的なshebangは次です。\n", "```Python\n", "#!/usr/bin/env python3\n", "```\n", "`#!` に続く部分で、コマンドを絶対パスで指定します。\n", "`env` コマンドは、その引数(ここでは `python3`)の名前のコマンドを、環境の中から探して実行します。\n", "したがって、上のように記述すると、Pythonインタプリタがインストールされている場所を気にせずに、Unix環境におけるPython3系列の標準コマンド名である `python3` を使って実行できるようになります。\n", "\n", "shebangと文字コード宣言の両方を含む場合は、たとえば、次のようになります。\n", "```Python\n", "#!/usr/bin/env python3\n", "# -*- coding: shift_jis -*-\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答\n", "\n", "各セルのコードを保存した `.py` ファイルが解答です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#arg1.py\n", "import sys\n", "print(sys.argv[1])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#scriptname.py\n", "import sys\n", "print(sys.argv[0])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#numargs.py\n", "import sys\n", "num = len(sys.argv) - 1 # sys.argv[0]はコマンドライン引数ではないので1減らす\n", "print(num)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "#sum.py\n", "import sys\n", "s = 0\n", "for v in sys.argv[1:]:\n", " s += int(v)\n", "print(s)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: colab/appendix/5-matplotlib.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/text-sample.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/small.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-july-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/argsprint.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/B1S.xml\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sample.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sin.html\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/console_in_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/argsprint.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/terminal_in_menu.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ▲Matplotlibライブラリ\n", "Matplotlibライブラリについて説明します。\n", "\n", "参考\n", "\n", "- https://matplotlib.org/\n", "\n", "**Matplotlib**ライブラリにはグラフを可視化するためのモジュールが含まれています。以下では、Matplotlibライブラリのモジュールを使った、グラフの基本的な描画について説明します。\n", "\n", "Matoplotlibライブラリを使用するには、まず `matplotlib` のモジュールをインポートします。ここでは、基本的なグラフを描画するための `matplotlib.pyplot` モジュールをインポートします。慣例として、同モジュールを `plt` と別名をつけてコードの中で使用します。また、グラフで可視化するデータはリストや配列を用いることが多いため、5-3で使用した `numpy` モジュールも併せてインポートします。なお、`%matplotlib inline` はノートブック内でグラフを表示するために必要です。\n", "\n", "`matplotlib` では、通常 `show()` 関数を呼ぶと描画を行いますが、`inline` 表示指定の場合、`show()` 関数を省略できます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 線グラフ\n", "\n", "`pyplot` モジュールの **`plot()`** 関数を用いて、リストの要素の数値をy軸の値として**グラフ**を描画します。y軸の値に対応するx軸の値は、リストの各要素のインデックスとなっています。\n", "\n", "具体的には、次のようにすることで `リストA` のインデックス `i` に対して、`(i, リストA[i])` の位置に点を打ち、各点を線でつなぎます。\n", "\n", "---\n", "```Python\n", "plt.plot(リストA)\n", "```\n", "---\n", "\n", "たとえば、次のようになります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# plotするデータ\n", "d =[0, 1, 4, 9, 16]\n", "\n", "# plot関数で描画\n", "plt.plot(d); \n", "# セルの最後に評価されたオブジェクトの出力表示を抑制するために、以下ではセルの最後の行にセミコロン (`;`) をつけています。\n", "# 試しにセミコロンを消した場合も試してみてください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`plot()` 関数では、x, y の両方の軸の値を引数に渡すこともできます。\n", "\n", "具体的には、次のように `リストX` と `リストY` を引数として与えると、各 `i` に対して、 `(リストX[i], リストY[i])` の位置に点を打ち、各点を線でつなぎます。\n", "\n", "---\n", "```Python\n", "plt.plot(リストX, リストY)\n", "```\n", "---\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# plotするデータ\n", "x =[0, 1, 2, 3, 4]\n", "y =[0, 3, 6, 9, 12]\n", "\n", "# plot関数で描画\n", "plt.plot(x,y); " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "リストの代わりに**NumPy**ライブラリの配列を与えても同じ結果が得られます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# plotするデータ\n", "x =[0, 1, 2, 3, 4]\n", "aryx = np.array(x) # リストから配列を作成\n", "y =[0, 3, 6, 9, 12]\n", "aryy = np.array(y) # リストから配列を作成\n", "\n", "# plot関数で描画\n", "plt.plot(aryx, aryy); " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のようにグラフを複数まとめて表示することもできます。複数のグラフを表示すると、線ごとに異なる色が自動で割り当てられます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# plotするデータ\n", "data =[0, 1, 4, 9, 16]\n", "x =[0, 1, 2, 3, 4]\n", "y =[0, 1, 2, 3, 4]\n", "# plot関数で描画。\n", "plt.plot(x, y)\n", "plt.plot(data);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`plot()` 関数ではグラフの線の色、形状、データポイントのマーカの種類を、それぞれ以下のように `linestyle`, `color`, `marker` 引数で指定して変更することができます。それぞれの引数で指定可能な値は以下を参照してください。\n", "\n", "- [linestyle](https://matplotlib.org/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D.set_linestyle)\n", "- [color](https://matplotlib.org/api/colors_api.html?highlight=color#module-matplotlib.colors)\n", "- [marker](https://matplotlib.org/api/markers_api.html#module-matplotlib.markers)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# plotするデータ\n", "data =[0, 1, 4, 9, 16]\n", "x =[0, 1, 2, 3, 4]\n", "y =[0, 1, 2, 3, 4]\n", "\n", "# plot関数で描画。線の形状、色、データポイントのマーカ指定\n", "plt.plot(x,y, linestyle='--', color='blue', marker='o') \n", "plt.plot(data, linestyle=':', color='green', marker='*');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`plot()` 関数の `label` 引数にグラフの各線の凡例を文字列として渡し、**`legend()`** 関数を呼ぶことで、グラフ内に凡例を表示できます。`legend()` 関数の `loc` 引数で凡例を表示する位置を指定することができます。引数で指定可能な値は以下を参照してください。\n", "\n", "- [lengend()関数](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.legend.html#matplotlib.pyplot.legend)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# plotするデータ\n", "data =[0, 1, 4, 9, 16]\n", "x =[0, 1, 2, 3, 4]\n", "y =[0, 1, 2, 3, 4]\n", "\n", "# plot関数で描画。線の形状、色、データポイントのマーカ指定\n", "plt.plot(x,y, linestyle='--', color='blue', marker='o', label='linear') \n", "plt.plot(data, linestyle=':', color='green', marker='*', label='quad')\n", "#凡例を表示\n", "plt.legend();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`pyplot` モジュールでは、以下のようにグラフのタイトルと各軸のラベルを指定して表示することができます。タイトル、x軸のラベル、y軸のラベル、はそれぞれ **`title()`** 関数、**`xlabel()`** 関数、**`ylabel()`** 関数に文字列を渡して指定します。また、**`grid()`** 関数を用いるとグリッドを併せて表示することもできます。グリッドを表示させたい場合は、`grid()` 関数に `True` を渡してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# plotするデータ\n", "data =[0, 1, 4, 9, 16]\n", "x =[0, 1, 2, 3, 4]\n", "y =[0, 1, 2, 3, 4]\n", "\n", "# plot関数で描画。線の形状、色、データポイントのマーカ、凡例を指定\n", "plt.plot(x,y, linestyle='--', color='blue', marker='o', label='linear') \n", "plt.plot(data, linestyle=':', color='green', marker='*', label='quad')\n", "plt.legend()\n", "\n", "plt.title('My First Graph') # グラフのタイトル\n", "plt.xlabel('x') #x軸のラベル\n", "plt.ylabel('y') #y軸のラベル\n", "plt.grid(True); #グリッドの表示" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "グラフを描画するときのプロット数を増やすことで任意の曲線のグラフを作成することもできます。以下では、`numpy` モジュールの `arange()` 関数を用いて、$- \\pi$ から $\\pi$ の範囲を `0.1` 刻みでx軸の値を配列として準備しています。そのx軸の値に対して、`numpy` モジュールの `cos()` 関数と `sin()` 関数を用いて、y軸の値をそれぞれ準備し、cosカーブとsinカーブを描画しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# グラフのx軸の値となる配列\n", "x = np.arange(-np.pi, np.pi, 0.1)\n", "\n", "# 上記配列をcos, sin関数に渡し, y軸の値として描画\n", "plt.plot(x,np.cos(x))\n", "plt.plot(x,np.sin(x))\n", "\n", "plt.title('cos ans sin Curves') # グラフのタイトル\n", "plt.xlabel('x') #x軸のラベル\n", "plt.ylabel('y') #y軸のラベル\n", "plt.grid(True); #グリッドの表示" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "プロットの数を少なくすると、曲線は直線をつなぎ合わせることで描画されていることがわかります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = np.arange(-np.pi, np.pi, 0.5)\n", "plt.plot(x,np.cos(x), marker='o')\n", "plt.plot(x,np.sin(x), marker='o')\n", "plt.title('cos ans sin Curves')\n", "plt.xlabel('x')\n", "plt.ylabel('y')\n", "plt.grid(True);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### グラフの例:ソートアルゴリズムにおける比較回数" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import random\n", "\n", "def bubble_sort(lst):\n", " n = 0\n", " for j in range(len(lst) - 1):\n", " for i in range(len(lst) - 1 - j):\n", " n = n + 1\n", " if lst[i] > lst[i+1]:\n", " lst[i + 1], lst[i] = lst[i], lst[i+1]\n", " return n\n", "\n", "def merge_sort_rec(data, l, r, work):\n", " if l+1 >= r: \n", " return 0\n", " m = l+(r-l)//2\n", " n1 = merge_sort_rec(data, l, m, work)\n", " n2 = merge_sort_rec(data, m, r, work)\n", " n = 0\n", " i1 = l\n", " i2 = m\n", " for i in range(l, r):\n", " from1 = False\n", " if i2 >= r:\n", " from1 = True\n", " elif i1 < m:\n", " n = n + 1\n", " if data[i1] <= data[i2]:\n", " from1 = True\n", " if from1:\n", " work[i] = data[i1]\n", " i1 = i1 + 1\n", " else:\n", " work[i] = data[i2]\n", " i2 = i2 + 1\n", " for i in range(l, r):\n", " data[i] = work[i]\n", " return n1+n2+n\n", "\n", "def merge_sort(data):\n", " return merge_sort_rec(data, 0, len(data), [0]*len(data))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = np.arange(100, 1100, 100)\n", "bdata = np.array([bubble_sort([random.randint(1,10000) for i in range(k)]) for k in x])\n", "mdata = np.array([merge_sort([random.randint(1,10000) for i in range(k)]) for k in x])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.plot(x, bdata, marker='o')\n", "plt.plot(x, mdata, marker='o')\n", "plt.title('bubble sort vs. merge sort')\n", "plt.xlabel('number of items')\n", "plt.ylabel('number of comparisons')\n", "plt.grid(True);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "`-2` から `2` の範囲を `0.1` 刻みでx軸の値を配列として作成し、そのx軸の値に対して `numpy` モジュールの `exp()` 関数を用いてy軸の値を作成し、$y=e^{x}$ のグラフを描画する関数 `plot_exp` を作成してください。ただし、そのグラフに任意のタイトル、x軸、y軸の任意のラベル、任意の凡例、グリッドを表示させてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "import ...\n", "...\n", "def plot_exp():\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "res_x = plot_exp()\n", "print(len(res_x) == 41, int(res_x[0]) == -2, int(res_x[9]) == -1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "4-csvで説明したように、`tokyo-temps.csv` には、気象庁のオープンデータからダウンロードした、東京の平均気温のデータが入っています。具体的には、各行の第2列に気温の値が格納されており、47行目に1875年6月の、48行目に1875年7月の、…、53行目に1875年12月の、54行目に1876年1月の、…という風に2017年1月のデータまでが格納されています。\n", "\n", "そこで、2つの整数 `year` と `month` を引数として取り、 `year` 年以降の `month` 月の平均気温の値をy軸に、年をx軸に描画した線グラフを表示するとともに、描画したx軸とy軸の値をタプルに格納して返す関数 `plot_tokyotemps` を作成してください。 \n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "import ...\n", "...\n", "def plot_tokyotemps(year, month):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "res_years, res_temps = plot_tokyotemps(1875, 7)\n", "print(len(res_years) == 142, len(res_temps) == 142, res_years[0] == 1875, res_temps[0] == 26.0)\n", "res_years, res_temps = plot_tokyotemps(1875, 6)\n", "print(len(res_years) == 142, len(res_temps) == 142, res_years[0] == 1875, res_temps[0] == 22.3)\n", "res_years, res_temps = plot_tokyotemps(1875, 12)\n", "print(len(res_years) == 142, len(res_temps) == 142, res_years[0] == 1875, res_temps[0] == 4.6)\n", "res_years, res_temps = plot_tokyotemps(1876, 1)\n", "print(len(res_years) == 142, len(res_temps) == 142, res_years[0] == 1876, res_temps[0] == 1.6)\n", "res_years, res_temps = plot_tokyotemps(1876, 6)\n", "print(len(res_years) == 141, len(res_temps) == 141, res_years[0] == 1876, res_temps[0] == 18.5)\n", "res_years, res_temps = plot_tokyotemps(1900, 6)\n", "print(len(res_years) == 117, len(res_temps) == 117, res_years[0] == 1900, res_temps[0] == 19.3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 散布図\n", "**散布図**は、`pyplot` モジュールの **`scatter()`** 関数を用いて描画できます。\n", "\n", "\n", "具体的には、次のように `リストX` と `リストY` (もしくは、 `配列X` と `配列Y`)を引数として与えると、各 `i` に対して、 `(リストX[i], リストY[i])` の位置に点を打ちます。\n", "\n", "---\n", "```Python\n", "plt.scatter(リストX, リストY)\n", "```\n", "---\n", "\n", "以下では、ランダムに生成した20個の要素からなる配列 x, y の各要素の値の組を点としてプロットした散布図を表示しています。プロットする点のマーカの色や形状は、線グラフの時と同様に、 `color`, `marker` 引数で指定して変更することができます。加えて、`s`, `alpha` 引数で、それぞれマーカの大きさと透明度を指定することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# グラフのx軸の値となる配列\n", "x = np.random.rand(20)\n", "# グラフのy軸の値となる配列\n", "y = np.random.rand(20)\n", "\n", "# scatter関数で散布図を描画\n", "plt.scatter(x, y, s=100, alpha=0.5);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下のように、`plot()` 関数を用いても同様の散布図を表示することができます。具体的には、3番目の引数にプロットする点のマーカの形状を指定することにより実現します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = np.random.rand(20)\n", "y = np.random.rand(20)\n", "plt.plot(x, y, '*', color='blue');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "`tokyo-temps.csv` には、気象庁のオープンデータからダウンロードした、東京の平均気温のデータが入っています。具体的には、各行の第2列に気温の値が格納されており、47行目に1875年6月の、48行目に1875年7月の、…、53行目に1875年12月の、54行目に1876年1月の、…という風に2017年1月のデータまでが格納されています。\n", "\n", "そこで、1875年以降の平均気温の値をy軸に、月の値をx軸に描画した散布図を表示するとともに、描画したx軸とy軸の値をタプルに格納して返す関数 `scatter_tokyotemps` を作成してください。 \n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "import ...\n", "...\n", "def scatter_tokyotemps():\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "res_months, res_temps = scatter_tokyotemps()\n", "print(len(res_months) == 1700, len(res_temps) == 1700, res_months[0] == 6, res_months[1] == 7, res_months[12] == 6, res_months[13] == 7)\n", "print(res_temps[0] == 22.3, res_temps[1] == 26.0, res_temps[12] == 18.5, res_temps[13] == 24.3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 棒グラフ\n", "**棒グラフ**は、`pyplot` モジュールの **`bar()`** 関数を用いて描画できます。以下では、ランダムに生成した10個の要素からなる配列 `y` の各要素の値を縦の棒グラフで表示しています。`x` は、x軸上で棒グラフのバーの並ぶ位置を示しています。ここでは、`numpy` モジュールの `arange()` 関数を用いて、`1` から `10` の範囲を `1` 刻みでx軸上のバーの並ぶ位置として配列を準備しています。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# x軸上で棒の並ぶ位置となる配列\n", "x = np.arange(1, 11, 1)\n", "# グラフのy軸の値となる配列\n", "y = np.random.rand(10)\n", "\n", "# bar関数で棒グラフを描画\n", "#print(x, y)\n", "plt.bar(x,y);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "`tokyo-temps.csv` には、気象庁のオープンデータからダウンロードした、東京の平均気温のデータが入っています。具体的には、各行の第2列に気温の値が格納されており、47行目に1875年6月の、48行目に1875年7月の、…、53行目に1875年12月の、54行目に1876年1月の、…という風に2017年1月のデータまでが格納されています。\n", "\n", "そこで、4つの引数 `year1`, `month1`, `year2`, `month2` を引数に取り、 `year1` 年 `month1` 月から `year2` 年 `month2` 月までの各月の平均気温の値をy軸に、年月の値(`tokyo-temps.csv` の1列目の値)をx軸に描画した棒グラフを表示するとともに、描画したx軸とy軸の値をタプルに格納して返す関数 `bar_tokyotemps` を作成してください。 \n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "import ...\n", "...\n", "def bar_tokyotemps(year1, month1, year2, month2):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "res_months, res_temps = bar_tokyotemps(2000, 6, 2001, 6)\n", "print(len(res_months) == 13, res_months[0] == '2000/6', res_temps[0] == 22.5, res_months[12] == '2001/6', res_temps[12] == 23.1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ヒストグラム\n", "\n", "**ヒストグラム**は、`pyplot` モジュールの **`hist()`** 関数を用いて描画できます。\n", "以下では、`numpy` モジュールの `random.randn()` 関数を用いて、正規分布に基づく1000個の数値の要素からなる配列を用意し、ヒストグラムとして表示しています。\n", "`hist()` 関数の `bins` 引数でヒストグラムの箱(ビン)の数を指定します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 正規分布に基づく1000個の数値の要素からなる配列 \n", "d = np.random.randn(1000)\n", "\n", "# hist関数でヒストグラムを描画\n", "plt.hist(d, bins=20);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "`tokyo-temps.csv` には、気象庁のオープンデータからダウンロードした、東京の平均気温のデータが入っています。具体的には、各行の第2列に気温の値が格納されており、47行目に1875年6月の、48行目に1875年7月の、…、53行目に1875年12月の、54行目に1876年1月の、…という風に2017年1月のデータまでが格納されています。\n", "\n", "そこで、5つの引数 `year1`, `month1`, `year2`, `month2`, `mybin` を引数に取り、 `year1` 年 `month1` 月から `year2` 年 `month2` 月までの各月の平均気温の値を格納したリスト `temps` から `mybin` 個のヒストグラムを表示するとともに、 `temps` を返す関数 `hist_tokyotemps` を作成してください。 \n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "import ...\n", "...\n", "def hist_tokyotemps(year1, month1, year2, month2, mybin):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "res_temps = hist_tokyotemps(1875, 6, 2000, 6, 50)\n", "print(len(res_temps) == 1501, res_temps[0] == 22.3, res_temps[1500] == 22.5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## ヒートマップ\n", "`impshow()` 関数を用いると、以下のように行列の要素の値に応じて色の濃淡を変えることで、行列を**ヒートマップ**として可視化することができます。`colorbar()` 関数は行列の値と色の濃淡の対応を表示します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 10行10列のランダム要素からなる行列\n", "ary1 = np.random.rand(100)\n", "ary2 = ary1.reshape(10,10)\n", "#ary2 = np.random.rand(100).reshape(10,10) #と同じ\n", "\n", "# imshow関数でヒートマップを描画\n", "im=plt.imshow(ary2)\n", "plt.colorbar(im);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "`tokyo-temps.csv` には、気象庁のオープンデータからダウンロードした、東京の平均気温のデータが入っています。具体的には、各行の第2列に気温の値が格納されており、47行目に1875年6月の、48行目に1875年7月の、…、53行目に1875年12月の、54行目に1876年1月の、…という風に2017年1月のデータまでが格納されています。\n", "\n", "そこで、30×12のNumPyの配列 `ary1` を作成し、各月の平均気温を整数に丸めた値を求めて、月ごとにその値の数を数えて配列 `ary1` に格納して、 `ary1` からなるヒートマップを表示しつつ、 `ary1` を返す関数 `heat_tokyotemps` を作成してください。 ただし、厳密には `x` が `0` 以上 `11` 以下の任意の整数とし、`y` を `0` 以上 `29` 以下の整数とするとき、 `ary1[y][x]` には、 `y` ℃以上、 `y+1` ℃より小さい平均気温を持つ `x+1` 月の数が格納されているものとします。\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "import ...\n", "...\n", "def heat_tokyotemps():\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "ary1 = heat_tokyotemps()\n", "print(ary1[0][0] == 2, ary1[1][1] == 2, ary1[2][0] == 28)\n", "#画像の向きが気になる人は、以下の2行を同時に実行してみてください\n", "#ary1 = np.flip(ary1, axis=0) \n", "#im=plt.imshow(ary1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## グラフの画像ファイル出力\n", "**`savefig()`** 関数を用いると、以下のように作成したグラフを画像としてファイルに保存することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = np.arange(-np.pi, np.pi, 0.1)\n", "plt.plot(x,np.cos(x), label='cos')\n", "plt.plot(x,np.sin(x), label='sin')\n", "plt.legend()\n", "plt.title('cos ans sin Curves') \n", "plt.xlabel('x') \n", "plt.ylabel('y') \n", "plt.grid(True)\n", "\n", "# savefig関数でグラフを画像保存\n", "plt.savefig('cos_sin.png'); " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "\n", "def plot_exp():\n", " x = np.arange(-2, 2.1, 0.1)\n", " y = np.exp(x)\n", " plt.plot(x, y, linestyle='--', color='blue', marker='x', label='exp(x)')\n", " plt.title('y = exp(x)') # タイトル\n", " plt.xlabel('x') # x軸のラベル\n", " plt.ylabel('exp(x)') # y軸のラベル\n", " plt.grid(True); # グリッドを表示\n", " plt.legend() # 盆例を表示\n", " return x" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "import csv\n", "\n", "def plot_tokyotemps(year, month):\n", " with open('tokyo-temps.csv', 'r', encoding='sjis') as f:\n", " dataReader = csv.reader(f) # csvリーダを作成\n", " n=0\n", " # 1875年6月が47行目なので、指定されたyear年6月のデータの行番号をまず求める\n", " init_row = (year - 1875) * 12 + 47 \n", " # その上で、year年month月のデータの行番号を求める\n", " init_row = init_row + month - 6\n", " years = [] # 年\n", " temps = [] # 平均気温\n", " for row in dataReader: # CSVファイルの中身を1行ずつ読み込み\n", " n = n+1\n", " if n >= init_row and (n - init_row) % 12 == 0: # init_row行目からはじめて12か月ごとにif内を実行\n", " years.append(year)\n", " temp = float(row[1]) # float関数で実数のデータ型に変換する\n", " temps.append(temp)\n", " year = year + 1\n", " #print(years)\n", " #print(temps)\n", " plt.plot(years, temps)\n", " return years, temps" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "import csv\n", "\n", "def scatter_tokyotemps():\n", " with open('tokyo-temps.csv', 'r', encoding='sjis') as f:\n", " dataReader = csv.reader(f) # csvリーダを作成\n", " n=0\n", " months = [] # 月\n", " temps = [] # 平均気温\n", " month = 6 # 47行目は6月\n", " for row in dataReader: # CSVファイルの中身を1行ずつ読み込み\n", " n = n+1\n", " if n >= 47: # 47行目からif内を実行\n", " months.append(month)\n", " temp = float(row[1]) # float関数で実数のデータ型に変換する\n", " temps.append(temp)\n", " month = month + 1\n", " if month > 12:\n", " month = 1\n", " #print(months)\n", " #print(temps)\n", " plt.scatter(months, temps, alpha=0.5)\n", " return months, temps" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "import csv\n", "\n", "def bar_tokyotemps(year1, month1, year2, month2):\n", " with open('tokyo-temps.csv', 'r', encoding='sjis') as f:\n", " dataReader = csv.reader(f) # csvリーダを作成\n", " n=0\n", " months = [] # \n", " temps = [] # 平均気温\n", " init_row = (year1 - 1875) * 12 - 6 + month1 + 47\n", " end_row = (year2 - 1875) * 12 - 6 + month2 + 47\n", " for row in dataReader: # CSVファイルの中身を1行ずつ読み込み\n", " n = n+1\n", " if n >= init_row and n <= end_row: # init_row行目から、end_row行までif内を実行\n", " months.append(row[0])\n", " temp = float(row[1]) # float関数で実数のデータ型に変換する\n", " temps.append(temp)\n", " #print(months)\n", " #print(temps)\n", " plt.bar(months, temps)\n", " return months, temps" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "import csv\n", "\n", "def hist_tokyotemps(year1, month1, year2, month2, mybin):\n", " with open('tokyo-temps.csv', 'r', encoding='sjis') as f:\n", " dataReader = csv.reader(f) # csvリーダを作成\n", " n=0\n", " months = [] # \n", " temps = [] # 平均気温\n", " init_row = (year1 - 1875) * 12 - 6 + month1 + 47\n", " end_row = (year2 - 1875) * 12 - 6 + month2 + 47\n", " for row in dataReader: # CSVファイルの中身を1行ずつ読み込み\n", " n = n+1\n", " if n >= init_row and n <= end_row: # init_row行目から、end_row行までif内を実行\n", " temp = float(row[1]) # float関数で実数のデータ型に変換する\n", " temps.append(temp)\n", " #print(months)\n", " #print(temps)\n", " plt.hist(temps, bins=mybin)\n", " return temps" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "import csv\n", "\n", "def heat_tokyotemps():\n", " ary1 = np.zeros(30*12, dtype=int) # 30×12の配列を作成\n", " ary1 = ary1.reshape(30, 12)\n", " with open('tokyo-temps.csv', 'r', encoding='sjis') as f:\n", " dataReader = csv.reader(f) # csvリーダを作成\n", " n=0\n", " month = 6 # 一番最初の月(47行目)は6月\n", " for row in dataReader: # CSVファイルの中身を1行ずつ読み込み\n", " n = n+1\n", " if n >= 47: # 47行目からif内を実行\n", " temp = int(float(row[1])) # まずfloat関数で実数型に変換してから、int関数で整数のデータ型に変換する\n", " ary1[temp][month-1] += 1 # month月の値はmonth-1行目に格納する\n", " month += 1\n", " if month == 13:\n", " month = 1\n", " im=plt.imshow(ary1)\n", " plt.colorbar(im);\n", " #print(ary1)\n", " return ary1" ] } ], "metadata": { "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.12.4" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: colab/appendix/5-re.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "##================================================\n", "## このセルを最初に実行せよ---Run this cell first.\n", "##================================================\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/text-sample.txt\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/small.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/tokyo-july-temps.csv\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/argsprint.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/B1S.xml\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sample.py\n", "!wget -P . https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/sin.html\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/console_in_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_open_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_3.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_mac_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_win2_2.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/argsprint.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/terminal_in_menu.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/sample_py_browser.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_1.png\n", "!wget -P fig https://raw.githubusercontent.com/utokyo-ipp/utokyo-ipp.github.io/master/colab/appendix/fig/py_conv_2.png" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# ▲正規表現\n", "正規表現について説明します。\n", "\n", "参考\n", "\n", "- https://docs.python.jp/3/library/re.html\n", "\n", "**正規表現** (regular expression) を扱う場合、`re` というモジュールをインポートする必要があります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 正規表現の基本\n", "\n", "正規表現とは、文字列の**パターン**を表す式です。\n", "文字列が正規表現に**マッチする**とは、文字列が正規表現の表すパターンに適合していることを意味します。\n", "また、正規表現が文字列にマッチするという言い方もします。\n", "\n", "たとえば、正規表現 `abc` は文字列 `abcde` (の部分文字列 `abc`)にマッチします。\n", "\n", "正規表現に文字列がマッチしているかどうかを調べることのできる関数に **`match`** があります。\n", "\n", "`match` は、指定した `正規表現A` が `文字列B`(の先頭部分)にマッチするかどうか調べます。\n", "\n", "---\n", "```Python\n", "re.match(正規表現A, 文字列B)\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.match('abc', 'abcde') #マッチする\n", "print(match1)\n", "match1 = re.match('abc', 'ababc') #マッチしない\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`match` では、マッチが成立している場合、**matchオブジェクト**と呼ばれる特殊なデータを返します。マッチが成立しない場合、 `None` を返します。\n", "\n", "つまり、マッチする部分文字列を含む場合、返値は `None` ではないので、if文などの条件で真とみなされます。\n", "したがって以下のようにして条件分岐することができます。\n", "\n", "---\n", "```Python\n", "if re.match(正規表現, 文字列):\n", " ...\n", "```\n", "---\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if re.match('abc', 'abcde'): #マッチする\n", " print('正規表現abcが文字列abcdeにマッチする')\n", "else:\n", " print('正規表現abcが文字列abcdeにマッチしない')\n", "if re.match('abc', 'ababc'): #マッチしない\n", " print('正規表現abcが文字列ababcにマッチする')\n", "else:\n", " print('正規表現abcが文字列ababcにマッチしない')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "さて、上で紹介したmatchオブジェクトには、マッチした文字列の情報が格納されています。上のセルの1つ目の実行結果を印字したものを見てください。\n", "\n", "`<_sre.SRE_Match object; span=(0, 3), match='abc'>` と表示されていると思います。このオブジェクト内の `match` という値は、マッチした文字列を、 `span` という値はマッチしたパターンが存在する、文字列のインデックスの範囲を表します。\n", "\n", "正規表現では大文字と小文字は区別されます。たとえば、正規表現 `abc` は文字列 `ABCdef` にはマッチしません。勿論、正規表現 `ABC` も文字列 `abcdef` にはマッチしません。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.match('abc', 'ABCdef')\n", "print(match1)\n", "match1 = re.match('ABC', 'abcdef')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "そこで `match` の3番目の引数として **`re.IGNORECASE`** もしくは **`re.I`** を指定すると、大文字と小文字を区別せずにマッチするかどうかを調べることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.match('abc', 'ABCdef', re.IGNORECASE)\n", "print(match1)\n", "match1 = re.match('ABC', 'abcdef', re.IGNORECASE)\n", "print(match1)\n", "match1 = re.match('ABC', 'ABCdef', re.IGNORECASE)\n", "print(match1)\n", "match1 = re.match('abc', 'ABCdef', re.I)\n", "print(match1)\n", "match1 = re.match('ABC', 'abcdef', re.I)\n", "print(match1)\n", "match1 = re.match('ABC', 'ABCdef', re.I)\n", "print(match1)\n", "match1 = re.match('AbC', 'aBcdef', re.I)\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`match` は文字列の先頭がマッチするかどうか調べますので、次のような場合、matchオブジェクトを返さずに `None` が返されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.match('def', 'abcdef')\n", "print(match1)\n", "match1 = re.match('xyz', 'abcdef')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列の先頭しか調べられないのでは、いかにも不便です。\n", "\n", "そこで、関数 **`search`** は、指定した `正規表現A` が `文字列B` に(文字列の先頭以外でも)マッチするかどうか調べることができます。\n", "\n", "---\n", "```Python\n", "re.search(正規表現A, 文字列B)\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('abc', 'abcdef')\n", "print(match1)\n", "match1 = re.search('abc', 'ababcd')\n", "print(match1)\n", "match1 = re.search('def', 'abcdef')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`search` の場合も3番目の引数として `re.IGNORECASE`、 もしくは `re.I` を指定することで、大文字と小文字を区別せずにマッチするかどうかを調べることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('abc', 'ABCdef')\n", "print(match1)\n", "match1 = re.search('DEF', 'abcdef')\n", "print(match1)\n", "match1 = re.search('abc', 'ABCdef', re.IGNORECASE)\n", "print(match1)\n", "match1 = re.search('DEF', 'abcdef', re.I)\n", "print(match1)\n", "match1 = re.search('not', 'It is NOT me.', re.I)\n", "print(match1)\n", "match1 = re.search('NOT', 'It is not mine.', re.I)\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`match` 関数と同様に、 `search` 関数においても、if文を使った条件分岐が可能であることは覚えておいてください。\n", "\n", "---\n", "```Python\n", "if re.search(正規表現, 文字列):\n", " ...\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if re.search('not', 'It is NOT me.'):\n", " print('正規表現notが文字列It is NOT me.にマッチする')\n", "else:\n", " print('正規表現notが文字列It is NOT me.にマッチしない')\n", "if re.search('not', 'It is NOT me.', re.I):\n", " print('正規表現notが文字列It is NOT me.にマッチする')\n", "else:\n", " print('正規表現notが文字列It is NOT me.にマッチしない')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字列の先頭からのマッチを調べたいときには、正規表現の先頭にキャレット (`^`) をつけてください。また、文字列の最後からマッチさせたいときは、正規表現の最後にドル記号 (`$`) をつけてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('abc', 'ababcd') #キャレットなしだとマッチする\n", "print(match1)\n", "match1 = re.search('^abc', 'ababcd') #キャレットありだとマッチしない\n", "print(match1)\n", "match1 = re.search('def', 'abcdefg') #ドル記号なしだとマッチする\n", "print(match1)\n", "match1 = re.search('def$', 'abcdefg') #ドル記号ありだとマッチしない\n", "print(match1)\n", "match1 = re.search('def$', 'abcdefxyzdef') # 2つあるうちの2番目(最後)の def にマッチする\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ただ、ここまでの内容だと、正規表現を用いずに文字列のメソッド (`find` など)によっても実現が可能です。これでは正規表現を使うメリットはほとんどありません。\n", "\n", "というのも、ここまで見てきた1つの正規表現によって、1つの文字列を表していたからです。しかし、最初に言った通り、正規表現は文字列の「パターン」を表します。すなわち、1つの正規表現で複数の文字列を表すことが可能なのです。\n", "\n", "たとえば、正規表現 `ab` と正規表現 `de` という2つの正規表現を `|` という記号で繋げた `ab|de` も正規表現を表します。この正規表現では、`ab` と `de` という2つの文字列を表しており、これらのいずれかを含む文字列にマッチします。この `|` の記号(演算)を**和**、もしくは**選択**といいます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('ab|de', 'bcdef')\n", "print(match1)\n", "match1 = re.search('ab|de', 'abcdef')\n", "print(match1)\n", "match1 = re.search('ab|de', 'fgdeab')\n", "print(match1)\n", "match1 = re.search('ab|de', 'acdf')\n", "print(match1)\n", "match1 = re.search('a|an|the', 'I slipped on a piece of the banana.')\n", "print(match1)\n", "match1 = re.search('a|an|the', 'I slipped on the banana.')\n", "print(match1)\n", "match1 = re.search('Good (Morning|Evening)', 'Good Evening, Vietnam.') #正規表現内の()については下で述べます\n", "print(match1)\n", "match1 = re.search('colo(u|)r', 'That color matches your suit.') #正規表現内の()については下で述べます\n", "print(match1)\n", "match1 = re.search('colo(u|)r', 'That colour matches your suit.') #正規表現内の()については下で述べます\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上記の3番目の例に注意してください。正規表現 `ab | de` では `ab` が `de` よりも先に記述されていますが、マッチする文字列は文字列上で先に出てきた方(`ab` ではなく、`de`)であることに注意してください。\n", "\n", "細かい話ですが、正規表現 `abc` は、正規表現 `a` と正規表現 `b` と正規表現 `c` という3つの正規表現を繋げて構成された正規表現であり、このように正規表現を繋げて新しい正規表現を作る演算を**連接**といいます。\n", "\n", "**`a*`** は、正規表現 `a` を0回以上繰り返した文字列とマッチします。この `*` の演算を**閉包**といいます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('a*', 'abcdef')\n", "print(match1)\n", "match1 = re.search('a*', 'aabbcc')\n", "print(match1)\n", "match1 = re.search('a*', 'cde')\n", "print(match1)\n", "match1 = re.search('bo*', 'boooo!')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上記の3番目の例において(文字 `a` が含まれていないにも関わらず)`None` が返らずに、マッチしているのを不思議に思うかもしれません。しかし、`a*` は `a` を0回反復した文字列にもマッチします。この0回反復した文字列とは、長さが0の文字列であり、**空列**とか**空文字列**と呼ばれます。文字列 `cde` の先頭には、空列があると見なせるので、`a*` が先頭部分にマッチしているのです。\n", "\n", "たとえば、正規表現 `abb*` は、 `ab`, `abb`, `abbb`, ... という文字列にマッチします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('abb*', 'abcdef')\n", "print(match1)\n", "match1 = re.search('abb*', 'aabbcc')\n", "print(match1)\n", "match1 = re.search('abb*', 'cde')\n", "print(match1)\n", "match1 = re.search('hello*', 'Hi, hellooooo!')\n", "print(match1)\n", "match1 = re.search('hello*', 'Hi, good morning!')\n", "print(match1)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "これまでに紹介した連接、和、閉包という3つの演算を組み合わせることで様々な正規表現を記述することができますが、これらの演算には結合の強さが存在します。たとえば、先に見た `ab | cd` という正規表現は、 `ab` もしくは `cd` という文字列にマッチします(`(ab)|(cd)` と同じ意味です)。つまり、連接の方が和よりも強く結合しているのです。そこで、丸括弧を使って `a(b|c)d` とすると、この正規表現は、`abd | acd` と同じ意味になります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('ab|de', 'fgdeab')\n", "print(match1)\n", "match1 = re.search('(ab)|(de)', 'fgdeab')\n", "print(match1)\n", "match1 = re.search('a(b|d)e', 'fgdeab')\n", "print(match1)\n", "match1 = re.search('a(b|d)e', 'fgadeab')\n", "print(match1)\n", "match1 = re.search('abe|ade', 'fgadeab')\n", "print(match1)\n", "match1 = re.search(\"(I|i)t('s| is| was)\", \"It was rainy yesterday, but it's fine today.\")\n", "print(match1)\n", "match1 = re.search(\"(I|i)t('s| is| was)\", \"It rained yesterday, but it's fine today.\")\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "演算の結合の強さは、「和 < 連接 < 閉包」という順序になっています。これは数学の、「和(+)< 積(×) < べき」と同じですので、直感的にもわかりやすいと思います。これまでに紹介した連接、和、閉包という3つの演算と結合の順序を明記する丸括弧 `()` とを組み合わせることで様々な正規表現を記述することができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('a(bc|b)*', 'defabcxyz')\n", "print(match1)\n", "match1 = re.search('a(bc|b)*', 'bbacbabbbbc')\n", "print(match1)\n", "match1 = re.search('ca(r|t(egory|tle|))', 'What category is this cat in?')\n", "print(match1)\n", "match1 = re.search('ca(r|t(egory|tle|))', 'No, this is not a carpet.')\n", "print(match1)\n", "match1 = re.search('ca(r|t(egory|tle|))', 'We saw a cattle car almost hit the cat.')\n", "print(match1)\n", "match1 = re.search('ca(r|t(egory|tle|))', 'Please locate him.')\n", "print(match1)\n", "match1 = re.search('ca(r|t(egory|tle|))', \"Don't play castanets.\")\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pythonでは正規表現は文字列によって表していることに注意してください。たとえば、`match` 関数の第一引数を文字列の変数で置き換えられるということです。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.match('abc', 'abcde') \n", "print(match1)\n", "reg1 = 'abc' # 正規表現を文字列で記述する\n", "match2 = re.match(reg1, 'abcde') #match1と同じ結果になる\n", "print(match2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "このことを覚えておくと複雑な正規表現を書くときに、少しずつ分解して記述することができて便利です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search(\"(I|i)t('s| is| was)\", \"It was rainy yesterday, but it's fine today.\")\n", "print(match1)\n", "reg1 = '(I|i)t' # 正規表現の前半部分\n", "reg2 = \"('s| is| was)\" # 正規表現の後半部分\n", "reg3 = reg1 + reg2 # 正規表現を表す2つの文字列を結合する\n", "print(reg3)\n", "match2 = re.search(reg3, \"It was rainy yesterday, but it's fine today.\")\n", "print(match2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `str1` を引数として取り、 `str1` の中に「月を表す文字列」が含まれているかどうか調べて、含まれていればマッチしたときのmatchオブジェクトを、含まれいなければ `None` を返す関数 `check_monthstr` を作成してください。 ただし、「月を表す文字列」 は次のような文字列とします。\n", "\n", "1. 長さ2の `mm` という文字列\n", "2. `mm` は、`00`, `01`, ..., `12` のいずれかの文字列\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def check_monthstr(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_monthstr('10').group() == '10') # group()については後半に説明があります(オプショナル)\n", "print(check_monthstr('mon1521vb') == None)\n", "print(check_monthstr('00an23') == None)\n", "print(check_monthstr('13302').group() == '02') " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `str1` を引数として取り、 `str1` を構成する文字列が `A`, `C`, `G`, `T` の4種類の文字以外の文字を含むかどうか調べて、これら以外を含む場合は `False` を、そうでない場合は `True` を返す関数 `check_ACGTstr` を作成してください。 ただし、大文字と小文字は区別しません。また、空列の場合は `False` を返してください。\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def check_ACGTstr(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_ACGTstr('AcCGTAGCacATcGgAaaTtGCacT') == True) \n", "print(check_ACGTstr(':ACaacgta24FgtGH') == False)\n", "print(check_ACGTstr('') == False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `str1` を引数として取り、 `str1` の中に「時刻を表す文字列」が含まれているかどうか調べて、含まれていればマッチしたときのmatchオブジェクトを、含まれいなければ `None` を返す関数 `check_timestr` を作成してください。 ただし、「時刻を表す文字列」 は次のような文字列とします。\n", "\n", "1. 長さ5の `hh:mm` という文字列であり、12時間表示で時間を表す。\n", "2. 前半の2文字 `hh` は、 `00`, `01`, ..., `11` のいずれかの文字列\n", "3. 後半の2文字 `mm` は、 `00`, `01`, ..., `59` のいずれかの文字列\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def check_timestr(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_timestr('10:23').group() == '10:23') # group()については後半に説明があります(オプショナル)\n", "print(check_timestr('time?1023') == None)\n", "print(check_timestr('time?11:23').group() == '11:23')\n", "print(check_timestr('12:3xx1;23ah23:23') == None)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `str1` を引数として取り、`str1` の中に「IPv4を表す文字列」が含まれているかどうか調べて、含まれていればマッチしたときのmatchオブジェクトを、含まれいなければ `None` を返す関数 `check_ipv4str` を作成してください。 ただし、「IPv4を表す文字列」 は次のような文字列とします。\n", "\n", "1. `aaa:bbb:ccc:ddd` という形式の長さ15の文字列\n", "2. `aaa`, `bbb`, `ccc`, `ddd` はいずれも、 `000`, `001`, ..., `254`, `255` のいずれかの文字列\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def check_ipv4str(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_ipv4str('IP=255:255:255:255').group() == '255:255:255:255') \n", "print(check_ipv4str('notIP=2x5:a5b:2c:255:14:444') == None)\n", "print(check_ipv4str('IP?=25:25:55:155') == None)\n", "print(check_ipv4str('IP?=255:255:255') == None) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `str1` を引数として取り、 `str1` の中に「月と日を表す文字列」が含まれているかどうか調べて、含まれていればマッチしたときのmatchオブジェクトを、含まれいなければ `None` を返す関数 `check_monthdaystr` を作成してください。 ただし、「月と日を表す文字列」 は次のような文字列とします。\n", "\n", "1. `mm/dd` という長さ5の文字列\n", "2. `mm` は、 `01`, `02`, ..., `12` のいずれかの文字列\n", "3. `dd` は、`mm` が `01`, `03`, `05`, `07`, `08`, `10`, `12` ならば、`01`, `02`, ..., `31` のいずれかの文字列\n", "4. `dd` は、`mm` が `04`, `06`, `09`, `11` ならば、`01`, `02`, ..., `30` のいずれかの文字列\n", "5. `dd` は、`mm` が `02` ならば、`01`, `02`, ..., `29` のいずれかの文字列\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def check_monthdaystr(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_monthdaystr('year11/31month11/30day15hour/27minute/sec').group() == '11/30')\n", "print(check_monthdaystr('11/31') == None)\n", "print(check_monthdaystr('x02f/2d5ax') == None)\n", "print(check_monthdaystr('03/24').group() == '03/24')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 文字クラス\n", "\n", " `[abc]` は `a|b|c` と同じ意味の正規表現です。この角括弧を用いた表記は、**文字クラス**と呼ばれます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('[abc]', 'defabcxyz')\n", "print(match1)\n", "match1 = re.search('[3456]', '1234567890')\n", "print(match1)\n", "match1 = re.search('ha[sd]', 'He has an apple and they have pineapples.')\n", "print(match1)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "勿論、これまでの和や閉包と組み合わせて用いることができます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('[def][abc]', 'defabcxyz')\n", "print(match1)\n", "match1 = re.search('4[3456][3456]([3456]|[7890])', '1234567890')\n", "print(match1)\n", "match1 = re.search('6[789]*', '1234567890')\n", "print(match1)\n", "match1 = re.search('she ha[sd]|they ha(ve|d)', 'He has an apple and they have pineapples.', re.I)\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ただし、文字クラスの中で連接、和、閉包は無効化されます。たとえば、`[a*]` という正規表現は、`a` もしくは、`*` にマッチします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('[a*]', 'aaaaaa') # a一文字にマッチ\n", "print(match1)\n", "match1 = re.search('[a*]', '*') # *一文字にマッチ\n", "print(match1)\n", "match1 = re.search('a*', 'aaaaaa')\n", "print(match1)\n", "match1 = re.search('a*', '*') # 文字クラスでない場合、*にはマッチしない\n", "print(match1)\n", "match1 = re.search('[a|b]', 'defabcxyz') # a一文字にマッチ\n", "print(match1)\n", "match1 = re.search('[a|b]', '|') # |一文字にマッチ\n", "print(match1)\n", "match1 = re.search('a|b', '|') # 文字クラスでない場合、|にはマッチしない\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字クラスでは一文字分の連続する和演算を表すことができますが、長さ2以上の文字列を表すことはできません。すなわち、`ab | cd` という正規表現を(1つの)文字クラスで表すことはできません。\n", "\n", "また、 `[abcdefg]` や `[gcdbeaf]` などは `[a-g]`、`[1234567]` や `[4271635]` などは `[1-7]` などとハイフン (`-`) を用いることで簡潔に表すことができます。たとえば、全てのアルファベットと数字を表す場合は、`[a-zA-Z0-9]` で表されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('[a-c]', 'defabcxyz')\n", "print(match1)\n", "match1 = re.search('3[4-8]', '1234567890')\n", "print(match1)\n", "match1 = re.search(':[a-zA-Z0-9]*:', 'a1b2c3:d4e5f:6g7A8B:9C0D')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "文字クラスの内側をキャレット (`^`) で始めると、**否定文字クラス**となり、キャレットの後ろに指定した文字以外の文字とマッチする正規表現となります。たとえば、`[^abc]` は `a`, `b`, `c` 以外の1文字とマッチする正規表現です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('[^abc]', 'abcdefxyz')\n", "print(match1)\n", "match1 = re.search('[^def]', 'defabcxyz')\n", "print(match1)\n", "match1 = re.search('[^1-7]', '1234567890')\n", "print(match1)\n", "match1 = re.search('ha[^sd]e', 'He has an apple and they have pineapples.')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "キャレットを先頭以外につけた場合は、単なる文字クラスになります。すなわち、キャレットにマッチするかどうかが判定されます。たとえば、`[d^ef]` は、`d`, `^`, `e`, `f` のいずれかにマッチします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('[d^ef]', 'defabcxyz') \n", "print(match1)\n", "match1 = re.search('[d^ef]', 'a^bcdef') # キャレットにマッチする\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 正規表現に関する基本的な関数\n", "\n", "上で紹介した正規表現を利用してマッチする文字列が存在するかどうかを調べるだけではなく、マッチした文字列に対して色々な処理を加えることができます。以下では2つの基本的な関数を紹介します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `sub`\n", "\n", "**`sub`** は、`正規表現R` にマッチする `文字列A` 中の全ての文字列を、指定した `文字列B` で置き換えることができます。\n", "\n", "具体的には次のようにすると、\n", "\n", "---\n", "```Python\n", "re.sub(正規表現R, 置換する文字列B, 元になる文字列A)\n", "```\n", "---\n", "\n", "`R` とマッチする `A` 中の全ての文字列を `B` と置き換えることができます。置き換えられた結果の文字列(新たに作られて)が返値となります。(もちろん、もとの文字列 `A` は変化しません。)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "str1 = re.sub('[346]', 'x', '03-5454-68284') #3,4,6をxに置き換える\n", "print(str1)\n", "str1 = re.sub('[.,:;!?]', '', \"He has three pets: a cat, a dog and a giraffe, doesn't he?\") #句読点を削除する(空文字列に置き換える)\n", "print(str1)\n", "str1 = re.sub('\\(a\\)|あっとまーく|@', '@', 'accountnameあっとまーくtest.ecc.u-tokyo.ac.jp') # スパム回避の文字列を@に置き換える\n", "print(str1)# \\(と\\)の意味については、下記の「正規表現のエスケープシーケンス」の節を参照してください" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```Python\n", "re.sub(r'[ \\t\\n][ \\t\\n]*', ' ', str1)\n", "```\n", "とすると、文字列 `str1` の空白文字の並びがスペース1個に置き換わります。\n", "\n", "ここで、`r'[ \\t\\n][ \\t\\n]*'` という正規表現は、空白かタブか改行の***1回以上***の繰り返しのパターンを表します。つまり、`aa*` という形をした「1回以上の `a` という文字列とマッチする正規表現」は `a+` という `+` を使った正規表現で置き換えることが可能です。この `+` は後で正式に紹介します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "re.sub(r'[ \\t\\n][ \\t\\n]*', ' ', 'Hello,\\n World!\\tHow are you?')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以下では、HTMLやXMLのタグを消しています(空文字列に置き換えています)。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "re.sub(r'<[^>]*>', '', '\\nClick this\\n\\n')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`r'<[^>]*>'` という正規表現は、`<` の後に `>` 以外の文字の繰り返しがあって最後に `>` が来るというパターンを表します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `re.split`\n", "\n", "\n", "**`split`** は、`正規表現R` にマッチする文字列を区切り文字(デリミタ)として、`文字列A` を分割します。分割された文字列がリストに格納されて返値となります。\n", "\n", "具体的には次のように用います。\n", "\n", "---\n", "```Python\n", "re.split(正規表現R, 元になる文字列A)\n", "```\n", "---\n", "\n", "以下が典型例です。\n", "\n", "---\n", "```Python\n", "re.split(r'[^a-zA-Z][^a-zA-Z]*', 'Hello, World! How are you?')\n", "\n", "```\n", "---\n", "\n", "`[^a-zA-Z][^a-zA-Z]*` という正規表現は、英文字以外の文字が1回以上繰り返されている、というパターンを表します。\n", "この正規表現を Python の式の中で用いるときは、`r'[^a-zA-Z][^a-zA-Z]*'` という構文を用います。\n", "先頭の `r` については、以下の説明を参照してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list1 = re.split(' ', \"He has three pets a cat a dog and a giraffe doesn't he\")\n", "print(list1)\n", "list2 = re.split(r'[^a-zA-Z][^a-zA-Z]*', 'Hello, World! How are you?')\n", "print(list2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この例のように、返されたリストに空文字列が含まれる場合がありますので、注意してください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `r` を付ける理由\n", "\n", "さて、以上のような正規表現は、`'hello*'` のようにPythonの文字列として `re.split` や `re.sub` などの関数に与えればよいのですが、\n", "以下のように文字列の前に `r` を付けることが推奨されます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "r'hello*'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`r'hello*'` の場合は `r` を付けても付けなくても同じなのですが、\n", "以下のように `r` を付けるとエスケープすべき文字がエスケープシーケンスになった文字列が得られます。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "r'[ \\t\\n]+'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`\\t` が `\\\\t` に変わったことでしょう。`\\\\` はバックスラッシュを表すエスケープシーケンスです。\n", "`\\t` はタブという文字を表しますが、`\\\\t` はバックススラッシュと `t` という2文字から成る文字列です。\n", "この場合、正規表現を解釈する段階でバックスラッシュが処理されます。\n", "\n", "特に `\\` という文字そのものを正規表現に含めたいときは `\\\\` と書いた上で `r` を付けてください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "r'\\\\t t/'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "この場合、文字列の中に `\\` が2個含まれており、正規表現を解釈する段階で正しく処理されます。すなわち、`\\` という文字そのものを表します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "英語の文書が保存された `text-sample.txt` というファイルから読み込み、出現する単語のリストを返す関数 `get_engsentences` を作成してください。 ただし、***重複する単語を削除してはいけません***が、空文字列は除きます。また、リストは返す前に中身を昇順に並べ替えてください。\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def get_engsentences():\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "list1 = get_engsentences()\n", "print(len(list1) == 289)\n", "print(list1[0] == 'a')\n", "print(list1[100] == 'in')\n", "print(list1[288] == 'would')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "英語の文書が保存された `text-sample.txt` というファイルから読み込み、出現する単語のリストを返す関数 `get_engsentences2` を作成してください。 ただし、空文字列は除きます。また、リストは返す前に中身を昇順に並べ替えてください。\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def get_engsentences2():\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "list1 = get_engsentences2()\n", "print(len(list1) == 149)\n", "print(list1[0] == 'a')\n", "print(list1[100] == 'proclaim')\n", "print(list1[148] == 'would')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## その他の反復演算\n", "\n", "閉包以外の反復演算を説明します。\n", "\n", "**`a?`** は、正規表現 `a` を高々1回反復する文字列とマッチします。たとえば、`a(bc)?` は `a|abc` と同じ意味の正規表現です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('colou?r', 'colour')\n", "print(match1)\n", "match1 = re.search('colou?r', 'color')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`a+`** は、正規表現 `a` を1回以上反復する文字列とマッチします。つまり、`a+` は `aa*` と同じ意味の正規表現です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('boo+', 'boooo!')\n", "print(match1)\n", "match1 = re.search('boo+', 'bo!')\n", "print(match1)\n", "match1 = re.search('a+', 'abcdef')\n", "print(match1)\n", "match1 = re.search('a+', 'aabbcc')\n", "print(match1)\n", "match1 = re.search('a+', 'cde')\n", "print(match1)\n", "match1 = re.search('[^a-zA-Z]+', 'abc12345efg67hi89j0k')\n", "print(match1)\n", "match1 = re.search('[a-zA-Z]+', 'abc12345efg67hi89j0k')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上記の例を `*` を使う形に書き換えてみてください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`a{x,y}`**、は正規表現 `a` を `x` 回以上かつ `y` 回以下繰り返す文字列とマッチします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('bo{3,5}', 'booooooo!')\n", "print(match1)\n", "match1 = re.search('bo{3,5}', 'boo!')\n", "print(match1)\n", "match1 = re.search('a{2,5}', 'bacaad')\n", "print(match1)\n", "match1 = re.search('[0-9]{1,3},[0-9]{3,3}', '1,298円')\n", "print(match1)\n", "match1 = re.search('[0-9]{1,3},[0-9]{3,3}', '298円')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## メタ文字\n", "\n", "以下では、良く使うメタ文字(特殊文字)を紹介します。\n", " \n", " **`.`**(ピリオド)は、あらゆる文字にマッチします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('.', 'Hello')\n", "print(match1)\n", "match1 = re.search('3.*9', '1234567890')\n", "print(match1)\n", "match1 = re.search('ha(.|..)', 'He has an apple and they have pineapples.')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "ただし、文字クラスの中で `.` を用いても、あらゆる文字とはマッチせず、`*` の場合と同様に、ピリオドとマッチします。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('[.]', 'Hello')\n", "print(match1)\n", "match1 = re.search('[.]', '3.141592')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`\\t`** は タブを表します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('b\\t', 'a\tb\tc\td')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " **`\\s`** は**空白文字**(スペース、タブ、改行など)を表します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('b\\s', 'a\tb\tc\td')\n", "print(match1)\n", "match1 = re.search('a\\s\\s\\s', 'a\t  b\t c\td')\n", "print(match1)\n", "match1 = re.search('b\\s*', 'a\t  b\t c\td')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " **`\\S`** は `\\s` 以外の全ての文字を表します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('b\\S', 'a\tb\tbc\td')\n", "print(match1)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`\\w`** は `[a-zA-Z0-9_]` と同じ意味です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('\\w\\w', 'abcde')\n", "print(match1)\n", "match1 = re.search('b\\w*g', 'abcdefgh')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`\\W`** は `\\w` 以外の全ての文字を表します。すなわち、`[^a-zA-Z0-9_]` と同じ意味です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('g\\W*', 'ab defg hi jklm no p')\n", "print(match1)\n", "match1 = re.search('\\W\\w*\\W', 'ab defg hi jklm no p')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`\\d`** は `[0-9]` と同じ意味です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('\\d\\d\\d-\\d\\d\\d\\d', '153-8902')\n", "print(match1)\n", "match1 = re.search('\\d*-\\d*', '153-8902')\n", "print(match1)\n", "match1 = re.search('\\d\\d-\\d\\d\\d\\d-\\d\\d\\d\\d', '03-5454-6828')\n", "print(match1)\n", "match1 = re.search('\\d*-\\d*-\\d*', '03-5454-6828')\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**`\\D`** は `\\d` 以外の全ての文字を表します。すなわち、`[^0-9]` と同じ意味です。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('\\D*', 'He has 10 apples.')\n", "print(match1)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "文字列から数字列を切り出して、それを整数とみなして足し合せた結果を整数として返す関数 `sumnumbers` を定義してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def sumnumbers(s):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(sumnumbers(' 2 33 45, 67.9') == 156)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `str1` を引数として取り、`str1` を構成する文字列が `A`, `C`, `G`, `T` の4種類の文字以外の文字を含むかどうか調べて、これら以外を含む場合は `False`、そうでない場合は `True` を返す関数 `check_ACGTstr` を作成してください。 ただし、大文字と小文字は区別しません。また、空列の場合は `False` を返してください。\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def check_ACGTstr(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_ACGTstr('AcCGTAGCacATcGgAaaTtGCacT') == True) \n", "print(check_ACGTstr(':ACaacgta24FgtGH') == False)\n", "print(check_ACGTstr('') == False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `str1` を引数として取り、 `str1` を構成する文字列が「日本の郵便番号」を表す文字列になっている場合は、 `True` を返し、そうでない場合は `False` を返す関数 `check_postalcode` を作成してください。 ただし、「日本の郵便番号」は `abc-defg` という形になっており、`a`, `b`, `c`, `d`, `e`, `d`, `f`, `g` はそれぞれ `0` から `9` までの値になっています。\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def check_postalcode(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_postalcode('113-8654') == True) \n", "print(check_postalcode('119-110') == False)\n", "print(check_postalcode('abc-defg') == False)\n", "print(check_postalcode('〒153-0041') == False) \n", "print(check_postalcode('113-86547') == False) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `str1` を引数として取り、`str1` を構成する文字列が「本郷の内線番号」を表す文字列になっている場合は、 `True` を返し、そうでない場合は `False` を返す関数 `check_extension` を作成してください。 ただし、「本郷の内線番号」は `2abcd` という形になっており、`a`, `b`, `c`, `d` はそれぞれ `0` から `9` までの値になっています。\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def check_extension(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_extension('24115') == True) \n", "print(check_extension('46858') == False)\n", "print(check_extension('☎46666') == False) \n", "print(check_extension('467890') == False) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 正規表現のエスケープシーケンス\n", "\n", "丸括弧 `()` や演算子 (`|`, `*`) など正規表現の中で特殊な役割を果たす記号のマッチを行いたい場合、文字列のエスケープシーケンスのように `\\` を前につけてやる必要があります。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('03(5454)6666', '03(5454)6666') #電話番号。つけないと丸括弧として扱われないのでマッチしない\n", "print(match1)\n", "match1 = re.search('03(5454)6666', '0354546666') # 括弧が含まれない文字列にマッチ\n", "print(match1)\n", "match1 = re.search('03\\(5454\\)6666', '03(5454)6666') # \\(と\\)で左右の丸括弧として扱われるのでマッチする\n", "print(match1)\n", "match1 = re.search('3*4+5=17', '3*4+5=17') #計算式。*と+が演算子扱いされているのでマッチしない\n", "print(match1)\n", "match1 = re.search('3*4+5=17', '33345=17') #\\がないと、たとえば、このような文字列とマッチする\n", "print(match1)\n", "match1 = re.search('3\\*4\\+5=17', '3*4+5=17') #意図した文字列にマッチ\n", "print(match1)\n", "match1 = re.search('|ω・`)チラ ', '|ω・`)チラ ') #顔文字。 空列にマッチしてしまう\n", "print(match1)\n", "match1 = re.search('\\|ω・`)チラ ', '|ω・`)チラ ') #意図した文字列にマッチ\n", "print(match1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "特殊な意味を持つ記号は次の14個です。\n", "\n", "`. ^ $ * + ? { } [ ] \\ | ( )`\n", "\n", "これらの特殊記号が含まれる場合(かつ意図したマッチの結果が得られない場合)には、エスケープシーケンスを使う(エスケープする)べき(可能性がある)ことも考慮に入れておいてください。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 正規表現に関する関数とメソッド \n", "\n", "以下では更に幾つかの関数とメソッドを紹介します。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `findall`\n", "\n", " **`findall`** は、`正規表現R` にマッチする `文字列A` 中の全ての文字列を、リストに格納して返します。\n", "\n", "具体的には次のように実行します。\n", "\n", "---\n", "```Python\n", "re.findall(正規表現R, 文字列A)\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "list1 = re.findall('had', 'James while John had had had had had had had had had had had a better effect on the teacher.')\n", "#James, while John had had 'had', had had 'had had'; 'had had' had had a better effect on the teacher.\n", "print(list1) #全てのhadを抜き出す\n", "list1 = re.findall('p[^ .]*', 'Peter Piper picked a peck of pickled peppers.', re.I) \n", "print(list1)# pで始まる全ての単語を取得する, 大文字小文字を区別しない" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `finditer`\n", "\n", " **`finditer`** は、`正規表現R` にマッチする `文字列A` 中の全ての matchオブジェクトを、特殊なリスト(のようなもの)に格納して返します。\n", "\n", "具体的には次のように実行します。\n", "\n", "---\n", "```Python\n", "re.finditer(正規表現R, 文字列A)\n", "```\n", "---\n", "\n", "返値は特殊なリスト(のようなもの)であり、for文の `in` の後ろに置いて使ってください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print('1:正規表現 had の結果:')\n", "iter1 = re.finditer('had', 'James while John had had had had had had had had had had had a better effect on the teacher.')\n", "#James, while John had had 'had', had had 'had had'; 'had had' had had a better effect on the teacher.\n", "for match in iter1:\n", " print(match) #全てのhadを抜き出す\n", "print('2:正規表現 p[^ .]* の結果:')\n", "iter1 = re.finditer('p[^ .]*', 'Peter Piper picked a peck of pickled peppers.', re.I) \n", "for match in iter1:\n", " print(match)# pで始まる全ての単語を取得する, 大文字小文字を区別しない" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `group`\n", "\n", "matchオブジェクトのメソッド **`group`** は、正規表現にマッチした文字列を(部分的に)取り出します。正規表現内に丸括弧を用いると、括弧内の正規表現とマッチした文字列を取得できるようになっています。なお、`group` によるこの操作を、括弧内の文字列を**キャプチャ**するといいます。\n", "\n", " `i` 番目のキャプチャした値を取得するには次のようにします。`i = 0` の場合は、マッチした文字列全体を取得できます。\n", "\n", "---\n", "```Python\n", "matchオブジェクト.group(i)\n", "```\n", "---" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "match1 = re.search('03-5454-(\\d\\d\\d\\d)', '03-5454-6666')\n", "print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1)) # 内線番号の取得 \n", "match1 = re.search('([^@]*)@[^.]*(\\.[^.]*)?\\.u-tokyo\\.ac\\.jp', 'accountname@test.ecc.u-tokyo.ac.jp') # \\.はピリオドを表します\n", "print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1)) # アカウント名の取得 \n", "match1 = re.search('([^@]*)@[^.]*(\\.[^.]*)?\\.u-tokyo\\.ac\\.jp', 'accountname@test.u-tokyo.ac.jp') # \\.はピリオドを表します\n", "print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1)) # アカウント名の取得 \n", "match1 = re.search(\"href=\\\"([^\\\"]*)\\\"\", 'U-Tokyo')# \\\"はダブルクォートを表します\n", "print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1)) # リンク先URLの取得\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "マッチに失敗した場合は、matchオブジェクトが返らずに `None` が返るので、それを確かめずに `group` を使おうとするとエラーが出ますので注意してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('03-5454-(\\d\\d\\d\\d)', '03-5454-666') #マッチしない文字列\n", "print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "たとえば、if文でエラーを回避します。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "match1 = re.search('03-5454-(\\d\\d\\d\\d)', '03-5454-666')\n", "if match1 != None:\n", " print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1))\n", "else: \n", " print('マッチしていません')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "文字列 `str1` を引数として取り、`str1` を構成する文字列が `A`, `C`, `G`, `T` の4種類の文字以外の文字を含むかどうか調べて、これら以外を含む場合は `False` を、そうでない場合は `True` を返す関数 `check_ACGTstr` を作成してください。 ただし、大文字と小文字は区別しません。また、空列の場合は `False` を返してください。\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def check_ACGTstr(str1):\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(check_ACGTstr('AcCGTAGCacATcGgAaaTtGCacT') == True) \n", "print(check_ACGTstr(':ACaacgta24FgtGH') == False)\n", "print(check_ACGTstr('') == False)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習\n", "\n", "xmlファイル B1S.xml は http://www.natcorp.ox.ac.uk から入手できるイギリス英語のコーパスのファイルです。\n", "\n", "B1S.xmlに含まれるwタグで囲まれる英単語をキー `key` に、その wタグの属性posの値を `key` の値とする辞書を返す関数 `get_pos` を作成してください。ただし、一般にwタグは、次のような形式で記述されます。\n", "\n", "---\n", "```\n", " 記号以外の何らかの文字列)>(英単語) \n", "```\n", "---\n", "\n", "たとえば、以下のような具合です。\n", "\n", "---\n", "```\n", "have \n", "```\n", "---\n", "\n", "\n", "以下のセルの `...` のところを書き換えて解答してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import ...\n", "def get_pos():\n", " ..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上のセルで解答を作成した後、以下のセルを実行し、実行結果が `True` になることを確認してください。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "raises-exception" ] }, "outputs": [], "source": [ "print(get_pos()['They '] == 'PRON')\n", "print(get_pos()['know '] == 'VERB')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 練習の解答" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "def check_monthstr(str1):\n", " reg_month = '((0(1|2|3|4|5|6|7|8|9))|10|11|12)' #\n", " #reg_month = '01|02|03|04|05|06|07|08|09|10|11|12' # としてもよい\n", " match1 = re.search(reg_month, str1) # 文字列を「含む」なので、(matchではなく)searchを使う\n", " return match1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "def check_timestr(str1):\n", " reg_hour = '((0(0|1|2|3|4|5|6|7|8|9))|10|11)' #「時」部分の正規表現\n", " #reg_hour = '((0[0-9]|10|11)' # 文字クラスを使ってと表すこともできます(文字クラスは後で学習します \n", " reg_min = '((0|2|3|4|5)(0|1|2|3|4|5|6|7|8|9))' #「分」部分の正規表現\n", " #reg_min = '([0-5][0-9])' # 文字クラスを使ってと表すこともできます(文字クラスは後で学習します \n", " reg_time = reg_hour + ':' + reg_min # 時部分と分部分を、「:」を挟んで結合した新しい正規表現\n", " #print(reg_time)\n", " match1 = re.search(reg_time, str1) # 文字列を「含む」なので、(matchではなく)searchを使う\n", " return match1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "def check_ipv4str(str1):\n", " reg_0to9 = '(0|1|2|3|4|5|6|7|8|9)' # 0から9の数を表す正規表現 \n", " #reg_0to9 = '[0-9]' # 文字クラスを使ってと表すこともできます(文字クラスは後で学習します \n", " reg_0_1 = '(0|1)' + reg_0to9 + reg_0to9 # 先頭の文字が0もしくは1だったときの正規表現(000から199まで)\n", " reg_20_24 = '2(0|1|2|3|4)' + reg_0to9 # 先頭が20,21,22,23,24だったときの正規表現(200から249まで)\n", " #reg_20_24 = '2[0-4]' + reg_0to9 # 文字クラスを使ってと表すこともできます\n", " reg_25 = '25(0|1|2|3|4|5)' # 先頭が25だったときの正規表現(250から255まで)\n", " #reg_25 = '25[0-5]' # 文字クラスを使ってと表すこともできます\n", " reg_000_255 = '(' + reg_0_1 + '|' + reg_20_24 + '|' + reg_25 + ')'# aaa(000から255)を表す正規表現\n", " #print(reg_000_255)\n", " reg_ip = reg_000_255 + ':' + reg_000_255 + ':' + reg_000_255 + ':' + reg_000_255 # aaa:bbb:ccc:dddを表す正規表現\n", " #print(reg_ip)\n", " match1 = re.search(reg_ip, str1) # 文字列を「含む」なので、(matchではなく)searchを使う\n", " return match1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "def check_monthdaystr(str1):\n", " reg_month_31 = '(01|03|05|07|08|10|12)' #ddが01から31になるmm\n", " reg_month_30 = '(04|06|09|11)' #ddが01から30になるmm\n", " reg_1to9 = '(1|2|3|4|5|6|7|8|9)' # [1-9]でもよい\n", " reg_0to9 = '(0|1|2|3|4|5|6|7|8|9)' # [0-9]でもよい\n", " reg_day_01to09 = '(0' + reg_1to9 + ')' # ddが01から09になる場合\n", " reg_day_10to19 = '(1' + reg_0to9 + ')' # ddが10から19になる場合\n", " reg_day_20to29 = '(2' + reg_0to9 + ')' # ddが21から29になる場合\n", " reg_day_01to29 = reg_day_01to09 + '|' + reg_day_10to19 + '|' + reg_day_20to29 # ddが01から29になる場合\n", " reg_day_01to30 = reg_day_01to29 + '|' + '30' # ddが01から30になる場合\n", " reg_day_01to31 = reg_day_01to30 + '|' + '31' # ddが01から31になる場合\n", " reg_monthday_31 = reg_month_31 + '/(' + reg_day_01to31 + ')' # mmとddを組み合わせる(01-31の場合)\n", " reg_monthday_30 = reg_month_30 + '/(' + reg_day_01to30 + ')' # mmとddを組み合わせる(01-30の場合)\n", " reg_monthday_29 = '02/(' + reg_day_01to29 + ')' # mmとddを組み合わせる(01-29の場合はmmは02のみ)\n", " # 文字列を「含む」なので、(matchではなく)searchを使う\n", " match1 = re.search(reg_monthday_31, str1) # 問題文の条件3を満たす文字列とマッチするかどうか\n", " if match1 != None:\n", " return match1\n", " match1 = re.search(reg_monthday_30, str1) # 問題文の条件4を満たす文字列とマッチするかどうか\n", " if match1 != None: \n", " return match1\n", " match1 = re.search(reg_monthday_29, str1) # 問題文の条件5を満たす文字列とマッチするかどうか\n", " return match1" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "def sumnumbers(s):\n", " numbers = re.split('[^0-9]+', s)\n", " numbers.remove('')\n", " n = 0\n", " for number in numbers:\n", " n += int(number)\n", " return n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "def get_engsentences():\n", " word_list = [] # 結果を格納するリスト\n", " with open('text-sample.txt', 'r') as f:\n", " file_str = f.read() #ファイルの中身を文字列に格納\n", " str_list = re.split(r'[^a-zA-Z][^a-zA-Z]*', file_str) # 文字列を単語に区切る\n", " for word in str_list: #`re.split(r'[^a-zA-Z][^a-zA-Z]*', f.read())` は、ファイル全体の文字列を単語に区切ります。\n", " #for word in re.split(r'[^a-zA-Z][^a-zA-Z]*', f.read()): # と一行にまとめてもよい\n", " if word != '': #空文字列を除く\n", " word = word.lower() #単語(文字列)の中の大文字を小文字に変換します\n", " word_list.append(word) #リストに追加 \n", " #word_list.append(word.lower())でも大丈夫\n", " word_list.sort() # sortメソッドは破壊的\n", " return word_list" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "def get_engsentences2():\n", " word_dict = {} # 重複する単語を削除する為に辞書を使ってみる\n", " with open('text-sample.txt', 'r') as f:\n", " file_str = f.read() #ファイルの中身を文字列に格納\n", " str_list = re.split(r'[^a-zA-Z][^a-zA-Z]*', file_str) # 文字列を単語に区切る\n", " for word in str_list: #`re.split(r'[^a-zA-Z][^a-zA-Z]*', f.read())` は、ファイル全体の文字列を単語に区切ります。\n", " if word != '': #空文字列を除く\n", " word = word.lower() #単語(文字列)の中の大文字を小文字に変換します\n", " word_dict[word] = 'anthing good' #wordという単語があったことを辞書に記録する(wordに対応する値は何でもよい)\n", " #word_dict[word.lower()] = 'anthing good'でも大丈夫\n", " word_list = [] # 結果を格納するリスト\n", " for word in word_dict:\n", " word_list.append(word)\n", " word_list.sort()\n", " return word_list" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "def check_ACGTstr(str1):\n", " reg_ACGT = '(A|C|G|T)+' # A,C,G,Tを表す正規表現 # +→* だと空文字列がマッチしてしまう \n", " #reg_ACGT = '(A|C|G|T)(A|C|G|T)*' # A,C,G,Tを表す正規表現 \n", " #reg_ACGT = '[ACGT]+' # A,C,G,Tを表す正規表現 \n", " match1 = re.search(reg_ACGT, str1, re.I) # re.I を入れて、大文字と小文字を区別しない\n", " if match1 != None and str1 == match1.group(): # str1全体とマッチした文字列が等しいかチェック\n", " return True\n", " return False\n", "#別解\n", "#def check_ACGTstr(str1):\n", "# reg_ACGT = '(A|C|G|T)+$' # A,C,G,Tを表す正規表現 # +→* だと空文字列がマッチしてしまう \n", "# #reg_ACGT = '(A|C|G|T)(A|C|G|T)*$' # A,C,G,Tを表す正規表現 \n", "# #reg_ACGT = '[ACGT]+$' # A,C,G,Tを表す正規表現 \n", "# match1 = re.search(reg_ACGT, str1, re.I) # re.I を入れて、大文字と小文字を区別しない\n", "# if match1 != None: # str1全体とマッチした文字列が等しいかチェック\n", "# return True\n", "# return False" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "def check_postalcode(str1):\n", " reg1 = '[0-9]{3,3}-[0-9]{4,4}'\n", " #reg1 = '\\d{3,3}-\\d{4,4}' #でも可\n", " #reg1 = '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]' #でも可\n", " match1 = re.match(reg1, str1)\n", " if match1 == None:\n", " return False\n", " if match1.group() == str1:\n", " return True\n", " return False\n", "#別解\n", "#def check_postalcode(str1):\n", "# reg1 = '[0-9]{3,3}-[0-9]{4,4}$' #ドル記号を使って行末からマッチを調べる\n", "# #reg1 = '\\d{3,3}-\\d{4,4}$' #でも可\n", "# #reg1 = '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$' #でも可\n", "# match1 = re.match(reg1, str1)\n", "# if match1 == None:\n", "# return False\n", "# return True" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "def check_extension(str1):\n", " reg1 = '2[0-9]{4,4}'\n", "# reg1 = '2\\d{4,4}' #でも可\n", "# reg1 = '2[0-9][0-9][0-9][0-9]' #でも可\n", " match1 = re.match(reg1, str1)\n", " if match1 == None:\n", " return False\n", " if match1.group() == str1:\n", " return True\n", " return False\n", "#別解\n", "#def check_extension(str1):\n", "# reg1 = '2[0-9]{4,4}$'\n", "# #reg1 = '2\\d{4,4}$' #でも可\n", "# #reg1 = '2[0-9][0-9][0-9][0-9]$' #でも可\n", "# match1 = re.match(reg1, str1)\n", "# if match1 == None:\n", "# return False\n", "# return True " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import re\n", "def get_pos():\n", " str_file = 'B1S.xml'\n", " with open(str_file, 'r', encoding='utf-8') as f:\n", " str_script = f.read() # ファイルの中身を1つの文字列に格納する\n", " #print(str_script)\n", " itr1 = re.finditer(\"]*pos=\\\"([^>\\\"]*)\\\"[^>]*>([^<]*)\", str_script) # 正規表現を使ってwタグ周辺の文字列をマッチ\n", " dic1 = {} # 辞書初期化\n", " for m1 in itr1:\n", " #print(m1)\n", " #print(m1.group(1), m1.group(2))\n", " dic1[m1.group(2)] = m1.group(1) # groupを使ってマッチした文字列をキャプチャする\n", " return dic1" ] } ], "metadata": { "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.12.4" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: colab/appendix/B1S.xml ================================================ Our family has Huntington's chorea. Sample containing about 676 words from a book (domain: social science) Data capture and transcription Oxford University Press BNC XML Edition, December 2006 676 tokens; 689 w-units; 47 s-units Distributed under licence by Oxford University Computing Services on behalf of the BNC Consortium. This material is protected by international copyright laws and may not be copied or redistributed in any way. Consult the BNC Web Site at http://www.natcorp.ox.ac.uk for full licencing and distribution conditions.B1S HuntCh Our family has Huntington's chorea. Slatford, Joy Graham-Cameron Publishing Cambridge 1987 2-24 W nonAc: soc scienceHuntington Huntingdon's chorea Tag usage updated for BNC-XMLLast check for BNC World first releaseRedo tagusage tablesCheck all tagcountsResequenced s-units and added headersAdded date infoUpdated all catrefsUpdated source titleUpdated titlescorrected tagUsagePOS codes revised for BNC-2; header updatedInitial accession to corpus

Everyone is ill sometimes.

At school, Nicola had a cold last week.

Adam broke his leg in the summer.

Iain had measles for two weeks.

Anthony gets headaches when he reads for too long.

Sometimes, when you are ill, the doctor comes to your home. If she thinks you need medicine the doctor will write a note so the medicine can be collected from the chemist.

At other times people have to go into hospital to have an operation to make them better.

But sometimes people have an illness which cannot be made better.

In our family we have a special illness. It is called Huntington's Chorea, or HC for short.

Peter and Paul's grandfather had HC. He was their Mum's dad and so their Mum could have HC from him.

HC is not catching, like measles. It is only if your Mum or Dad has it, that you may possible have it when you grown up, whether you are a boy or a girl.

There are other families like Peter and Paul's who have HC. They all joined together to make a group called COMBAT.

Combat means to fight, and they help each other to fight against this illness, by talking and finding out more about it, and having parties, too.

HC is not like other illnesses. Usually, it only happens to grown-ups. People with HC may be clumsy, or fall over a lot, or get very fidgety. Sometimes they may not be able to eat or talk very well. They can also be forgetful or very tired and perhaps bad tempered.

When people get it, they may have to go into hospital or a special home, to rest, or perhaps to stay.

Not everyone understands it is HC which makes people behave strangely. It is not their fault, it is the illness. It does not mean they don't love their families, but sometimes the HC stops them showing it.

When Peter and Paul's Mum sometimes get angry or clumsy, they don't know whether she is starting HC, or just worrying about starting HC.

HC normally begins after you are grown up, so you don't know whether you will get it or not.

If their Mum does have HC, Peter and Paul may get it later on. There is as much chance of them having it, as them not having it. The chances are the same for both of them.

But if she does not have it then they will never get it nor could their children.

If their Mum does get HC, Peter and Paul have a favourite Aunty who will help Daddy look after them and love them very much.

Peter and Paul will want to remember their Mummy as she was before she got ill, and how much she loved and cared about them when they were younger, even if the illness makes here different.

Peter and Paul do not want Mummy to be ill or to have HC themselves, but at the moment there is no sure way to know for everyone.

Doctors all over the world have been working to find a way to test whether people like Peter and Paul's Mum will have HC or not. This test is around now for some people.

Doctors are also trying to find ways to make people with HC better and everyone hopes they will.

In the meantime, families like Peter and Paul's have to think carefully about whether to have children themselves, or not.

Peter and Paul hope that by the time they are grown up, the doctors will know more about HC and how to stop it.

They know that other unhappy things can happen to people like road accidents or other illnesses.

It's not just their family which has worried. They will enjoy themselves and make the most of their lives like everyone else.

The family hopes Mum never gets HC. If she does she will need them to love her and to understand.

They also know other families with HC, and about COMBAT so they won't feel alone.

================================================ FILE: colab/appendix/argsprint.py ================================================ import sys print(sys.argv) ================================================ FILE: colab/appendix/sample.py ================================================ a1 = 10 print('a1 contains the value of', a1) ================================================ FILE: colab/appendix/sin.html ================================================ Bokeh Plot
================================================ FILE: colab/appendix/small.csv ================================================ 11,12,13,14,15 21,22,23,24,25 31,32,33,34,35 ================================================ FILE: colab/appendix/text-sample.txt ================================================ We, the Japanese People, acting through our duly elected representatives in the National Diet, determined that we shall secure for ourselves and our posterity the fruits of peaceful cooperation with all nations and the blessings of liberty throughout this land, and resolved that never again shall we be visited with the horrors of war through the action of government, do proclaim the sovereignty of the people's will and do ordain and establish this Constitution, founded upon the universal principle that government is a sacred trust the authority for which is derived from the people, the powers of which are exercised by the representatives of the people, and the benefits of which are enjoyed by the people; and we reject and revoke all constitutions, ordinances, laws and rescripts in conflict herewith. Desiring peace for all time and fully conscious of the high ideals controlling human relationship now stirring mankind, we have determined to rely for our security and survival upon the justice and good faith of the peace-loving peoples of the world. We desire to occupy an honored place in an international society designed and dedicated to the preservation of peace, and the banishment of tyranny and slavery, oppression and intolerance, for all time from the earth. We recognize and acknowledge that all peoples have the right to live in peace, free from fear and want. We hold that no people is responsible to itself alone, but that laws of political morality are universal; and that obedience to such laws is incumbent upon all peoples who would sustain their own sovereignty and justify their sovereign relationship with other peoples. To these high principles and purposes we, the Japanese People, pledge our national honor, determined will and full resources. ================================================ FILE: colab/appendix/tokyo-july-temps.csv ================================================ 1875,26.0 1876,24.3 1877,26.5 1878,26.0 1879,26.1 1880,24.2 1881,24.0 1882,24.2 1883,23.7 1884,23.4 1885,23.1 1886,25.0 1887,23.6 1888,24.5 1889,23.4 1890,23.5 1891,24.9 1892,25.7 1893,25.3 1894,26.8 1895,22.1 1896,24.1 1897,22.9 1898,25.9 1899,23.2 1900,22.8 1901,22.1 1902,21.8 1903,23.2 1904,24.8 1905,23.3 1906,23.5 1907,22.7 1908,22.1 1909,24.3 1910,23.0 1911,24.5 1912,24.3 1913,23.3 1914,25.5 1915,24.2 1916,23.9 1917,25.7 1918,26.0 1919,23.6 1920,26.1 1921,24.3 1922,25.0 1923,24.0 1924,26.1 1925,23.2 1926,24.6 1927,26.0 1928,23.4 1929,25.9 1930,26.3 1931,21.8 1932,25.7 1933,26.6 1934,23.9 1935,24.3 1936,24.9 1937,26.3 1938,25.0 1939,26.5 1940,26.9 1941,23.7 1942,27.5 1943,25.1 1944,25.6 1945,22.0 1946,26.2 1947,25.7 1948,26.0 1949,25.3 1950,26.5 1951,24.3 1952,24.3 1953,24.7 1954,22.3 1955,27.6 1956,24.2 1957,24.4 1958,24.9 1959,26.1 1960,25.8 1961,27.4 1962,25.1 1963,25.7 1964,25.5 1965,24.2 1966,24.4 1967,26.3 1968,24.7 1969,25.0 1970,25.4 1971,25.8 1972,25.2 1973,26.1 1974,23.4 1975,25.6 1976,23.9 1977,25.8 1978,27.8 1979,25.2 1980,23.8 1981,26.3 1982,23.1 1983,23.8 1984,26.2 1985,26.3 1986,23.9 1987,27.0 1988,22.4 1989,24.1 1990,25.7 1991,26.7 1992,25.5 1993,22.5 1994,28.3 1995,26.4 1996,26.2 1997,26.6 1998,25.3 1999,25.9 2000,27.7 2001,28.5 2002,28.0 2003,22.8 2004,28.5 2005,25.6 2006,25.6 2007,24.4 2008,27.0 2009,26.3 2010,28.0 2011,27.3 2012,26.4 2013,27.3 2014,26.8 2015,26.2 2016,25.4 ================================================ FILE: colab/appendix/tokyo-temps.csv ================================================ _E[hF2017/08/30 17:06:00 ,,, N,ϋC(),ϋC(),ϋC() ,,i,ώԍ 1872/1,,0,1 1872/2,,0,1 1872/3,,0,1 1872/4,,0,1 1872/5,,0,1 1872/6,,0,1 1872/7,,0,1 1872/8,,0,1 1872/9,,0,1 1872/10,,0,1 1872/11,,0,1 1872/12,,0,1 1873/1,,0,1 1873/2,,0,1 1873/3,,0,1 1873/4,,0,1 1873/5,,0,1 1873/6,,0,1 1873/7,,0,1 1873/8,,0,1 1873/9,,0,1 1873/10,,0,1 1873/11,,0,1 1873/12,,0,1 1874/1,,0,1 1874/2,,0,1 1874/3,,0,1 1874/4,,0,1 1874/5,,0,1 1874/6,,0,1 1874/7,,0,1 1874/8,,0,1 1874/9,,0,1 1874/10,,0,1 1874/11,,0,1 1874/12,,0,1 1875/1,,0,1 1875/2,,0,1 1875/3,,0,1 1875/4,,0,1 1875/5,,0,1 1875/6,22.3,4,1 1875/7,26.0,5,1 1875/8,24.9,8,1 1875/9,21.5,8,1 1875/10,15.3,8,1 1875/11,9.7,5,1 1875/12,4.6,8,1 1876/1,1.6,8,1 1876/2,3.4,5,1 1876/3,8.1,8,1 1876/4,12.2,8,1 1876/5,17.0,8,1 1876/6,18.5,8,1 1876/7,24.3,8,1 1876/8,26.6,8,1 1876/9,22.6,5,1 1876/10,14.8,5,1 1876/11,9.1,8,1 1876/12,4.8,8,1 1877/1,3.2,8,1 1877/2,3.6,8,1 1877/3,6.2,8,1 1877/4,13.6,8,1 1877/5,16.5,8,1 1877/6,22.0,8,1 1877/7,26.5,8,1 1877/8,25.9,8,1 1877/9,21.3,8,1 1877/10,15.9,8,1 1877/11,9.6,8,1 1877/12,5.8,8,1 1878/1,2.3,8,1 1878/2,2.5,8,1 1878/3,7.2,8,1 1878/4,11.5,8,1 1878/5,18.3,8,1 1878/6,20.0,8,1 1878/7,26.0,8,1 1878/8,24.6,8,1 1878/9,22.8,8,1 1878/10,15.8,8,1 1878/11,9.7,8,1 1878/12,5.1,8,1 1879/1,3.2,8,1 1879/2,5.4,8,1 1879/3,8.0,8,1 1879/4,12.6,8,1 1879/5,18.0,8,1 1879/6,21.4,5,1 1879/7,26.1,8,1 1879/8,26.6,8,1 1879/9,21.3,8,1 1879/10,15.0,8,1 1879/11,9.7,8,1 1879/12,8.0,8,1 1880/1,2.6,8,1 1880/2,5.8,8,1 1880/3,8.4,8,1 1880/4,12.3,8,1 1880/5,17.7,8,1 1880/6,19.8,8,1 1880/7,24.2,8,1 1880/8,25.5,8,1 1880/9,22.5,8,1 1880/10,16.6,8,1 1880/11,10.2,8,1 1880/12,3.9,8,1 1881/1,2.1,8,1 1881/2,3.7,8,1 1881/3,5.3,8,1 1881/4,11.6,8,1 1881/5,17.2,8,1 1881/6,21.3,8,1 1881/7,24.0,8,1 1881/8,26.7,8,1 1881/9,22.7,8,1 1881/10,15.7,8,1 1881/11,11.0,8,1 1881/12,4.3,8,1 1882/1,4.6,8,1 1882/2,5.2,8,1 1882/3,6.9,8,1 1882/4,13.7,8,1 1882/5,16.8,8,1 1882/6,20.4,8,1 1882/7,24.2,5,1 1882/8,24.7,5,1 1882/9,21.1,8,1 1882/10,15.4,8,1 1882/11,9.6,8,1 1882/12,5.0,8,1 1883/1,3.1,8,1 1883/2,1.9,8,1 1883/3,5.3,8,1 1883/4,12.0,8,1 1883/5,15.5,8,1 1883/6,19.8,8,1 1883/7,23.7,8,1 1883/8,25.1,8,1 1883/9,21.8,8,1 1883/10,16.7,8,1 1883/11,10.0,8,1 1883/12,5.0,8,1 1884/1,2.6,8,1 1884/2,2.7,8,1 1884/3,6.1,8,1 1884/4,11.6,8,1 1884/5,15.5,8,1 1884/6,19.8,8,1 1884/7,23.4,8,1 1884/8,24.1,8,1 1884/9,22.3,8,1 1884/10,15.8,8,1 1884/11,7.6,8,1 1884/12,3.4,8,1 1885/1,0.6,8,1 1885/2,2.2,5,1 1885/3,4.9,8,1 1885/4,10.7,8,1 1885/5,15.2,8,1 1885/6,20.3,8,1 1885/7,23.1,8,1 1885/8,25.4,8,1 1885/9,22.1,8,1 1885/10,16.1,8,1 1885/11,10.7,8,1 1885/12,5.7,8,1 1886/1,2.4,8,1 1886/2,2.0,8,1 1886/3,6.9,8,1 1886/4,12.3,8,1 1886/5,16.4,8,1 1886/6,20.9,8,1 1886/7,25.0,8,1 1886/8,26.5,8,1 1886/9,23.2,8,1 1886/10,16.6,8,1 1886/11,10.2,8,1 1886/12,4.7,8,1 1887/1,2.7,8,1 1887/2,4.3,8,1 1887/3,6.9,8,1 1887/4,12.2,8,1 1887/5,15.2,8,1 1887/6,20.3,8,1 1887/7,23.6,8,1 1887/8,25.3,8,1 1887/9,21.0,8,1 1887/10,16.6,8,1 1887/11,11.6,8,1 1887/12,5.7,8,1 1888/1,3.3,8,1 1888/2,2.2,8,1 1888/3,7.2,8,1 1888/4,12.4,8,1 1888/5,16.0,8,1 1888/6,18.6,8,1 1888/7,24.5,8,1 1888/8,25.6,8,1 1888/9,20.9,8,1 1888/10,15.0,8,1 1888/11,11.4,8,1 1888/12,5.2,8,1 1889/1,2.1,8,1 1889/2,3.1,8,1 1889/3,6.9,8,1 1889/4,12.0,8,1 1889/5,15.7,8,1 1889/6,20.9,8,1 1889/7,23.4,8,1 1889/8,25.8,8,1 1889/9,20.3,8,1 1889/10,14.6,8,1 1889/11,9.7,8,1 1889/12,4.9,8,1 1890/1,3.4,8,1 1890/2,6.1,8,1 1890/3,9.2,8,1 1890/4,14.2,8,1 1890/5,16.1,8,1 1890/6,22.0,8,1 1890/7,23.5,8,1 1890/8,25.4,8,1 1890/9,24.2,8,1 1890/10,16.0,8,1 1890/11,10.8,8,1 1890/12,9.3,8,1 1891/1,2.4,8,1 1891/2,3.8,8,1 1891/3,8.9,8,1 1891/4,12.0,8,1 1891/5,18.2,8,1 1891/6,20.3,8,1 1891/7,24.9,8,1 1891/8,25.5,8,1 1891/9,24.3,8,1 1891/10,16.5,8,1 1891/11,10.4,8,1 1891/12,5.6,8,1 1892/1,3.7,8,1 1892/2,4.1,8,1 1892/3,5.1,8,1 1892/4,13.1,8,1 1892/5,16.6,8,1 1892/6,21.1,8,1 1892/7,25.7,8,1 1892/8,26.4,8,1 1892/9,23.0,8,1 1892/10,16.5,8,1 1892/11,9.9,8,1 1892/12,3.3,8,1 1893/1,2.6,8,1 1893/2,2.2,8,1 1893/3,6.2,8,1 1893/4,13.3,8,1 1893/5,15.8,8,1 1893/6,20.5,8,1 1893/7,25.3,8,1 1893/8,26.2,8,1 1893/9,22.5,8,1 1893/10,15.9,8,1 1893/11,10.1,8,1 1893/12,4.7,8,1 1894/1,3.0,8,1 1894/2,3.7,8,1 1894/3,8.4,8,1 1894/4,13.8,8,1 1894/5,16.3,8,1 1894/6,23.6,8,1 1894/7,26.8,8,1 1894/8,27.0,8,1 1894/9,21.9,8,1 1894/10,15.4,8,1 1894/11,11.6,8,1 1894/12,5.8,8,1 1895/1,2.1,8,1 1895/2,4.0,8,1 1895/3,6.9,8,1 1895/4,12.9,8,1 1895/5,17.5,8,1 1895/6,20.4,8,1 1895/7,22.1,8,1 1895/8,25.5,8,1 1895/9,22.9,8,1 1895/10,16.5,8,1 1895/11,9.9,8,1 1895/12,5.4,8,1 1896/1,3.3,8,1 1896/2,3.5,8,1 1896/3,6.0,8,1 1896/4,13.7,8,1 1896/5,16.6,8,1 1896/6,21.6,8,1 1896/7,24.1,8,1 1896/8,25.9,8,1 1896/9,22.3,8,1 1896/10,15.8,8,1 1896/11,10.7,8,1 1896/12,4.8,8,1 1897/1,3.7,8,1 1897/2,3.5,8,1 1897/3,5.7,8,1 1897/4,11.3,8,1 1897/5,17.3,8,1 1897/6,18.8,8,1 1897/7,22.9,8,1 1897/8,25.0,8,1 1897/9,20.9,8,1 1897/10,15.2,8,1 1897/11,10.1,8,1 1897/12,3.7,8,1 1898/1,3.6,8,1 1898/2,4.4,8,1 1898/3,5.5,8,1 1898/4,11.2,8,1 1898/5,16.7,8,1 1898/6,19.2,8,1 1898/7,25.9,8,1 1898/8,26.1,8,1 1898/9,21.6,8,1 1898/10,16.0,8,1 1898/11,10.9,8,1 1898/12,6.4,8,1 1899/1,3.2,8,1 1899/2,4.2,8,1 1899/3,8.5,8,1 1899/4,12.8,8,1 1899/5,17.9,8,1 1899/6,21.5,8,1 1899/7,23.2,8,1 1899/8,26.1,8,1 1899/9,19.8,8,1 1899/10,14.3,8,1 1899/11,8.9,8,1 1899/12,5.5,8,1 1900/1,1.6,8,1 1900/2,3.1,8,1 1900/3,5.7,8,1 1900/4,11.4,8,1 1900/5,17.3,8,1 1900/6,19.3,8,1 1900/7,22.8,8,1 1900/8,26.1,8,1 1900/9,22.6,8,1 1900/10,16.5,8,1 1900/11,11.0,8,1 1900/12,5.5,8,1 1901/1,4.1,8,1 1901/2,3.7,8,1 1901/3,7.3,8,1 1901/4,13.4,8,1 1901/5,16.1,8,1 1901/6,20.6,8,1 1901/7,22.1,8,1 1901/8,25.1,8,1 1901/9,22.3,8,1 1901/10,16.8,8,1 1901/11,10.2,8,1 1901/12,4.5,8,1 1902/1,2.4,8,1 1902/2,3.8,8,1 1902/3,8.4,8,1 1902/4,11.6,8,1 1902/5,16.3,8,1 1902/6,19.8,8,1 1902/7,21.8,8,1 1902/8,22.9,8,1 1902/9,22.6,8,1 1902/10,16.6,8,1 1902/11,11.5,8,1 1902/12,7.1,8,1 1903/1,4.6,8,1 1903/2,4.1,8,1 1903/3,7.7,8,1 1903/4,12.7,8,1 1903/5,15.9,8,1 1903/6,19.7,8,1 1903/7,23.2,8,1 1903/8,25.7,8,1 1903/9,22.3,8,1 1903/10,15.2,8,1 1903/11,9.1,8,1 1903/12,4.1,8,1 1904/1,1.9,8,1 1904/2,4.3,8,1 1904/3,6.1,8,1 1904/4,13.2,8,1 1904/5,15.7,8,1 1904/6,21.8,8,1 1904/7,24.8,8,1 1904/8,25.1,8,1 1904/9,21.2,8,1 1904/10,16.4,8,1 1904/11,9.1,8,1 1904/12,5.3,8,1 1905/1,4.3,8,1 1905/2,2.7,8,1 1905/3,5.6,8,1 1905/4,10.9,8,1 1905/5,16.9,8,1 1905/6,20.8,8,1 1905/7,23.3,8,1 1905/8,22.2,8,1 1905/9,21.9,8,1 1905/10,16.2,8,1 1905/11,10.3,8,1 1905/12,6.8,8,1 1906/1,2.2,8,1 1906/2,2.6,8,1 1906/3,7.3,8,1 1906/4,12.9,8,1 1906/5,16.3,8,1 1906/6,18.4,8,1 1906/7,23.5,8,1 1906/8,24.5,8,1 1906/9,19.7,8,1 1906/10,15.1,8,1 1906/11,9.3,8,1 1906/12,5.9,8,1 1907/1,4.0,8,1 1907/2,2.9,8,1 1907/3,5.6,8,1 1907/4,12.4,8,1 1907/5,17.1,8,1 1907/6,19.2,8,1 1907/7,22.7,8,1 1907/8,25.8,8,1 1907/9,21.3,8,1 1907/10,15.2,8,1 1907/11,11.2,8,1 1907/12,4.5,8,1 1908/1,3.2,8,1 1908/2,3.4,8,1 1908/3,6.2,8,1 1908/4,12.3,8,1 1908/5,16.1,8,1 1908/6,20.9,8,1 1908/7,22.1,8,1 1908/8,25.4,8,1 1908/9,19.4,8,1 1908/10,16.1,8,1 1908/11,9.1,8,1 1908/12,4.6,8,1 1909/1,2.1,8,1 1909/2,3.1,8,1 1909/3,6.3,8,1 1909/4,13.6,8,1 1909/5,16.9,8,1 1909/6,20.2,8,1 1909/7,24.3,8,1 1909/8,25.2,8,1 1909/9,21.8,8,1 1909/10,14.8,8,1 1909/11,10.0,8,1 1909/12,4.6,8,1 1910/1,4.2,8,1 1910/2,2.9,8,1 1910/3,6.1,8,1 1910/4,12.3,8,1 1910/5,16.8,8,1 1910/6,20.7,8,1 1910/7,23.0,8,1 1910/8,24.1,8,1 1910/9,20.9,8,1 1910/10,16.1,8,1 1910/11,10.4,8,1 1910/12,4.3,8,1 1911/1,2.5,8,1 1911/2,5.2,8,1 1911/3,8.2,8,1 1911/4,13.8,8,1 1911/5,16.2,8,1 1911/6,20.8,8,1 1911/7,24.5,8,1 1911/8,25.6,8,1 1911/9,22.6,8,1 1911/10,15.8,8,1 1911/11,12.8,8,1 1911/12,5.0,8,1 1912/1,3.0,8,1 1912/2,6.2,8,1 1912/3,8.1,8,1 1912/4,13.0,8,1 1912/5,16.7,8,1 1912/6,20.1,8,1 1912/7,24.3,8,1 1912/8,25.2,8,1 1912/9,20.2,8,1 1912/10,15.9,8,1 1912/11,9.4,8,1 1912/12,4.7,8,1 1913/1,1.9,8,1 1913/2,4.5,8,1 1913/3,6.2,8,1 1913/4,13.6,8,1 1913/5,16.1,8,1 1913/6,20.3,8,1 1913/7,23.3,8,1 1913/8,23.8,8,1 1913/9,20.0,8,1 1913/10,15.6,8,1 1913/11,10.0,8,1 1913/12,5.2,8,1 1914/1,4.3,8,1 1914/2,3.5,8,1 1914/3,8.8,8,1 1914/4,11.8,8,1 1914/5,17.8,8,1 1914/6,21.5,8,1 1914/7,25.5,8,1 1914/8,26.4,8,1 1914/9,22.5,8,1 1914/10,16.1,8,1 1914/11,11.9,8,1 1914/12,5.8,8,1 1915/1,3.3,8,1 1915/2,4.1,8,1 1915/3,6.6,8,1 1915/4,11.6,8,1 1915/5,15.9,8,1 1915/6,21.9,8,1 1915/7,24.2,8,1 1915/8,25.7,8,1 1915/9,22.7,8,1 1915/10,17.6,8,1 1915/11,11.1,8,1 1915/12,5.6,8,1 1916/1,5.1,8,1 1916/2,4.1,8,1 1916/3,5.8,8,1 1916/4,12.7,8,1 1916/5,16.9,8,1 1916/6,22.7,8,1 1916/7,23.9,8,1 1916/8,25.0,8,1 1916/9,23.7,8,1 1916/10,15.8,8,1 1916/11,11.3,8,1 1916/12,6.8,8,1 1917/1,2.3,8,1 1917/2,4.5,8,1 1917/3,6.5,8,1 1917/4,12.7,8,1 1917/5,15.8,8,1 1917/6,19.6,8,1 1917/7,25.7,8,1 1917/8,25.0,8,1 1917/9,22.0,8,1 1917/10,16.8,8,1 1917/11,8.7,8,1 1917/12,4.0,8,1 1918/1,1.6,8,1 1918/2,3.6,8,1 1918/3,6.7,8,1 1918/4,11.7,8,1 1918/5,16.7,8,1 1918/6,20.1,8,1 1918/7,26.0,8,1 1918/8,26.1,8,1 1918/9,22.6,8,1 1918/10,16.0,8,1 1918/11,10.4,8,1 1918/12,3.9,8,1 1919/1,2.8,8,1 1919/2,3.7,8,1 1919/3,8.3,8,1 1919/4,13.4,8,1 1919/5,16.2,8,1 1919/6,19.8,8,1 1919/7,23.6,8,1 1919/8,25.0,8,1 1919/9,22.7,8,1 1919/10,16.4,8,1 1919/11,11.4,8,1 1919/12,5.3,8,1 1920/1,4.1,8,1 1920/2,2.6,8,1 1920/3,6.6,8,1 1920/4,12.6,8,1 1920/5,16.8,8,1 1920/6,20.3,8,1 1920/7,26.1,8,1 1920/8,25.7,8,1 1920/9,21.4,8,1 1920/10,16.4,8,1 1920/11,12.0,8,1 1920/12,5.2,8,1 1921/1,4.0,8,1 1921/2,3.5,8,1 1921/3,6.2,8,1 1921/4,13.8,8,1 1921/5,16.4,8,1 1921/6,18.8,8,1 1921/7,24.3,8,1 1921/8,25.3,8,1 1921/9,21.3,8,1 1921/10,15.4,8,1 1921/11,9.3,8,1 1921/12,5.0,8,1 1922/1,0.6,8,1 1922/2,7.0,8,1 1922/3,6.6,8,1 1922/4,13.3,8,1 1922/5,16.8,8,1 1922/6,21.7,8,1 1922/7,25.0,8,1 1922/8,27.3,8,1 1922/9,23.4,8,1 1922/10,16.8,8,1 1922/11,10.8,8,1 1922/12,4.0,8,1 1923/1,1.7,8,1 1923/2,3.0,8,1 1923/3,7.9,8,1 1923/4,12.0,8,1 1923/5,16.8,8,1 1923/6,20.4,8,1 1923/7,24.0,8,1 1923/8,27.2,8,1 1923/9,23.4,5,1 1923/10,16.8,8,1 1923/11,12.0,8,1 1923/12,5.6,8,1 1924/1,2.7,8,1 1924/2,4.5,8,1 1924/3,5.0,8,1 1924/4,14.7,8,1 1924/5,16.9,8,1 1924/6,19.4,8,1 1924/7,26.1,8,1 1924/8,26.2,8,1 1924/9,21.8,8,1 1924/10,15.4,8,1 1924/11,9.9,8,1 1924/12,5.2,8,1 1925/1,2.9,8,1 1925/2,2.4,8,1 1925/3,6.2,8,1 1925/4,11.9,8,1 1925/5,16.1,8,1 1925/6,20.1,8,1 1925/7,23.2,8,1 1925/8,25.7,8,1 1925/9,22.9,8,1 1925/10,16.3,8,1 1925/11,11.4,8,1 1925/12,6.8,8,1 1926/1,3.1,8,1 1926/2,4.6,8,1 1926/3,6.3,8,1 1926/4,11.1,8,1 1926/5,16.3,8,1 1926/6,19.0,8,1 1926/7,24.6,8,1 1926/8,26.3,8,1 1926/9,23.2,8,1 1926/10,15.0,8,1 1926/11,9.8,8,1 1926/12,4.1,8,1 1927/1,2.7,8,1 1927/2,2.1,8,1 1927/3,6.3,8,1 1927/4,13.5,8,1 1927/5,17.1,8,1 1927/6,20.5,8,1 1927/7,26.0,8,1 1927/8,26.6,8,1 1927/9,21.2,8,1 1927/10,16.7,8,1 1927/11,11.2,8,1 1927/12,5.5,8,1 1928/1,3.6,8,1 1928/2,3.3,8,1 1928/3,6.9,8,1 1928/4,12.5,8,1 1928/5,17.8,8,1 1928/6,20.3,8,1 1928/7,23.4,8,1 1928/8,24.1,8,1 1928/9,23.9,8,1 1928/10,16.7,8,1 1928/11,11.7,8,1 1928/12,5.4,8,1 1929/1,2.6,8,1 1929/2,2.9,8,1 1929/3,7.1,8,1 1929/4,12.6,8,1 1929/5,15.9,8,1 1929/6,20.6,8,1 1929/7,25.9,8,1 1929/8,27.1,8,1 1929/9,20.5,8,1 1929/10,16.5,8,1 1929/11,11.0,8,1 1929/12,8.6,8,1 1930/1,3.8,8,1 1930/2,5.4,8,1 1930/3,8.8,8,1 1930/4,14.0,8,1 1930/5,17.7,8,1 1930/6,21.4,8,1 1930/7,26.3,8,1 1930/8,26.8,8,1 1930/9,21.5,8,1 1930/10,16.7,8,1 1930/11,10.3,8,1 1930/12,5.2,8,1 1931/1,2.9,8,1 1931/2,2.5,8,1 1931/3,7.9,8,1 1931/4,12.4,8,1 1931/5,16.3,8,1 1931/6,20.4,8,1 1931/7,21.8,8,1 1931/8,26.4,8,1 1931/9,22.5,8,1 1931/10,16.3,8,1 1931/11,11.5,8,1 1931/12,6.9,8,1 1932/1,5.9,8,1 1932/2,4.3,8,1 1932/3,6.9,8,1 1932/4,12.3,8,1 1932/5,18.0,8,1 1932/6,19.8,8,1 1932/7,25.7,8,1 1932/8,26.7,8,1 1932/9,21.8,8,1 1932/10,16.5,8,1 1932/11,10.9,8,1 1932/12,6.0,8,1 1933/1,3.2,8,1 1933/2,3.6,8,1 1933/3,5.8,8,1 1933/4,12.3,8,1 1933/5,18.1,8,1 1933/6,21.9,8,1 1933/7,26.6,8,1 1933/8,27.5,8,1 1933/9,23.1,8,1 1933/10,16.8,8,1 1933/11,11.2,8,1 1933/12,6.2,8,1 1934/1,2.5,8,1 1934/2,4.0,8,1 1934/3,6.1,8,1 1934/4,11.5,8,1 1934/5,17.8,8,1 1934/6,22.0,8,1 1934/7,23.9,8,1 1934/8,26.1,8,1 1934/9,21.6,8,1 1934/10,14.6,8,1 1934/11,10.8,8,1 1934/12,5.9,8,1 1935/1,3.7,8,1 1935/2,4.8,8,1 1935/3,7.1,8,1 1935/4,12.5,8,1 1935/5,16.7,8,1 1935/6,21.5,8,1 1935/7,24.3,8,1 1935/8,24.8,8,1 1935/9,20.8,8,1 1935/10,17.1,8,1 1935/11,10.7,8,1 1935/12,5.5,8,1 1936/1,2.0,8,1 1936/2,2.5,8,1 1936/3,6.1,8,1 1936/4,12.0,8,1 1936/5,16.4,8,1 1936/6,21.4,8,1 1936/7,24.9,8,1 1936/8,26.5,8,1 1936/9,24.2,8,1 1936/10,16.0,8,1 1936/11,11.2,8,1 1936/12,6.2,8,1 1937/1,4.6,8,1 1937/2,5.7,8,1 1937/3,8.1,8,1 1937/4,12.8,8,1 1937/5,17.6,8,1 1937/6,19.6,8,1 1937/7,26.3,8,1 1937/8,28.2,8,1 1937/9,22.7,8,1 1937/10,16.3,8,1 1937/11,11.2,8,1 1937/12,5.2,8,1 1938/1,2.7,8,1 1938/2,3.4,8,1 1938/3,8.8,8,1 1938/4,13.2,8,1 1938/5,18.7,8,1 1938/6,20.8,8,1 1938/7,25.0,8,1 1938/8,26.0,8,1 1938/9,22.4,8,1 1938/10,16.7,8,1 1938/11,10.8,8,1 1938/12,5.9,8,1 1939/1,2.4,8,1 1939/2,4.1,8,1 1939/3,7.4,8,1 1939/4,12.8,8,1 1939/5,17.0,8,1 1939/6,20.7,8,1 1939/7,26.5,8,1 1939/8,25.8,8,1 1939/9,23.7,8,1 1939/10,17.9,8,1 1939/11,12.3,8,1 1939/12,5.4,8,1 1940/1,2.7,8,1 1940/2,3.7,8,1 1940/3,8.2,8,1 1940/4,13.1,8,1 1940/5,17.7,8,1 1940/6,22.1,8,1 1940/7,26.9,8,1 1940/8,24.9,8,1 1940/9,21.7,8,1 1940/10,17.8,8,1 1940/11,12.3,8,1 1940/12,6.2,8,1 1941/1,4.8,8,1 1941/2,5.0,8,1 1941/3,8.2,8,1 1941/4,12.7,8,1 1941/5,17.6,8,1 1941/6,20.8,8,1 1941/7,23.7,8,1 1941/8,25.4,8,1 1941/9,20.6,8,1 1941/10,17.3,8,1 1941/11,11.7,8,1 1941/12,6.9,8,1 1942/1,2.9,8,1 1942/2,2.6,8,1 1942/3,10.3,8,1 1942/4,13.6,8,1 1942/5,17.3,8,1 1942/6,22.2,8,1 1942/7,27.5,8,1 1942/8,27.0,8,1 1942/9,24.9,8,1 1942/10,16.4,8,1 1942/11,10.1,8,1 1942/12,5.4,8,1 1943/1,2.4,8,1 1943/2,4.0,8,1 1943/3,6.8,8,1 1943/4,11.8,8,1 1943/5,17.8,8,1 1943/6,21.5,8,1 1943/7,25.1,8,1 1943/8,27.4,8,1 1943/9,24.4,8,1 1943/10,17.2,8,1 1943/11,10.8,8,1 1943/12,5.7,8,1 1944/1,3.0,8,1 1944/2,3.2,8,1 1944/3,5.6,8,1 1944/4,10.6,8,1 1944/5,17.7,8,1 1944/6,22.3,8,1 1944/7,25.6,8,1 1944/8,27.5,8,1 1944/9,23.2,8,1 1944/10,16.3,8,1 1944/11,10.9,8,1 1944/12,4.3,8,1 1945/1,1.1,8,1 1945/2,1.6,8,1 1945/3,6.6,8,1 1945/4,13.5,8,1 1945/5,15.6,8,1 1945/6,20.4,8,1 1945/7,22.0,8,1 1945/8,26.7,8,1 1945/9,22.4,8,1 1945/10,16.8,8,1 1945/11,11.3,8,1 1945/12,4.8,8,1 1946/1,3.5,8,1 1946/2,4.2,8,1 1946/3,6.2,8,1 1946/4,14.3,8,1 1946/5,16.9,8,1 1946/6,23.3,8,1 1946/7,26.2,8,1 1946/8,26.7,8,1 1946/9,23.1,8,1 1946/10,17.3,8,1 1946/11,12.4,8,1 1946/12,4.7,8,1 1947/1,3.4,8,1 1947/2,2.7,8,1 1947/3,6.8,8,1 1947/4,13.1,8,1 1947/5,16.9,8,1 1947/6,19.2,8,1 1947/7,25.7,8,1 1947/8,28.0,8,1 1947/9,22.9,8,1 1947/10,15.6,8,1 1947/11,10.3,8,1 1947/12,4.1,8,1 1948/1,4.0,8,1 1948/2,5.1,8,1 1948/3,6.5,8,1 1948/4,14.2,8,1 1948/5,18.1,8,1 1948/6,21.6,8,1 1948/7,26.0,8,1 1948/8,25.4,8,1 1948/9,23.8,8,1 1948/10,17.4,8,1 1948/11,11.9,8,1 1948/12,7.9,8,1 1949/1,5.4,8,1 1949/2,6.5,8,1 1949/3,6.7,8,1 1949/4,12.1,8,1 1949/5,18.4,8,1 1949/6,19.4,8,1 1949/7,25.3,8,1 1949/8,26.6,8,1 1949/9,22.4,8,1 1949/10,16.1,8,1 1949/11,10.0,8,1 1949/12,6.0,8,1 1950/1,5.0,8,1 1950/2,4.7,8,1 1950/3,7.7,8,1 1950/4,13.9,8,1 1950/5,19.2,8,1 1950/6,21.8,8,1 1950/7,26.5,8,1 1950/8,26.2,8,1 1950/9,23.8,8,1 1950/10,15.8,8,1 1950/11,11.1,8,1 1950/12,5.4,8,1 1951/1,3.3,8,1 1951/2,4.5,8,1 1951/3,8.8,8,1 1951/4,13.3,8,1 1951/5,18.0,8,1 1951/6,21.2,8,1 1951/7,24.3,8,1 1951/8,26.7,8,1 1951/9,20.7,8,1 1951/10,17.3,8,1 1951/11,11.4,8,1 1951/12,7.3,8,1 1952/1,4.3,8,1 1952/2,2.6,8,1 1952/3,7.4,8,1 1952/4,13.3,8,1 1952/5,18.1,8,1 1952/6,21.3,8,1 1952/7,24.3,8,1 1952/8,26.8,8,1 1952/9,22.7,8,1 1952/10,17.3,8,1 1952/11,12.0,8,1 1952/12,5.3,8,1 1953/1,3.3,8,1 1953/2,4.2,8,1 1953/3,9.4,8,1 1953/4,12.7,8,1 1953/5,17.8,8,1 1953/6,20.6,8,1 1953/7,24.7,8,1 1953/8,25.0,8,1 1953/9,22.2,8,1 1953/10,17.2,8,1 1953/11,10.4,8,1 1953/12,7.6,8,1 1954/1,4.3,8,1 1954/2,5.6,8,1 1954/3,8.4,8,1 1954/4,14.9,8,1 1954/5,17.6,8,1 1954/6,18.3,8,1 1954/7,22.3,8,1 1954/8,27.0,8,1 1954/9,24.6,8,1 1954/10,15.5,8,1 1954/11,11.7,8,1 1954/12,7.1,8,1 1955/1,3.8,8,1 1955/2,6.2,8,1 1955/3,8.7,8,1 1955/4,13.6,8,1 1955/5,18.2,8,1 1955/6,22.7,8,1 1955/7,27.6,8,1 1955/8,26.3,8,1 1955/9,22.3,8,1 1955/10,17.6,8,1 1955/11,11.0,8,1 1955/12,7.9,8,1 1956/1,4.2,8,1 1956/2,4.3,8,1 1956/3,8.6,8,1 1956/4,13.1,8,1 1956/5,17.6,8,1 1956/6,22.3,8,1 1956/7,24.2,8,1 1956/8,25.4,8,1 1956/9,22.7,8,1 1956/10,17.3,8,1 1956/11,11.8,8,1 1956/12,5.0,8,1 1957/1,5.7,8,1 1957/2,4.3,8,1 1957/3,6.8,8,1 1957/4,14.3,8,1 1957/5,17.1,8,1 1957/6,19.8,8,1 1957/7,24.4,8,1 1957/8,27.3,8,1 1957/9,20.8,8,1 1957/10,17.2,8,1 1957/11,12.9,8,1 1957/12,8.0,8,1 1958/1,5.0,8,1 1958/2,6.0,8,1 1958/3,8.4,8,1 1958/4,13.9,8,1 1958/5,18.0,8,1 1958/6,22.0,8,1 1958/7,24.9,8,1 1958/8,25.8,8,1 1958/9,23.2,8,1 1958/10,16.0,8,1 1958/11,11.1,8,1 1958/12,7.9,8,1 1959/1,3.7,8,1 1959/2,7.3,8,1 1959/3,8.9,8,1 1959/4,15.3,8,1 1959/5,18.5,8,1 1959/6,20.4,8,1 1959/7,26.1,8,1 1959/8,26.7,8,1 1959/9,24.1,8,1 1959/10,17.6,8,1 1959/11,12.3,8,1 1959/12,7.0,8,1 1960/1,5.0,8,1 1960/2,6.6,8,1 1960/3,9.5,8,1 1960/4,12.8,8,1 1960/5,17.8,8,1 1960/6,21.5,8,1 1960/7,25.8,8,1 1960/8,26.4,8,1 1960/9,23.6,8,1 1960/10,16.8,8,1 1960/11,12.3,8,1 1960/12,6.7,8,1 1961/1,3.6,8,1 1961/2,4.5,8,1 1961/3,8.2,8,1 1961/4,14.9,8,1 1961/5,19.8,8,1 1961/6,22.6,8,1 1961/7,27.4,8,1 1961/8,26.8,8,1 1961/9,25.3,8,1 1961/10,18.3,8,1 1961/11,12.7,8,1 1961/12,7.2,8,1 1962/1,4.5,8,1 1962/2,5.9,8,1 1962/3,8.2,8,1 1962/4,14.1,8,1 1962/5,18.4,8,1 1962/6,20.9,8,1 1962/7,25.1,8,1 1962/8,28.1,8,1 1962/9,24.5,8,1 1962/10,16.7,8,1 1962/11,11.3,8,1 1962/12,7.0,8,1 1963/1,3.2,8,1 1963/2,4.8,8,1 1963/3,7.6,8,1 1963/4,13.9,8,1 1963/5,18.4,8,1 1963/6,21.8,8,1 1963/7,25.7,8,1 1963/8,26.6,8,1 1963/9,21.4,8,1 1963/10,16.3,8,1 1963/11,12.1,8,1 1963/12,8.1,8,1 1964/1,5.4,8,1 1964/2,4.2,8,1 1964/3,7.6,8,1 1964/4,15.3,8,1 1964/5,18.9,8,1 1964/6,21.5,8,1 1964/7,25.5,8,1 1964/8,27.8,8,1 1964/9,22.3,8,1 1964/10,15.9,8,1 1964/11,11.1,8,1 1964/12,7.5,8,1 1965/1,4.4,8,1 1965/2,4.7,8,1 1965/3,6.9,8,1 1965/4,11.1,8,1 1965/5,17.2,8,1 1965/6,21.6,8,1 1965/7,24.2,8,1 1965/8,26.7,8,1 1965/9,22.2,8,1 1965/10,16.9,8,1 1965/11,12.7,8,1 1965/12,7.0,8,1 1966/1,4.6,8,1 1966/2,7.2,8,1 1966/3,9.6,8,1 1966/4,13.6,8,1 1966/5,17.9,8,1 1966/6,20.1,8,1 1966/7,24.4,8,1 1966/8,26.9,8,1 1966/9,23.2,8,1 1966/10,18.9,8,1 1966/11,12.9,8,1 1966/12,6.6,8,1 1967/1,4.4,8,1 1967/2,4.9,8,1 1967/3,9.5,8,1 1967/4,14.5,8,1 1967/5,20.0,8,1 1967/6,23.0,8,1 1967/7,26.3,8,1 1967/8,28.0,8,1 1967/9,22.6,8,1 1967/10,16.9,8,1 1967/11,12.1,8,1 1967/12,6.7,8,1 1968/1,5.7,8,1 1968/2,4.3,8,1 1968/3,10.0,8,1 1968/4,14.1,8,1 1968/5,17.5,8,1 1968/6,22.0,8,1 1968/7,24.7,8,1 1968/8,26.6,8,1 1968/9,21.9,8,1 1968/10,16.3,8,1 1968/11,14.1,8,1 1968/12,10.2,8,1 1969/1,5.7,8,1 1969/2,5.7,8,1 1969/3,7.9,8,1 1969/4,14.6,8,1 1969/5,19.6,8,1 1969/6,21.8,8,1 1969/7,25.0,8,1 1969/8,27.2,8,1 1969/9,22.8,8,1 1969/10,17.3,8,1 1969/11,12.8,8,1 1969/12,7.2,8,1 1970/1,4.5,8,1 1970/2,6.0,8,1 1970/3,5.5,8,1 1970/4,13.0,8,1 1970/5,19.6,8,1 1970/6,20.7,8,1 1970/7,25.4,8,1 1970/8,27.4,8,1 1970/9,24.0,8,1 1970/10,17.2,8,1 1970/11,12.3,8,1 1970/12,6.8,8,1 1971/1,5.1,8,1 1971/2,5.9,8,1 1971/3,8.3,8,1 1971/4,13.5,8,1 1971/5,17.4,8,1 1971/6,21.3,8,1 1971/7,25.8,8,1 1971/8,26.7,8,1 1971/9,21.1,8,1 1971/10,15.5,8,1 1971/11,11.9,8,1 1971/12,7.9,8,1 1972/1,6.6,8,1 1972/2,5.1,8,1 1972/3,9.7,8,1 1972/4,13.4,8,1 1972/5,18.6,8,1 1972/6,21.4,8,1 1972/7,25.2,8,1 1972/8,26.6,8,1 1972/9,23.1,8,1 1972/10,18.5,8,1 1972/11,12.3,8,1 1972/12,8.1,8,1 1973/1,6.3,8,1 1973/2,6.9,8,1 1973/3,7.8,8,1 1973/4,15.3,8,1 1973/5,17.9,8,1 1973/6,19.8,8,1 1973/7,26.1,8,1 1973/8,28.5,8,1 1973/9,23.2,8,1 1973/10,17.4,8,1 1973/11,12.1,8,1 1973/12,6.6,8,1 1974/1,4.4,8,1 1974/2,5.1,8,1 1974/3,7.3,8,1 1974/4,14.8,8,1 1974/5,19.3,8,1 1974/6,21.9,8,1 1974/7,23.4,8,1 1974/8,27.1,8,1 1974/9,22.8,8,1 1974/10,17.8,8,1 1974/11,11.7,8,1 1974/12,6.7,8,1 1975/1,4.7,8,1 1975/2,5.1,8,1 1975/3,7.9,8,1 1975/4,14.3,8,1 1975/5,18.6,8,1 1975/6,21.6,8,1 1975/7,25.6,8,1 1975/8,27.3,8,1 1975/9,25.2,8,1 1975/10,17.3,8,1 1975/11,12.7,8,1 1975/12,6.7,8,1 1976/1,5.4,8,1 1976/2,6.8,8,1 1976/3,9.0,8,1 1976/4,13.0,8,1 1976/5,17.7,8,1 1976/6,21.5,8,1 1976/7,23.9,8,1 1976/8,25.1,8,1 1976/9,22.0,8,1 1976/10,17.5,8,1 1976/11,11.2,8,1 1976/12,7.3,8,1 1977/1,3.4,8,1 1977/2,4.9,8,1 1977/3,9.3,8,1 1977/4,15.1,8,1 1977/5,18.7,8,1 1977/6,20.9,8,1 1977/7,25.8,8,1 1977/8,25.0,8,1 1977/9,24.3,8,1 1977/10,18.7,8,1 1977/11,14.8,8,1 1977/12,8.9,8,1 1978/1,5.6,8,1 1978/2,4.2,8,1 1978/3,8.7,8,1 1978/4,13.9,8,1 1978/5,19.0,8,1 1978/6,23.8,8,1 1978/7,27.8,8,1 1978/8,28.9,8,1 1978/9,22.2,8,1 1978/10,17.3,8,1 1978/11,12.9,8,1 1978/12,8.5,8,1 1979/1,6.6,8,1 1979/2,8.4,8,1 1979/3,9.9,8,1 1979/4,13.9,8,1 1979/5,18.6,8,1 1979/6,24.4,8,1 1979/7,25.2,8,1 1979/8,27.4,8,1 1979/9,24.1,8,1 1979/10,19.6,8,1 1979/11,14.3,8,1 1979/12,10.1,8,1 1980/1,5.6,8,1 1980/2,5.2,8,1 1980/3,8.2,8,1 1980/4,13.6,8,1 1980/5,19.2,8,1 1980/6,23.6,8,1 1980/7,23.8,8,1 1980/8,23.4,8,1 1980/9,23.0,8,1 1980/10,18.2,8,1 1980/11,13.0,8,1 1980/12,7.7,8,1 1981/1,4.4,8,1 1981/2,5.3,8,1 1981/3,9.0,8,1 1981/4,13.9,8,1 1981/5,17.5,8,1 1981/6,20.2,8,1 1981/7,26.3,8,1 1981/8,26.2,8,1 1981/9,21.8,8,1 1981/10,17.6,8,1 1981/11,10.4,8,1 1981/12,7.6,8,1 1982/1,5.8,8,1 1982/2,5.5,8,1 1982/3,9.9,8,1 1982/4,14.0,8,1 1982/5,20.7,8,1 1982/6,21.4,8,1 1982/7,23.1,8,1 1982/8,27.1,8,1 1982/9,22.3,8,1 1982/10,18.0,8,1 1982/11,14.3,8,1 1982/12,9.5,8,1 1983/1,6.2,8,1 1983/2,6.1,8,1 1983/3,8.6,8,1 1983/4,15.9,8,1 1983/5,19.7,8,1 1983/6,20.5,8,1 1983/7,23.8,8,1 1983/8,27.5,8,1 1983/9,23.1,8,1 1983/10,17.7,8,1 1983/11,12.3,8,1 1983/12,7.1,8,1 1984/1,3.7,8,1 1984/2,3.0,8,1 1984/3,5.9,8,1 1984/4,11.6,8,1 1984/5,17.2,8,1 1984/6,21.8,8,1 1984/7,26.2,8,1 1984/8,28.6,8,1 1984/9,23.5,8,1 1984/10,17.7,8,1 1984/11,12.2,8,1 1984/12,7.7,8,1 1985/1,4.1,8,1 1985/2,6.5,8,1 1985/3,7.8,8,1 1985/4,14.2,8,1 1985/5,19.1,8,1 1985/6,20.2,8,1 1985/7,26.3,8,1 1985/8,27.9,8,1 1985/9,23.1,8,1 1985/10,17.9,8,1 1985/11,13.3,8,1 1985/12,7.4,8,1 1986/1,4.5,8,1 1986/2,4.3,8,1 1986/3,7.8,8,1 1986/4,13.9,8,1 1986/5,17.9,8,1 1986/6,21.1,8,1 1986/7,23.9,8,1 1986/8,26.8,8,1 1986/9,23.7,8,1 1986/10,17.1,8,1 1986/11,12.3,8,1 1986/12,8.5,8,1 1987/1,5.8,8,1 1987/2,6.8,8,1 1987/3,9.3,8,1 1987/4,14.4,8,1 1987/5,19.3,8,1 1987/6,22.1,8,1 1987/7,27.0,8,1 1987/8,27.3,8,1 1987/9,23.3,8,1 1987/10,18.9,8,1 1987/11,12.8,8,1 1987/12,8.1,8,1 1988/1,7.7,8,1 1988/2,4.9,8,1 1988/3,8.4,8,1 1988/4,14.3,8,1 1988/5,18.2,8,1 1988/6,22.3,8,1 1988/7,22.4,8,1 1988/8,27.0,8,1 1988/9,22.8,8,1 1988/10,17.5,8,1 1988/11,11.4,8,1 1988/12,8.4,8,1 1989/1,8.1,8,1 1989/2,7.5,8,1 1989/3,9.6,8,1 1989/4,15.6,8,1 1989/5,17.7,8,1 1989/6,20.7,8,1 1989/7,24.1,8,1 1989/8,27.1,8,1 1989/9,25.2,8,1 1989/10,17.5,8,1 1989/11,14.2,8,1 1989/12,9.2,8,1 1990/1,5.0,8,1 1990/2,7.8,8,1 1990/3,10.6,8,1 1990/4,14.7,8,1 1990/5,19.2,8,1 1990/6,23.5,8,1 1990/7,25.7,8,1 1990/8,28.6,8,1 1990/9,24.8,8,1 1990/10,19.2,8,1 1990/11,15.1,8,1 1990/12,10.0,8,1 1991/1,6.3,8,1 1991/2,6.5,8,1 1991/3,9.5,8,1 1991/4,15.4,8,1 1991/5,18.8,8,1 1991/6,23.6,8,1 1991/7,26.7,8,1 1991/8,25.5,8,1 1991/9,23.9,8,1 1991/10,18.1,8,1 1991/11,13.0,8,1 1991/12,9.2,8,1 1992/1,6.8,8,1 1992/2,6.9,8,1 1992/3,9.7,8,1 1992/4,15.1,8,1 1992/5,17.3,8,1 1992/6,20.6,8,1 1992/7,25.5,8,1 1992/8,27.0,8,1 1992/9,23.3,8,1 1992/10,17.3,8,1 1992/11,13.0,8,1 1992/12,9.4,8,1 1993/1,6.2,8,1 1993/2,7.7,8,1 1993/3,8.7,8,1 1993/4,13.4,8,1 1993/5,18.1,8,1 1993/6,21.7,8,1 1993/7,22.5,8,1 1993/8,24.8,8,1 1993/9,22.9,8,1 1993/10,17.5,8,1 1993/11,14.1,8,1 1993/12,8.5,8,1 1994/1,5.5,8,1 1994/2,6.6,8,1 1994/3,8.1,8,1 1994/4,15.8,8,1 1994/5,19.5,8,1 1994/6,22.4,8,1 1994/7,28.3,8,1 1994/8,28.9,8,1 1994/9,24.8,8,1 1994/10,20.2,8,1 1994/11,13.4,8,1 1994/12,9.0,8,1 1995/1,6.3,8,1 1995/2,6.5,8,1 1995/3,8.9,8,1 1995/4,15.0,8,1 1995/5,19.1,8,1 1995/6,20.4,8,1 1995/7,26.4,8,1 1995/8,29.4,8,1 1995/9,23.7,8,1 1995/10,19.5,8,1 1995/11,12.7,8,1 1995/12,7.7,8,1 1996/1,6.6,8,1 1996/2,5.4,8,1 1996/3,9.2,8,1 1996/4,12.7,8,1 1996/5,18.1,8,1 1996/6,22.6,8,1 1996/7,26.2,8,1 1996/8,26.0,8,1 1996/9,22.4,8,1 1996/10,18.0,8,1 1996/11,13.2,8,1 1996/12,9.3,8,1 1997/1,6.8,8,1 1997/2,7.0,8,1 1997/3,10.5,8,1 1997/4,15.2,8,1 1997/5,19.2,8,1 1997/6,22.7,8,1 1997/7,26.6,8,1 1997/8,27.0,8,1 1997/9,22.9,8,1 1997/10,18.7,8,1 1997/11,14.3,8,1 1997/12,9.2,8,1 1998/1,5.3,8,1 1998/2,7.0,8,1 1998/3,10.1,8,1 1998/4,16.3,8,1 1998/5,20.5,8,1 1998/6,21.5,8,1 1998/7,25.3,8,1 1998/8,27.2,8,1 1998/9,24.4,8,1 1998/10,20.1,8,1 1998/11,13.9,8,1 1998/12,9.0,8,1 1999/1,6.6,8,1 1999/2,6.7,8,1 1999/3,10.1,8,1 1999/4,15.0,8,1 1999/5,19.9,8,1 1999/6,22.8,8,1 1999/7,25.9,8,1 1999/8,28.5,8,1 1999/9,26.2,8,1 1999/10,19.5,8,1 1999/11,14.2,8,1 1999/12,9.0,8,1 2000/1,7.6,8,1 2000/2,6.0,8,1 2000/3,9.4,8,1 2000/4,14.5,8,1 2000/5,19.8,8,1 2000/6,22.5,8,1 2000/7,27.7,8,1 2000/8,28.3,8,1 2000/9,25.6,8,1 2000/10,18.8,8,1 2000/11,13.3,8,1 2000/12,8.8,8,1 2001/1,4.9,8,1 2001/2,6.6,8,1 2001/3,9.8,8,1 2001/4,15.7,8,1 2001/5,19.5,8,1 2001/6,23.1,8,1 2001/7,28.5,8,1 2001/8,26.4,8,1 2001/9,23.2,8,1 2001/10,18.7,8,1 2001/11,13.1,8,1 2001/12,8.4,8,1 2002/1,7.4,8,1 2002/2,7.9,8,1 2002/3,12.2,8,1 2002/4,16.1,8,1 2002/5,18.4,8,1 2002/6,21.6,8,1 2002/7,28.0,8,1 2002/8,28.0,8,1 2002/9,23.1,8,1 2002/10,19.0,8,1 2002/11,11.6,8,1 2002/12,7.2,8,1 2003/1,5.5,8,1 2003/2,6.4,8,1 2003/3,8.7,8,1 2003/4,15.1,8,1 2003/5,18.8,8,1 2003/6,23.2,8,1 2003/7,22.8,8,1 2003/8,26.0,8,1 2003/9,24.2,8,1 2003/10,17.8,8,1 2003/11,14.4,8,1 2003/12,9.2,8,1 2004/1,6.3,8,1 2004/2,8.5,8,1 2004/3,9.8,8,1 2004/4,16.4,8,1 2004/5,19.6,8,1 2004/6,23.7,8,1 2004/7,28.5,8,1 2004/8,27.2,8,1 2004/9,25.1,8,1 2004/10,17.5,8,1 2004/11,15.6,8,1 2004/12,9.9,8,1 2005/1,6.1,8,1 2005/2,6.2,8,1 2005/3,9.0,8,1 2005/4,15.1,8,1 2005/5,17.7,8,1 2005/6,23.2,8,1 2005/7,25.6,8,1 2005/8,28.1,8,1 2005/9,24.7,8,1 2005/10,19.2,8,1 2005/11,13.3,8,1 2005/12,6.4,8,1 2006/1,5.1,8,1 2006/2,6.7,8,1 2006/3,9.8,8,1 2006/4,13.6,8,1 2006/5,19.0,8,1 2006/6,22.5,8,1 2006/7,25.6,8,1 2006/8,27.5,8,1 2006/9,23.5,8,1 2006/10,19.5,8,1 2006/11,14.4,8,1 2006/12,9.5,8,1 2007/1,7.6,8,1 2007/2,8.6,8,1 2007/3,10.8,8,1 2007/4,13.7,8,1 2007/5,19.8,8,1 2007/6,23.2,8,1 2007/7,24.4,8,1 2007/8,29.0,8,1 2007/9,25.2,8,1 2007/10,19.0,8,1 2007/11,13.3,8,1 2007/12,9.0,8,1 2008/1,5.9,8,1 2008/2,5.5,8,1 2008/3,10.7,8,1 2008/4,14.7,8,1 2008/5,18.5,8,1 2008/6,21.3,8,1 2008/7,27.0,8,1 2008/8,26.8,8,1 2008/9,24.4,8,1 2008/10,19.4,8,1 2008/11,13.1,8,1 2008/12,9.8,8,1 2009/1,6.8,8,1 2009/2,7.8,8,1 2009/3,10.0,8,1 2009/4,15.7,8,1 2009/5,20.1,8,1 2009/6,22.5,8,1 2009/7,26.3,8,1 2009/8,26.6,8,1 2009/9,23.0,8,1 2009/10,19.0,8,1 2009/11,13.5,8,1 2009/12,9.0,8,1 2010/1,7.0,8,1 2010/2,6.5,8,1 2010/3,9.1,8,1 2010/4,12.4,8,1 2010/5,19.0,8,1 2010/6,23.6,8,1 2010/7,28.0,8,1 2010/8,29.6,8,1 2010/9,25.1,8,1 2010/10,18.9,8,1 2010/11,13.5,8,1 2010/12,9.9,8,1 2011/1,5.1,8,1 2011/2,7.0,8,1 2011/3,8.1,8,1 2011/4,14.5,8,1 2011/5,18.5,8,1 2011/6,22.8,8,1 2011/7,27.3,8,1 2011/8,27.5,8,1 2011/9,25.1,8,1 2011/10,19.5,8,1 2011/11,14.9,8,1 2011/12,7.5,8,1 2012/1,4.8,8,1 2012/2,5.4,8,1 2012/3,8.8,8,1 2012/4,14.5,8,1 2012/5,19.6,8,1 2012/6,21.4,8,1 2012/7,26.4,8,1 2012/8,29.1,8,1 2012/9,26.2,8,1 2012/10,19.4,8,1 2012/11,12.7,8,1 2012/12,7.3,8,1 2013/1,5.5,8,1 2013/2,6.2,8,1 2013/3,12.1,8,1 2013/4,15.2,8,1 2013/5,19.8,8,1 2013/6,22.9,8,1 2013/7,27.3,8,1 2013/8,29.2,8,1 2013/9,25.2,8,1 2013/10,19.8,8,1 2013/11,13.5,8,1 2013/12,8.3,8,1 2014/1,6.3,8,1 2014/2,5.9,8,1 2014/3,10.4,8,1 2014/4,15.0,8,1 2014/5,20.3,8,1 2014/6,23.4,8,1 2014/7,26.8,8,1 2014/8,27.7,8,1 2014/9,23.2,8,1 2014/10,19.1,8,1 2014/11,14.2,8,1 2014/12,6.7,8,2 2015/1,5.8,8,2 2015/2,5.7,8,2 2015/3,10.3,8,2 2015/4,14.5,8,2 2015/5,21.1,8,2 2015/6,22.1,8,2 2015/7,26.2,8,2 2015/8,26.7,8,2 2015/9,22.6,8,2 2015/10,18.4,8,2 2015/11,13.9,8,2 2015/12,9.3,8,2 2016/1,6.1,8,2 2016/2,7.2,8,2 2016/3,10.1,8,2 2016/4,15.4,8,2 2016/5,20.2,8,2 2016/6,22.4,8,2 2016/7,25.4,8,2 2016/8,27.1,8,2 2016/9,24.4,8,2 2016/10,18.7,8,2 2016/11,11.4,8,2 2016/12,8.9,8,2 2017/1,5.8,8,2 ================================================ FILE: colab/index.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Pythonプログラミング入門\n", "\n", "▲で始まる項目は授業では扱いません。興味にしたがって学習してください。\n", "\n", "ノートブック全体に▲が付いているものもありますので注意してください。\n", "\n", "## [1-0. Colaboratory (Colab) の使い方](1/1-0.ipynb)\n", "\n", "- Colaboratoryの立ち上げ\n", "- 教材のオープン\n", "- ノートブックの操作\n", "- セル\n", "- セルの編集\n", "- 練習\n", "- セルの挿入\n", "- セルの実行が止まらないとき\n", "- セルの操作\n", "- ノートブックの参照\n", "- ノートブックのダウンロード\n", "\n", "## [1-1. 数値演算](1/1-1.ipynb)\n", "\n", "- 簡単な算術計算\n", "- コメント\n", "- 整数と実数\n", "- 演算子の優先順位と括弧\n", "- 算術演算子のまとめ\n", "- 空白\n", "- エラー\n", "- 数学関数(モジュールのインポート)\n", "- 練習\n", "\n", "## [1-2. 変数と関数の基礎](1/1-2.ipynb)\n", "\n", "- 変数\n", "- 関数の定義と返値\n", "- ローカル変数\n", "- `print`\n", "- `print` と `return`\n", "- コメントと空行\n", "- 関数の参照の書き方\n", "- ▲グローバル変数\n", "- 練習の解答\n", "\n", "## [1-3. 論理・比較演算と条件分岐の基礎](1/1-3.ipynb)\n", "\n", "- if文による条件分岐\n", "- 様々な条件\n", "- 真理値を返す関数\n", "- オブジェクト\n", "- `None`\n", "- ▲条件として使われる他の値\n", "- ▲再帰\n", "- 練習の解答\n", "\n", "## [1-4. テストとデバッグ](1/1-4.ipynb)\n", "\n", "- 仕様・テスト・デバッグ\n", "- assert文\n", "- エラーの分類\n", "- デバッグの具体例\n", "- コーディングスタイル\n", "\n", "## [2-1. 文字列 (string)](2/2-1.ipynb)\n", "\n", "- 文字列とインデックス\n", "- 文字列とスライス\n", "- 空文字列\n", "- 文字列の検索\n", "- ▲エスケープシーケンス\n", "- バックスラッシュの表示と入力\n", "- 文字列の連結\n", "- 文字列とメソッド\n", "- **文字列の比較演算**\n", "- 練習\n", "- 初心者によくある誤解 --- **変数**と**文字列**の混乱\n", "- 練習\n", "- 練習の解答\n", "\n", "## [2-2. リスト (list)](2/2-2.ipynb)\n", "\n", "- リストとインデックス\n", "- 練習\n", "- **多重リスト**\n", "- リストに対する関数・演算子・メソッド\n", "- 破壊的(インプレース)な操作と非破壊的な生成\n", "- リストを操作するメソッドなど\n", "- リストと文字列の相互変換\n", "- タプル (tuple)\n", "- 練習\n", "- 多重代入\n", "- リストやタプルの比較演算\n", "- for文による繰り返しとリスト・タプル\n", "- 練習\n", "- for文による繰り返しと文字列\n", "- 練習\n", "- for文によるリスト初期化の短縮記法\n", "- ▲オブジェクトの等価性と同一性\n", "- 練習の解答\n", "\n", "## [2-3. 条件分岐](2/2-3.ipynb)\n", "\n", "- インデントによる構文\n", "- **`if`** ... **`else`** による条件分岐\n", "- **`if`** ... **`elif`** ... **`else`** による条件分岐\n", "- 練習\n", "- 練習\n", "- ▲複数行にまたがる条件式\n", "- **`if`** ... **`elif`** ... **`else`** における条件の評価\n", "- 練習\n", "- `or` もしくは `and` で結合された条件の評価\n", "- ▲**3項演算子**(条件式)\n", "- 練習の解答\n", "- 練習の解説\n", "\n", "## [3-1. 辞書 (dictionary)](3/3-1.ipynb)\n", "\n", "- 練習\n", "- 辞書のメソッド\n", "- 辞書とリスト\n", "- 練習\n", "- 練習の解答\n", "\n", "## [3-2. 繰り返し](3/3-2.ipynb)\n", "\n", "- for文による繰り返し\n", "- for文による繰り返しと辞書\n", "- 練習\n", "- `range`\n", "- 練習\n", "- 練習\n", "- `range` とリスト\n", "- for文の**入れ子**\n", "- 練習\n", "- 練習\n", "- for文の**計算量**\n", "- **`enumerate`**\n", "- **`in`**\n", "- while文による繰り返し\n", "- 制御構造とreturn文\n", "- **break文**\n", "- 練習\n", "- **continue文**\n", "- ▲for文とwhile文における **`else`**\n", "- **pass文**\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 練習の解答\n", "- 練習の解説\n", "- 練習の解答\n", "\n", "## [3-3. 関数](3/3-3.ipynb)\n", "\n", "- 関数の定義\n", "- 引数\n", "- 返値\n", "- 複数の引数\n", "- 変数とスコープ\n", "- ▲キーワード引数\n", "- ▲引数の初期値\n", "- ▲可変長引数\n", "- ▲辞書型の可変長引数\n", "- ▲引数の順番\n", "- ▲変数としての関数\n", "\n", "## [4-1. ファイル入出力の基本](4/4-1.ipynb)\n", "\n", "- ファイルのオープン\n", "- ファイルのクローズ\n", "- 行の読み込み\n", "- 練習\n", "- ファイル全体の読み込み\n", "- 練習\n", "- 編集中のファイルの動作\n", "- ファイルに対するwith文\n", "- ファイルへの書き込み\n", "- 練習\n", "- ファイルの読み書きにおける文字コード指定\n", "- 改行文字の削除\n", "- 練習の解答\n", "\n", "## [4-2. イテラブルとイテレータ](4/4-2.ipynb)\n", "\n", "- for文による繰り返しとファイルオブジェクト\n", "- for文とイテラブルとイテレータ\n", "- `iter`\n", "- `next`\n", "- for文の仕組み\n", "- イテレータは特殊なイテラブル\n", "- ファイルオブジェクトはイテレータ\n", "- イテラブルはイテレータではない\n", "- イテレータを返す `enumerate`\n", "- ▲イテラブルとイテレータの定義\n", "- 練習の解答\n", "\n", "## [4-3. ディレクトリと木構造](4/4-3.ipynb)\n", "\n", "- ディレクトリと階層構造\n", "- カレントワーキングディレクトリ\n", "- パス\n", "- 木構造\n", "- データ表現としての木構造\n", "\n", "## [5-1. モジュールの使い方](5/5-1.ipynb)\n", "\n", "- モジュールのインポート\n", "- `from`\n", "- `as`\n", "- 練習\n", "- 練習の解答\n", "\n", "## [5-2. モジュールの作り方](5/5-2.ipynb)\n", "\n", "- モジュールファイル\n", "- 自作モジュールの使い方\n", "\n", "## [5-3. NumPyライブラリ](5/5-3.ipynb)\n", "\n", "- 配列の構築\n", "- 配列要素を生成する構築関数\n", "- 練習\n", "- 配列要素の操作\n", "- 要素毎の演算\n", "- よく使われる配列操作\n", "- 配列の保存と復元\n", "- ▲**真理値配列によるインデックスアクセス**\n", "- ▲線形代数の演算\n", "- 練習の解答\n", "\n", "## [6-1. 内包表記](6/6-1.ipynb)\n", "\n", "- リスト内包表記\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 内包表記の入れ子\n", "- 練習\n", "- 練習\n", "- ▲**条件付き内包表記**\n", "- ▲**セット内包表記**\n", "- ▲**辞書内包表記**\n", "- ▲**ジェネレータ式**\n", "- 練習の解答\n", "\n", "## [6-2. 高階関数](6/6-2.ipynb)\n", "\n", "- `max`\n", "- `sorted`\n", "- ラムダ式\n", "- リストからイテラブルへ\n", "- 練習\n", "- `map`\n", "- 練習\n", "- `filter`\n", "- 練習\n", "- 練習\n", "- 練習の解答\n", "\n", "## [6-3. クラス](6/6-3.ipynb)\n", "\n", "- クラス定義\n", "- 初期化と属性\n", "- 継承\n", "- 特殊メソッド\n", "- 継承による振舞いの改変\n", "- 練習\n", "- ▲with文への対応\n", "- 練習の解答\n", "\n", "## [7-1. pandasライブラリ](7/7-1.ipynb)\n", "\n", "- シリーズとデータフレーム\n", "- シリーズ (`Series`) の作成\n", "- データフレーム (`DataFrame`) の作成\n", "- CSVファイルからのデータフレームの作成\n", "- データの参照\n", "- データの条件取り出し\n", "- 列の追加と削除\n", "- 行の追加と削除\n", "- データの並び替え\n", "- データの統計量\n", "- ▲データの連結\n", "- ▲データの結合\n", "- ▲データのグループ化\n", "- ▲欠損値、時系列データの処理\n", "\n", "## [7-2. scikit-learnライブラリ](7/7-2.ipynb)\n", "\n", "- 機械学習について\n", "- 教師あり学習\n", "- 教師なし学習\n", "- データ\n", "- モデル学習の基礎\n", "- 教師あり学習・分類の例\n", "- 練習\n", "- 教師あり学習・回帰の例\n", "- 教師なし学習・クラスタリングの例\n", "- 練習\n", "- 教師なし学習・次元削減の例\n", "- 練習の解答例\n", "\n", "## [▲Jupyter Notebook の使い方](appendix/1-jupyter-notebook.ipynb)\n", "\n", "- セル\n", "- コマンドモード\n", "- 編集モード\n", "- 練習\n", "- (注意)Shift-Enterに反応がなくなったとき\n", "\n", "## [▲セット (set)](appendix/2-set.ipynb)\n", "\n", "- セットの組み込み関数\n", "- 練習\n", "- 練習\n", "- **集合演算**\n", "- **比較演算**\n", "- セットのメソッド\n", "- 練習\n", "- 練習の解答\n", "\n", "## [▲再帰](appendix/3-recursion.ipynb)\n", "\n", "- 再帰関数の例:接頭辞リストと接尾辞リスト\n", "- 再帰関数の例:べき乗の計算\n", "- 再帰関数の例:マージソート\n", "\n", "## [▲簡単なデータの可視化](appendix/3-visualization.ipynb)\n", "\n", "- **`matplotlib`**\n", "- 折れ線グラフ\n", "- 散布図\n", "- 棒グラフ\n", "\n", "## [▲CSVファイルの入出力](appendix/4-csv.ipynb)\n", "\n", "- CSV形式とは\n", "- CSVファイルの読み込み\n", "- CSVファイルに対するfor文\n", "- CSVファイルに対するwith文\n", "- CSVファイルの書き込み\n", "- 練習\n", "- 練習\n", "- 練習の解答\n", "\n", "## [▲Bokehライブラリ](appendix/5-bokeh.ipynb)\n", "\n", "- 線グラフ\n", "- 散布図\n", "- 棒グラフ\n", "- ヒストグラム\n", "- ヒートマップ\n", "- グラフのファイル出力\n", "\n", "## [▲Pythonスクリプトとコマンドライン実行](appendix/5-command.ipynb)\n", "\n", "- コマンドライン実行の具体例\n", "- コマンドライン引数\n", "- モジュールのコマンドライン実行\n", "- ソースファイル先頭部分にある宣言\n", "- 練習の解答\n", "\n", "## [▲Matplotlibライブラリ](appendix/5-matplotlib.ipynb)\n", "\n", "- 線グラフ\n", "- 練習\n", "- 練習\n", "- 散布図\n", "- 練習\n", "- 棒グラフ\n", "- 練習\n", "- ヒストグラム\n", "- 練習\n", "- ヒートマップ\n", "- 練習\n", "- グラフの画像ファイル出力\n", "- 練習の解答\n", "\n", "## [▲正規表現](appendix/5-re.ipynb)\n", "\n", "- 正規表現の基本\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 文字クラス\n", "- 正規表現に関する基本的な関数\n", "- 練習\n", "- 練習\n", "- その他の反復演算\n", "- メタ文字\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 練習\n", "- 正規表現のエスケープシーケンス\n", "- 正規表現に関する関数とメソッド\n", "- 練習\n", "- 練習\n", "- 練習の解答\n", "\n", "## [索引](index_of_terms.ipynb)\n", "\n", "\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: colab/index_of_terms.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 索引\n", "\n", "- `!=` [1/1-3#様々な条件](1/1-3.ipynb#様々な条件)\n", "- `#` [1/1-1#コメント](1/1-1.ipynb#コメント)\n", "- `%` [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- `>` [1/1-3#様々な条件](1/1-3.ipynb#様々な条件)\n", "- `>=` [1/1-3#様々な条件](1/1-3.ipynb#様々な条件)\n", "- `<` [1/1-3#様々な条件](1/1-3.ipynb#様々な条件)\n", "- `<=` [1/1-3#様々な条件](1/1-3.ipynb#様々な条件)\n", "- `*` [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算), [3/3-3#▲可変長引数](3/3-3.ipynb#▲可変長引数), [3/3-3#▲可変長引数](3/3-3.ipynb#▲可変長引数), [2/2-1#文字列の連結](2/2-1.ipynb#文字列の連結), [2/2-2#リストと演算子](2/2-2.ipynb#リストと演算子), [5/5-1#`from`](5/5-1.ipynb#from), [5/5-2#自作モジュールの使い方](5/5-2.ipynb#自作モジュールの使い方)\n", "- `**` [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算), [3/3-3#▲辞書型の可変長引数](3/3-3.ipynb#▲辞書型の可変長引数)\n", "- `+` [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算), [1/1-1#単項の `+` と `-`](1/1-1.ipynb#単項の-+-と--), [2/2-1#文字列の連結](2/2-1.ipynb#文字列の連結), [2/2-2#リストと演算子](2/2-2.ipynb#リストと演算子)\n", "- `+=` [1/1-2#累積代入文](1/1-2.ipynb#累積代入文)\n", "- `-` [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算), [1/1-1#単項の `+` と `-`](1/1-1.ipynb#単項の-+-と--)\n", "- `-=` [1/1-2#累積代入文](1/1-2.ipynb#累積代入文)\n", "- `.` [appendix/5-re#メタ文字](appendix/5-re.ipynb#メタ文字)\n", "- `/` [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- `//` [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- 2項演算子 [1/1-1#単項の `+` と `-`](1/1-1.ipynb#単項の-+-と--)\n", "- 3項演算子 [2/2-3#▲3項演算子(条件式)](2/2-3.ipynb#▲3項演算子(条件式))\n", "- `=` [1/1-2#変数](1/1-2.ipynb#変数), [1/1-2#代入文](1/1-2.ipynb#代入文)\n", "- `==` [1/1-3#様々な条件](1/1-3.ipynb#様々な条件)\n", "- CSV [appendix/4-csv#CSV形式とは](appendix/4-csv.ipynb#CSV形式とは)\n", "- CSVファイル [7/7-1#CSVファイルからのデータフレームの作成](7/7-1.ipynb#CSVファイルからのデータフレームの作成)\n", "- CSVライター [appendix/4-csv#CSVファイルの書き込み](appendix/4-csv.ipynb#CSVファイルの書き込み)\n", "- CSVリーダ [appendix/4-csv#CSVファイルの読み込み](appendix/4-csv.ipynb#CSVファイルの読み込み)\n", "- `DataFrame` [7/7-1#シリーズとデータフレーム](7/7-1.ipynb#シリーズとデータフレーム)\n", "- `False` [1/1-3#真理値を返す関数](1/1-3.ipynb#真理値を返す関数)\n", "- `KMeans` [7/7-2#教師なし学習・クラスタリングの例](7/7-2.ipynb#教師なし学習・クラスタリングの例)\n", "- `LinearRegression` [7/7-2#教師あり学習・回帰の例](7/7-2.ipynb#教師あり学習・回帰の例)\n", "- `LogisticRegression` [7/7-2#教師あり学習・分類の例](7/7-2.ipynb#教師あり学習・分類の例)\n", "- Matplotlib [appendix/5-matplotlib#▲Matplotlibライブラリ](appendix/5-matplotlib.ipynb#▲Matplotlibライブラリ)\n", "- `None` [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [1/1-3#`None`](1/1-3.ipynb#None), [3/3-3#返値](3/3-3.ipynb#返値)\n", "- NumPy [appendix/5-matplotlib#線グラフ](appendix/5-matplotlib.ipynb#線グラフ), [5/5-3#5-3. NumPyライブラリ](5/5-3.ipynb#5-3.-NumPyライブラリ)\n", "- `PCA` [7/7-2#教師なし学習・次元削減の例](7/7-2.ipynb#教師なし学習・次元削減の例)\n", "- PEP8 [1/1-4#コーディングスタイル](1/1-4.ipynb#コーディングスタイル)\n", "- Pythonスクリプト [appendix/5-command#▲Pythonスクリプトとコマンドライン実行](appendix/5-command.ipynb#▲Pythonスクリプトとコマンドライン実行)\n", "- `Series` [7/7-1#シリーズとデータフレーム](7/7-1.ipynb#シリーズとデータフレーム)\n", "- `StopIteration` [6/6-3#特殊メソッド](6/6-3.ipynb#特殊メソッド)\n", "- `True` [1/1-3#真理値を返す関数](1/1-3.ipynb#真理値を返す関数)\n", "- `\\` [2/2-3#▲複数行にまたがる条件式](2/2-3.ipynb#▲複数行にまたがる条件式)\n", "- `\\D` [appendix/5-re#メタ文字](appendix/5-re.ipynb#メタ文字)\n", "- `\\S` [appendix/5-re#メタ文字](appendix/5-re.ipynb#メタ文字)\n", "- `\\W` [appendix/5-re#メタ文字](appendix/5-re.ipynb#メタ文字)\n", "- `\\d` [appendix/5-re#メタ文字](appendix/5-re.ipynb#メタ文字)\n", "- `\\s` [appendix/5-re#メタ文字](appendix/5-re.ipynb#メタ文字)\n", "- `\\t` [appendix/5-re#メタ文字](appendix/5-re.ipynb#メタ文字)\n", "- `\\w` [appendix/5-re#メタ文字](appendix/5-re.ipynb#メタ文字)\n", "- `__enter__` [6/6-3#▲with文への対応](6/6-3.ipynb#▲with文への対応)\n", "- `__exit__` [6/6-3#▲with文への対応](6/6-3.ipynb#▲with文への対応)\n", "- `__init__` [6/6-3#初期化と属性](6/6-3.ipynb#初期化と属性)\n", "- `__iter__` [6/6-3#特殊メソッド](6/6-3.ipynb#特殊メソッド), [4/4-2#▲イテラブルとイテレータの定義](4/4-2.ipynb#▲イテラブルとイテレータの定義)\n", "- `__name__` [appendix/5-command#モジュールのコマンドライン実行](appendix/5-command.ipynb#モジュールのコマンドライン実行)\n", "- `__next__` [6/6-3#特殊メソッド](6/6-3.ipynb#特殊メソッド), [4/4-2#▲イテラブルとイテレータの定義](4/4-2.ipynb#▲イテラブルとイテレータの定義)\n", "- `a*` [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- `a+` [appendix/5-re#その他の反復演算](appendix/5-re.ipynb#その他の反復演算)\n", "- `a?` [appendix/5-re#その他の反復演算](appendix/5-re.ipynb#その他の反復演算)\n", "- add [appendix/2-set#add](appendix/2-set.ipynb#add)\n", "- `and` [1/1-3#様々な条件](1/1-3.ipynb#様々な条件)\n", "- `append` [2/2-2#リストに要素を追加する](2/2-2.ipynb#リストに要素を追加する)\n", "- argument [3/3-3#引数](3/3-3.ipynb#引数)\n", "- `as` [4/4-1#ファイルに対するwith文](4/4-1.ipynb#ファイルに対するwith文), [5/5-1#`as`](5/5-1.ipynb#as), [5/5-2#自作モジュールの使い方](5/5-2.ipynb#自作モジュールの使い方)\n", "- `ascending` [7/7-1#データの並び替え](7/7-1.ipynb#データの並び替え)\n", "- assert文 [1/1-4#assert文](1/1-4.ipynb#assert文)\n", "- `assign` [7/7-1#列の追加と削除](7/7-1.ipynb#列の追加と削除)\n", "- assignment [1/1-2#代入文](1/1-2.ipynb#代入文)\n", "- assignment statement [1/1-2#代入文](1/1-2.ipynb#代入文)\n", "- augmented assignment statement [1/1-2#累積代入文](1/1-2.ipynb#累積代入文)\n", "- `axis` [7/7-1#列の追加と削除](7/7-1.ipynb#列の追加と削除)\n", "- `a{x,y}` [appendix/5-re#その他の反復演算](appendix/5-re.ipynb#その他の反復演算)\n", "- `bar` [appendix/5-matplotlib#棒グラフ](appendix/5-matplotlib.ipynb#棒グラフ)\n", "- `bokeh` [appendix/5-bokeh#▲Bokehライブラリ](appendix/5-bokeh.ipynb#▲Bokehライブラリ)\n", "- `bokeh.models.ColumnDataSource` [appendix/5-bokeh#ヒートマップ](appendix/5-bokeh.ipynb#ヒートマップ)\n", "- `bokeh.models.LinearColorMapper` [appendix/5-bokeh#ヒートマップ](appendix/5-bokeh.ipynb#ヒートマップ)\n", "- `bokeh.plotting` [appendix/5-bokeh#線グラフ](appendix/5-bokeh.ipynb#線グラフ)\n", "- `bokeh.plotting.figure` [appendix/5-bokeh#線グラフ](appendix/5-bokeh.ipynb#線グラフ)\n", "- `bokeh.plotting.output_file` [appendix/5-bokeh#グラフのファイル出力](appendix/5-bokeh.ipynb#グラフのファイル出力)\n", "- `bokeh.plotting.output_notebook` [appendix/5-bokeh#線グラフ](appendix/5-bokeh.ipynb#線グラフ)\n", "- `bokeh.plotting.reset_output` [appendix/5-bokeh#グラフのファイル出力](appendix/5-bokeh.ipynb#グラフのファイル出力)\n", "- `bokeh.plotting.show` [appendix/5-bokeh#線グラフ](appendix/5-bokeh.ipynb#線グラフ)\n", "- break文 [3/3-2#break文](3/3-2.ipynb#break文), [3/3-2#break文](3/3-2.ipynb#break文)\n", "- `capitalize` [2/2-1#大文字・小文字](2/2-1.ipynb#大文字・小文字)\n", "- `chr` [3/3-2#for文による繰り返し](3/3-2.ipynb#for文による繰り返し)\n", "- `circle` [appendix/5-bokeh#線グラフ](appendix/5-bokeh.ipynb#線グラフ)\n", "- clear [appendix/2-set#clear](appendix/2-set.ipynb#clear)\n", "- `clear` [3/3-1#▲全てのキーと値の削除](3/3-1.ipynb#▲全てのキーと値の削除)\n", "- `close` [4/4-1#ファイルのクローズ](4/4-1.ipynb#ファイルのクローズ)\n", "- `complex` [appendix/4-csv#CSVファイルの読み込み](appendix/4-csv.ipynb#CSVファイルの読み込み)\n", "- `concat` [7/7-1#行の追加と削除](7/7-1.ipynb#行の追加と削除), [7/7-1#▲データの連結](7/7-1.ipynb#▲データの連結)\n", "- continue文 [3/3-2#continue文](3/3-2.ipynb#continue文)\n", "- `copy` [3/3-1#▲辞書を複製する](3/3-1.ipynb#▲辞書を複製する), [2/2-2#▲ `copy`](2/2-2.ipynb#▲-copy)\n", "- `count` [2/2-1#数え上げ](2/2-1.ipynb#数え上げ), [2/2-2#指定した要素のインデックス取得と数えあげ](2/2-2.ipynb#指定した要素のインデックス取得と数えあげ)\n", "- `cross` [appendix/5-bokeh#線グラフ](appendix/5-bokeh.ipynb#線グラフ)\n", "- `csv` [appendix/4-csv#CSVファイルの読み込み](appendix/4-csv.ipynb#CSVファイルの読み込み), [appendix/4-csv#CSVファイルの書き込み](appendix/4-csv.ipynb#CSVファイルの書き込み)\n", "- `csv.reader` [appendix/4-csv#CSVファイルの読み込み](appendix/4-csv.ipynb#CSVファイルの読み込み)\n", "- `csv.writer` [appendix/4-csv#CSVファイルの書き込み](appendix/4-csv.ipynb#CSVファイルの書き込み)\n", "- `def` [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [3/3-3#関数の定義](3/3-3.ipynb#関数の定義)\n", "- `del` [7/7-1#列の追加と削除](7/7-1.ipynb#列の追加と削除), [3/3-1#3-1. 辞書 (dictionary)](3/3-1.ipynb#3-1.-辞書-(dictionary)), [2/2-2#▲リスト要素を削除する](2/2-2.ipynb#▲リスト要素を削除する)\n", "- `describe` [7/7-1#データの統計量](7/7-1.ipynb#データの統計量)\n", "- difference [appendix/2-set#union, intersection, difference](appendix/2-set.ipynb#union,-intersection,-difference)\n", "- discard [appendix/2-set#discard](appendix/2-set.ipynb#discard)\n", "- `drop` [7/7-1#列の追加と削除](7/7-1.ipynb#列の追加と削除), [7/7-1#行の追加と削除](7/7-1.ipynb#行の追加と削除)\n", "- `elif` [2/2-3#`if` ... `elif` ... `else` による条件分岐](2/2-3.ipynb#if-...-elif-...-else-による条件分岐), [2/2-3#`if` ... `elif` ... `else` による条件分岐](2/2-3.ipynb#if-...-elif-...-else-による条件分岐), [2/2-3#`if` ... `elif` ... `else` における条件の評価](2/2-3.ipynb#if-...-elif-...-else-における条件の評価)\n", "- `else` [1/1-3#if文による条件分岐](1/1-3.ipynb#if文による条件分岐), [3/3-2#▲for文とwhile文における `else`](3/3-2.ipynb#▲for文とwhile文における-else), [2/2-3#`if` ... `else` による条件分岐](2/2-3.ipynb#if-...-else-による条件分岐), [2/2-3#`if` ... `elif` ... `else` による条件分岐](2/2-3.ipynb#if-...-elif-...-else-による条件分岐), [2/2-3#`if` ... `elif` ... `else` における条件の評価](2/2-3.ipynb#if-...-elif-...-else-における条件の評価)\n", "- `encoding` [appendix/4-csv#東京の7月の気温](appendix/4-csv.ipynb#東京の7月の気温)\n", "- `enumerate` [4/4-2#イテレータを返す `enumerate`](4/4-2.ipynb#イテレータを返す-enumerate), [3/3-2#`enumerate`](3/3-2.ipynb#enumerate)\n", "- `extend` [2/2-2#▲リストにリストの要素を追加する](2/2-2.ipynb#▲リストにリストの要素を追加する)\n", "- `filter` [6/6-2#`filter`](6/6-2.ipynb#filter)\n", "- `find` [2/2-1#検索](2/2-1.ipynb#検索)\n", "- `findall` [appendix/5-re#`findall`](appendix/5-re.ipynb#findall)\n", "- `finditer` [appendix/5-re#`finditer`](appendix/5-re.ipynb#finditer)\n", "- `fit` [7/7-2#教師あり学習・分類の例](7/7-2.ipynb#教師あり学習・分類の例)\n", "- `flatten` [5/5-3#多次元配列](5/5-3.ipynb#多次元配列)\n", "- `float` [appendix/4-csv#CSVファイルの読み込み](appendix/4-csv.ipynb#CSVファイルの読み込み), [1/1-1#整数と実数の間の変換](1/1-1.ipynb#整数と実数の間の変換), [2/2-1#2-1. 文字列 (string)](2/2-1.ipynb#2-1.-文字列-(string))\n", "- `for` [3/3-2#for文による繰り返し](3/3-2.ipynb#for文による繰り返し)\n", "- for文 [3/3-2#for文による繰り返し](3/3-2.ipynb#for文による繰り返し), [2/2-2#for文による繰り返しとリスト・タプル](2/2-2.ipynb#for文による繰り返しとリスト・タプル)\n", "- `from` [5/5-1#`from`](5/5-1.ipynb#from), [5/5-2#自作モジュールの使い方](5/5-2.ipynb#自作モジュールの使い方)\n", "- `get` [3/3-1#キーを指定して値を得るメソッド](3/3-1.ipynb#キーを指定して値を得るメソッド)\n", "- `global` [3/3-3#▲ global 宣言](3/3-3.ipynb#▲-global-宣言)\n", "- `grid` [appendix/5-matplotlib#線グラフ](appendix/5-matplotlib.ipynb#線グラフ)\n", "- `group` [appendix/5-re#`group`](appendix/5-re.ipynb#group)\n", "- `groupby` [7/7-1#▲データのグループ化](7/7-1.ipynb#▲データのグループ化)\n", "- `head` [7/7-1#CSVファイルからのデータフレームの作成](7/7-1.ipynb#CSVファイルからのデータフレームの作成)\n", "- `hist` [appendix/5-matplotlib#ヒストグラム](appendix/5-matplotlib.ipynb#ヒストグラム)\n", "- `if` [1/1-3#if文による条件分岐](1/1-3.ipynb#if文による条件分岐), [2/2-3#2-3. 条件分岐](2/2-3.ipynb#2-3.-条件分岐), [2/2-3#`if` ... `else` による条件分岐](2/2-3.ipynb#if-...-else-による条件分岐), [2/2-3#`if` ... `elif` ... `else` による条件分岐](2/2-3.ipynb#if-...-elif-...-else-による条件分岐), [2/2-3#`if` ... `elif` ... `else` における条件の評価](2/2-3.ipynb#if-...-elif-...-else-における条件の評価)\n", "- if文 [1/1-3#if文による条件分岐](1/1-3.ipynb#if文による条件分岐)\n", "- `iloc` [7/7-1#`iloc` と `loc`](7/7-1.ipynb#iloc-と-loc)\n", "- `import` [1/1-1#数学関数(モジュールのインポート)](1/1-1.ipynb#数学関数(モジュールのインポート)), [5/5-1#モジュールのインポート](5/5-1.ipynb#モジュールのインポート), [5/5-2#自作モジュールの使い方](5/5-2.ipynb#自作モジュールの使い方)\n", "- `in` [3/3-1#3-1. 辞書 (dictionary)](3/3-1.ipynb#3-1.-辞書-(dictionary)), [3/3-2#for文による繰り返し](3/3-2.ipynb#for文による繰り返し), [3/3-2#`in`](3/3-2.ipynb#in), [3/3-2#`in`](3/3-2.ipynb#in), [2/2-1#文字列の検索](2/2-1.ipynb#文字列の検索), [2/2-2#リストと演算子](2/2-2.ipynb#リストと演算子)\n", "- in-place [2/2-2#破壊的(インプレース)な操作と非破壊的な生成](2/2-2.ipynb#破壊的(インプレース)な操作と非破壊的な生成)\n", "- `index` [7/7-1#CSVファイルからのデータフレームの作成](7/7-1.ipynb#CSVファイルからのデータフレームの作成), [2/2-1#検索](2/2-1.ipynb#検索), [2/2-2#指定した要素のインデックス取得と数えあげ](2/2-2.ipynb#指定した要素のインデックス取得と数えあげ)\n", "- `inplace` [7/7-1#データの並び替え](7/7-1.ipynb#データの並び替え)\n", "- insert [2/2-2#▲リストに要素を挿入する](2/2-2.ipynb#▲リストに要素を挿入する)\n", "- `int` [appendix/4-csv#CSVファイルの読み込み](appendix/4-csv.ipynb#CSVファイルの読み込み), [6/6-1#練習](6/6-1.ipynb#練習), [1/1-1#整数と実数の間の変換](1/1-1.ipynb#整数と実数の間の変換), [2/2-1#2-1. 文字列 (string)](2/2-1.ipynb#2-1.-文字列-(string))\n", "- intersection [appendix/2-set#union, intersection, difference](appendix/2-set.ipynb#union,-intersection,-difference)\n", "- `is` [4/4-2#イテレータは特殊なイテラブル](4/4-2.ipynb#イテレータは特殊なイテラブル), [2/2-2#▲オブジェクトの等価性と同一性](2/2-2.ipynb#▲オブジェクトの等価性と同一性)\n", "- `is not` [2/2-2#▲オブジェクトの等価性と同一性](2/2-2.ipynb#▲オブジェクトの等価性と同一性)\n", "- `items` [3/3-1#キーと値の一覧を得る](3/3-1.ipynb#キーと値の一覧を得る), [3/3-2#for文による繰り返しと辞書](3/3-2.ipynb#for文による繰り返しと辞書)\n", "- `iter` [4/4-2#`iter`](4/4-2.ipynb#iter)\n", "- `join` [2/2-2#リストと文字列の相互変換](2/2-2.ipynb#リストと文字列の相互変換)\n", "- `key` [6/6-2#`max`](6/6-2.ipynb#max), [6/6-2#`sorted`](6/6-2.ipynb#sorted)\n", "- key [3/3-1#3-1. 辞書 (dictionary)](3/3-1.ipynb#3-1.-辞書-(dictionary))\n", "- `keys` [3/3-1#キーの一覧を得る](3/3-1.ipynb#キーの一覧を得る), [3/3-1#キーの一覧を得る](3/3-1.ipynb#キーの一覧を得る), [3/3-2#for文による繰り返しと辞書](3/3-2.ipynb#for文による繰り返しと辞書)\n", "- `lambda` [6/6-2#ラムダ式](6/6-2.ipynb#ラムダ式)\n", "- `legend` [appendix/5-matplotlib#線グラフ](appendix/5-matplotlib.ipynb#線グラフ)\n", "- `len` [3/3-1#3-1. 辞書 (dictionary)](3/3-1.ipynb#3-1.-辞書-(dictionary)), [2/2-1#2-1. 文字列 (string)](2/2-1.ipynb#2-1.-文字列-(string)), [2/2-2#リストの要素数](2/2-2.ipynb#リストの要素数)\n", "- `line` [appendix/5-bokeh#線グラフ](appendix/5-bokeh.ipynb#線グラフ)\n", "- `list` [2/2-2#2-2. リスト (list)](2/2-2.ipynb#2-2.-リスト-(list)), [2/2-2#タプル (tuple)](2/2-2.ipynb#タプル-(tuple))\n", "- `loc` [7/7-1#`iloc` と `loc`](7/7-1.ipynb#iloc-と-loc)\n", "- `lower` [2/2-1#大文字・小文字](2/2-1.ipynb#大文字・小文字)\n", "- `map` [6/6-2#`map`](6/6-2.ipynb#map)\n", "- `match` [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- matchオブジェクト [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- `math` [1/1-1#数学関数(モジュールのインポート)](1/1-1.ipynb#数学関数(モジュールのインポート))\n", "- `math.cos` [1/1-1#数学関数(モジュールのインポート)](1/1-1.ipynb#数学関数(モジュールのインポート))\n", "- `math.pi` [1/1-1#数学関数(モジュールのインポート)](1/1-1.ipynb#数学関数(モジュールのインポート))\n", "- `math.sin` [1/1-1#数学関数(モジュールのインポート)](1/1-1.ipynb#数学関数(モジュールのインポート))\n", "- `math.sqrt` [1/1-1#数学関数(モジュールのインポート)](1/1-1.ipynb#数学関数(モジュールのインポート))\n", "- `matplotlib` [appendix/3-visualization#`matplotlib`](appendix/3-visualization.ipynb#matplotlib)\n", "- `max` [6/6-2#`max`](6/6-2.ipynb#max), [2/2-2#`max` と `min`](2/2-2.ipynb#max-と-min), [5/5-3#`sum`, `max`, `min`, `mean`](5/5-3.ipynb#sum,-max,-min,-mean)\n", "- `mean` [5/5-3#`sum`, `max`, `min`, `mean`](5/5-3.ipynb#sum,-max,-min,-mean)\n", "- `merge` [7/7-1#▲データの結合](7/7-1.ipynb#▲データの結合)\n", "- `min` [2/2-2#`max` と `min`](2/2-2.ipynb#max-と-min), [5/5-3#`sum`, `max`, `min`, `mean`](5/5-3.ipynb#sum,-max,-min,-mean)\n", "- `next` [4/4-2#`next`](4/4-2.ipynb#next)\n", "- `not` [1/1-3#様々な条件](1/1-3.ipynb#様々な条件)\n", "- `not in` [3/3-2#`in`](3/3-2.ipynb#in), [2/2-1#文字列の検索](2/2-1.ipynb#文字列の検索), [2/2-2#リストと演算子](2/2-2.ipynb#リストと演算子)\n", "- `numpy` [5/5-3#5-3. NumPyライブラリ](5/5-3.ipynb#5-3.-NumPyライブラリ)\n", "- `numpy.arange` [5/5-3#`arange`](5/5-3.ipynb#arange)\n", "- `numpy.array` [5/5-3#配列の構築](5/5-3.ipynb#配列の構築)\n", "- `numpy.bool_` [5/5-3#要素型](5/5-3.ipynb#要素型)\n", "- `numpy.complex128` [5/5-3#要素型](5/5-3.ipynb#要素型)\n", "- `numpy.dot` [5/5-3#`dot`](5/5-3.ipynb#dot)\n", "- `numpy.float64` [5/5-3#要素型](5/5-3.ipynb#要素型)\n", "- `numpy.histogram` [appendix/5-bokeh#ヒストグラム](appendix/5-bokeh.ipynb#ヒストグラム)\n", "- `numpy.identity` [5/5-3#▲線形代数の演算](5/5-3.ipynb#▲線形代数の演算)\n", "- `numpy.int32` [5/5-3#要素型](5/5-3.ipynb#要素型)\n", "- `numpy.linalg` [5/5-3#▲線形代数の演算](5/5-3.ipynb#▲線形代数の演算)\n", "- `numpy.linalg.norm` [5/5-3#▲線形代数の演算](5/5-3.ipynb#▲線形代数の演算)\n", "- `numpy.linspace` [5/5-3#`linspace`](5/5-3.ipynb#linspace)\n", "- `numpy.loadtxt` [5/5-3#配列の保存と復元](5/5-3.ipynb#配列の保存と復元)\n", "- `numpy.matmul` [5/5-3#▲線形代数の演算](5/5-3.ipynb#▲線形代数の演算)\n", "- `numpy.ndarray` [5/5-3#配列の構築](5/5-3.ipynb#配列の構築)\n", "- `numpy.ones` [5/5-3#`zeros` と `ones`](5/5-3.ipynb#zeros-と-ones)\n", "- `numpy.random.binomial` [5/5-3#`random.rand`](5/5-3.ipynb#random.rand)\n", "- `numpy.random.poisson` [5/5-3#`random.rand`](5/5-3.ipynb#random.rand)\n", "- `numpy.random.rand` [5/5-3#`random.rand`](5/5-3.ipynb#random.rand)\n", "- `numpy.random.randn` [5/5-3#`random.rand`](5/5-3.ipynb#random.rand)\n", "- `numpy.savetxt` [5/5-3#配列の保存と復元](5/5-3.ipynb#配列の保存と復元)\n", "- `numpy.sort` [5/5-3#`sort`](5/5-3.ipynb#sort)\n", "- `numpy.sqrt` [5/5-3#ユニバーサル関数](5/5-3.ipynb#ユニバーサル関数)\n", "- `numpy.zeros` [5/5-3#`zeros` と `ones`](5/5-3.ipynb#zeros-と-ones)\n", "- `on` [7/7-1#▲データの結合](7/7-1.ipynb#▲データの結合)\n", "- `open` [4/4-1#ファイルのオープン](4/4-1.ipynb#ファイルのオープン)\n", "- `or` [1/1-3#様々な条件](1/1-3.ipynb#様々な条件)\n", "- `ord` [3/3-2#for文による繰り返し](3/3-2.ipynb#for文による繰り返し)\n", "- `os.chdir` [4/4-3#カレントワーキングディレクトリ](4/4-3.ipynb#カレントワーキングディレクトリ)\n", "- pandas [7/7-1#7-1. pandasライブラリ](7/7-1.ipynb#7-1.-pandasライブラリ)\n", "- parameter [3/3-3#引数](3/3-3.ipynb#引数)\n", "- pass文 [3/3-2#pass文](3/3-2.ipynb#pass文)\n", "- `plot` [appendix/5-matplotlib#線グラフ](appendix/5-matplotlib.ipynb#線グラフ)\n", "- pop [appendix/2-set#pop](appendix/2-set.ipynb#pop)\n", "- `pop` [3/3-1#▲キーを指定した削除](3/3-1.ipynb#▲キーを指定した削除), [2/2-2#▲リストからインデックスで指定した要素を削除する](2/2-2.ipynb#▲リストからインデックスで指定した要素を削除する)\n", "- `predict` [7/7-2#教師あり学習・分類の例](7/7-2.ipynb#教師あり学習・分類の例)\n", "- `print` [1/1-2#`print`](1/1-2.ipynb#print)\n", "- `quad` [appendix/5-bokeh#ヒストグラム](appendix/5-bokeh.ipynb#ヒストグラム)\n", "- `raise` [6/6-3#特殊メソッド](6/6-3.ipynb#特殊メソッド)\n", "- `range` [3/3-2#`range`](3/3-2.ipynb#range), [3/3-2#`range` とリスト](3/3-2.ipynb#range-とリスト)\n", "- `ravel` [5/5-3#多次元配列](5/5-3.ipynb#多次元配列)\n", "- `re.I` [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- `re.IGNORECASE` [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- `read` [4/4-1#ファイル全体の読み込み](4/4-1.ipynb#ファイル全体の読み込み)\n", "- `read_csv` [7/7-1#CSVファイルからのデータフレームの作成](7/7-1.ipynb#CSVファイルからのデータフレームの作成)\n", "- `readline` [4/4-1#行の読み込み](4/4-1.ipynb#行の読み込み)\n", "- remove [appendix/2-set#remove](appendix/2-set.ipynb#remove)\n", "- `remove` [2/2-2#▲リストから要素を削除する](2/2-2.ipynb#▲リストから要素を削除する)\n", "- `replace` [2/2-1#置換](2/2-1.ipynb#置換)\n", "- `reshape` [5/5-3#多次元配列](5/5-3.ipynb#多次元配列)\n", "- `return` [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [3/3-3#返値](3/3-3.ipynb#返値)\n", "- return文 [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [3/3-2#制御構造とreturn文](3/3-2.ipynb#制御構造とreturn文)\n", "- `reverse` [6/6-2#`sorted`](6/6-2.ipynb#sorted), [2/2-2#▲リストの要素を逆順にする](2/2-2.ipynb#▲リストの要素を逆順にする)\n", "- `savefig` [appendix/5-matplotlib#グラフの画像ファイル出力](appendix/5-matplotlib.ipynb#グラフの画像ファイル出力)\n", "- `scatter` [appendix/5-bokeh#散布図](appendix/5-bokeh.ipynb#散布図), [appendix/5-matplotlib#散布図](appendix/5-matplotlib.ipynb#散布図)\n", "- scikit-learn [7/7-2#7-2. scikit-learnライブラリ](7/7-2.ipynb#7-2.-scikit-learnライブラリ)\n", "- `search` [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- `set` [appendix/2-set#▲セット (set)](appendix/2-set.ipynb#▲セット-(set))\n", "- `setdefault` [3/3-1#▲キーがない場合に登録を行う](3/3-1.ipynb#▲キーがない場合に登録を行う)\n", "- shebang [appendix/5-command#shebang](appendix/5-command.ipynb#shebang)\n", "- `sort` [2/2-2#並べ替え(`sort` メソッド)](2/2-2.ipynb#並べ替え(sort-メソッド)), [5/5-3#`sort`](5/5-3.ipynb#sort)\n", "- `sort_index` [7/7-1#データの並び替え](7/7-1.ipynb#データの並び替え)\n", "- `sort_values` [7/7-1#データの並び替え](7/7-1.ipynb#データの並び替え)\n", "- `sorted` [6/6-2#`sorted`](6/6-2.ipynb#sorted), [2/2-2#並べ替え(`sorted` 組み込み関数)](2/2-2.ipynb#並べ替え(sorted-組み込み関数))\n", "- `split` [appendix/5-re#`re.split`](appendix/5-re.ipynb#re.split), [2/2-2#リストと文字列の相互変換](2/2-2.ipynb#リストと文字列の相互変換)\n", "- `str` [2/2-1#2-1. 文字列 (string)](2/2-1.ipynb#2-1.-文字列-(string)), [2/2-1#2-1. 文字列 (string)](2/2-1.ipynb#2-1.-文字列-(string))\n", "- `sub` [appendix/5-re#`sub`](appendix/5-re.ipynb#sub)\n", "- `sum` [6/6-1#リスト内包表記](6/6-1.ipynb#リスト内包表記), [2/2-2#`sum`](2/2-2.ipynb#sum), [5/5-3#`sum`, `max`, `min`, `mean`](5/5-3.ipynb#sum,-max,-min,-mean)\n", "- `super` [6/6-3#継承](6/6-3.ipynb#継承)\n", "- `title` [appendix/5-matplotlib#線グラフ](appendix/5-matplotlib.ipynb#線グラフ)\n", "- `transform` [7/7-2#教師なし学習・次元削減の例](7/7-2.ipynb#教師なし学習・次元削減の例)\n", "- `tuple` [2/2-2#タプル (tuple)](2/2-2.ipynb#タプル-(tuple))\n", "- `type` [2/2-1#2-1. 文字列 (string)](2/2-1.ipynb#2-1.-文字列-(string))\n", "- union [appendix/2-set#union, intersection, difference](appendix/2-set.ipynb#union,-intersection,-difference)\n", "- `upper` [2/2-1#大文字・小文字](2/2-1.ipynb#大文字・小文字)\n", "- value [3/3-1#3-1. 辞書 (dictionary)](3/3-1.ipynb#3-1.-辞書-(dictionary))\n", "- `values` [3/3-1#値の一覧を得る](3/3-1.ipynb#値の一覧を得る), [3/3-2#for文による繰り返しと辞書](3/3-2.ipynb#for文による繰り返しと辞書)\n", "- `vbar` [appendix/5-bokeh#棒グラフ](appendix/5-bokeh.ipynb#棒グラフ)\n", "- `while` [3/3-2#while文による繰り返し](3/3-2.ipynb#while文による繰り返し)\n", "- while文 [3/3-2#while文による繰り返し](3/3-2.ipynb#while文による繰り返し)\n", "- `with` [4/4-1#ファイルに対するwith文](4/4-1.ipynb#ファイルに対するwith文)\n", "- with文 [6/6-3#▲with文への対応](6/6-3.ipynb#▲with文への対応)\n", "- `write` [4/4-1#ファイルへの書き込み](4/4-1.ipynb#ファイルへの書き込み)\n", "- `xlabel` [appendix/5-matplotlib#線グラフ](appendix/5-matplotlib.ipynb#線グラフ)\n", "- `ylabel` [appendix/5-matplotlib#線グラフ](appendix/5-matplotlib.ipynb#線グラフ)\n", "- 値 [3/3-1#3-1. 辞書 (dictionary)](3/3-1.ipynb#3-1.-辞書-(dictionary))\n", "- 余り [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- イテラブル [6/6-2#リストからイテラブルへ](6/6-2.ipynb#リストからイテラブルへ), [4/4-2#for文とイテラブルとイテレータ](4/4-2.ipynb#for文とイテラブルとイテレータ)\n", "- イテレータ [6/6-2#`map`](6/6-2.ipynb#map), [6/6-1#▲ジェネレータ式](6/6-1.ipynb#▲ジェネレータ式), [4/4-2#for文とイテラブルとイテレータ](4/4-2.ipynb#for文とイテラブルとイテレータ)\n", "- 入れ子 [6/6-1#内包表記の入れ子](6/6-1.ipynb#内包表記の入れ子), [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [3/3-2#for文の入れ子](3/3-2.ipynb#for文の入れ子), [3/3-2#for文の入れ子](3/3-2.ipynb#for文の入れ子), [2/2-3#`if` ... `else` による条件分岐](2/2-3.ipynb#if-...-else-による条件分岐)\n", "- 印字 [1/1-2#`print`](1/1-2.ipynb#print)\n", "- インスタンス [6/6-3#クラス定義](6/6-3.ipynb#クラス定義)\n", "- インデックス [7/7-1#シリーズとデータフレーム](7/7-1.ipynb#シリーズとデータフレーム), [2/2-1#文字列とインデックス](2/2-1.ipynb#文字列とインデックス)\n", "- インデント [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [2/2-3#インデントによる構文](2/2-3.ipynb#インデントによる構文)\n", "- インプレース [2/2-2#破壊的(インプレース)な操作と非破壊的な生成](2/2-2.ipynb#破壊的(インプレース)な操作と非破壊的な生成)\n", "- インポート [1/1-1#数学関数(モジュールのインポート)](1/1-1.ipynb#数学関数(モジュールのインポート)), [5/5-1#モジュールのインポート](5/5-1.ipynb#モジュールのインポート)\n", "- エスケープシーケンス [4/4-1#ファイルへの書き込み](4/4-1.ipynb#ファイルへの書き込み), [2/2-1#▲エスケープシーケンス](2/2-1.ipynb#▲エスケープシーケンス)\n", "- エラー [1/1-1#エラー](1/1-1.ipynb#エラー)\n", "- 大文字 [2/2-1#大文字・小文字](2/2-1.ipynb#大文字・小文字)\n", "- オブジェクト [6/6-3#クラス定義](6/6-3.ipynb#クラス定義), [1/1-3#オブジェクト](1/1-3.ipynb#オブジェクト)\n", "- オブジェクト指向プログラミング [6/6-3#クラス定義](6/6-3.ipynb#クラス定義)\n", "- オブジェクトの同一性 [2/2-2#▲オブジェクトの等価性と同一性](2/2-2.ipynb#▲オブジェクトの等価性と同一性)\n", "- オブジェクトの等価性 [2/2-2#▲オブジェクトの等価性と同一性](2/2-2.ipynb#▲オブジェクトの等価性と同一性)\n", "- 親クラス [6/6-3#継承](6/6-3.ipynb#継承)\n", "- オーダー [3/3-2#for文の計算量](3/3-2.ipynb#for文の計算量)\n", "- オープン [4/4-1#ファイルのオープン](4/4-1.ipynb#ファイルのオープン)\n", "- 返値 [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [3/3-3#返値](3/3-3.ipynb#返値)\n", "- 書き込みモード [4/4-1#ファイルへの書き込み](4/4-1.ipynb#ファイルへの書き込み)\n", "- 掛け算 [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- 数え上げ [2/2-1#数え上げ](2/2-1.ipynb#数え上げ)\n", "- 型 [2/2-1#2-1. 文字列 (string)](2/2-1.ipynb#2-1.-文字列-(string))\n", "- 形 [5/5-3#多次元配列](5/5-3.ipynb#多次元配列)\n", "- 括弧 [1/1-1#演算子の優先順位と括弧](1/1-1.ipynb#演算子の優先順位と括弧)\n", "- 可変長引数 [3/3-3#▲可変長引数](3/3-3.ipynb#▲可変長引数)\n", "- 仮引数 [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [3/3-3#引数](3/3-3.ipynb#引数)\n", "- カレントディレクトリ [4/4-3#カレントワーキングディレクトリ](4/4-3.ipynb#カレントワーキングディレクトリ)\n", "- カレントワーキングディレクトリ [4/4-3#カレントワーキングディレクトリ](4/4-3.ipynb#カレントワーキングディレクトリ)\n", "- 関数 [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [3/3-3#関数の定義](3/3-3.ipynb#関数の定義)\n", "- 関数定義 [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [3/3-3#関数の定義](3/3-3.ipynb#関数の定義)\n", "- 木 [4/4-3#木構造](4/4-3.ipynb#木構造)\n", "- 機械学習 [7/7-2#機械学習について](7/7-2.ipynb#機械学習について)\n", "- 木構造 [4/4-3#木構造](4/4-3.ipynb#木構造)\n", "- キャプチャ [appendix/5-re#`group`](appendix/5-re.ipynb#group)\n", "- 教師あり学習 [7/7-2#教師あり学習](7/7-2.ipynb#教師あり学習)\n", "- 教師なし学習 [7/7-2#教師なし学習](7/7-2.ipynb#教師なし学習)\n", "- 兄弟 [4/4-3#木構造](4/4-3.ipynb#木構造)\n", "- キー [3/3-1#3-1. 辞書 (dictionary)](3/3-1.ipynb#3-1.-辞書-(dictionary))\n", "- キーワード引数 [3/3-3#▲キーワード引数](3/3-3.ipynb#▲キーワード引数)\n", "- 偽 [1/1-3#真理値を返す関数](1/1-3.ipynb#真理値を返す関数)\n", "- 行番号 [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値)\n", "- 空行 [1/1-2#コメントと空行](1/1-2.ipynb#コメントと空行)\n", "- 空タプル [2/2-2#タプル (tuple)](2/2-2.ipynb#タプル-(tuple))\n", "- 空白 [1/1-1#空白](1/1-1.ipynb#空白)\n", "- 空白文字 [appendix/5-re#メタ文字](appendix/5-re.ipynb#メタ文字), [2/2-1#▲空白文字の削除](2/2-1.ipynb#▲空白文字の削除)\n", "- 空文字列 [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本), [2/2-1#空文字列](2/2-1.ipynb#空文字列)\n", "- 空リスト [2/2-2#2-2. リスト (list)](2/2-2.ipynb#2-2.-リスト-(list))\n", "- 空列 [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本), [2/2-1#空文字列](2/2-1.ipynb#空文字列)\n", "- 組み込み関数 [1/1-2#`print`](1/1-2.ipynb#print)\n", "- 組み込み定数 [1/1-3#真理値を返す関数](1/1-3.ipynb#真理値を返す関数)\n", "- クラス [6/6-3#クラス定義](6/6-3.ipynb#クラス定義)\n", "- クラスタリング [7/7-2#教師なし学習・クラスタリングの例](7/7-2.ipynb#教師なし学習・クラスタリングの例)\n", "- 繰り返し [3/3-2#3-2. 繰り返し](3/3-2.ipynb#3-2.-繰り返し)\n", "- クローズ [4/4-1#ファイルのクローズ](4/4-1.ipynb#ファイルのクローズ)\n", "- グラフ [appendix/5-matplotlib#線グラフ](appendix/5-matplotlib.ipynb#線グラフ)\n", "- グローバル変数 [1/1-2#▲グローバル変数](1/1-2.ipynb#▲グローバル変数), [3/3-3#変数とスコープ](3/3-3.ipynb#変数とスコープ)\n", "- 計算量 [3/3-2#for文の計算量](3/3-2.ipynb#for文の計算量), [3/3-2#for文の計算量](3/3-2.ipynb#for文の計算量)\n", "- 計算量のオーダー [3/3-2#for文の計算量](3/3-2.ipynb#for文の計算量)\n", "- 継承 [6/6-3#継承](6/6-3.ipynb#継承)\n", "- 検索 [2/2-1#検索](2/2-1.ipynb#検索)\n", "- 親 [4/4-3#木構造](4/4-3.ipynb#木構造)\n", "- 子 [4/4-3#木構造](4/4-3.ipynb#木構造)\n", "- 高階関数 [6/6-2#`max`](6/6-2.ipynb#max)\n", "- 構文エラー [1/1-4#構文エラー](1/1-4.ipynb#構文エラー), [1/1-1#エラー](1/1-1.ipynb#エラー)\n", "- 子クラス [6/6-3#継承](6/6-3.ipynb#継承)\n", "- コマンドライン実行 [appendix/5-command#▲Pythonスクリプトとコマンドライン実行](appendix/5-command.ipynb#▲Pythonスクリプトとコマンドライン実行)\n", "- コマンドライン引数 [appendix/5-command#コマンドライン引数](appendix/5-command.ipynb#コマンドライン引数)\n", "- コメント [1/1-2#コメントと空行](1/1-2.ipynb#コメントと空行), [1/1-1#コメント](1/1-1.ipynb#コメント)\n", "- 小文字 [2/2-1#大文字・小文字](2/2-1.ipynb#大文字・小文字)\n", "- コンストラクタ [6/6-3#クラス定義](6/6-3.ipynb#クラス定義)\n", "- コーディングスタイル [1/1-4#コーディングスタイル](1/1-4.ipynb#コーディングスタイル)\n", "- 再帰 [appendix/3-recursion#▲再帰](appendix/3-recursion.ipynb#▲再帰), [1/1-3#▲再帰](1/1-3.ipynb#▲再帰)\n", "- 再帰関数 [appendix/3-recursion#▲再帰](appendix/3-recursion.ipynb#▲再帰)\n", "- 再帰呼び出し [appendix/3-recursion#▲再帰](appendix/3-recursion.ipynb#▲再帰)\n", "- 作業ディレクトリ [4/4-3#カレントワーキングディレクトリ](4/4-3.ipynb#カレントワーキングディレクトリ)\n", "- 差集合 [appendix/2-set#集合演算](appendix/2-set.ipynb#集合演算), [appendix/2-set#union, intersection, difference](appendix/2-set.ipynb#union,-intersection,-difference)\n", "- 散布図 [appendix/5-matplotlib#散布図](appendix/5-matplotlib.ipynb#散布図)\n", "- 子孫 [4/4-3#木構造](4/4-3.ipynb#木構造)\n", "- 集合 [appendix/2-set#▲セット (set)](appendix/2-set.ipynb#▲セット-(set))\n", "- 集合演算 [appendix/2-set#集合演算](appendix/2-set.ipynb#集合演算)\n", "- 商 [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- 初期化 [6/6-3#初期化と属性](6/6-3.ipynb#初期化と属性)\n", "- 初期値 [3/3-3#▲引数の初期値](3/3-3.ipynb#▲引数の初期値)\n", "- 仕様 [1/1-4#仕様・テスト・デバッグ](1/1-4.ipynb#仕様・テスト・デバッグ)\n", "- シリーズ [7/7-1#シリーズとデータフレーム](7/7-1.ipynb#シリーズとデータフレーム)\n", "- 真 [1/1-3#真理値を返す関数](1/1-3.ipynb#真理値を返す関数)\n", "- 真理値 [1/1-3#真理値を返す関数](1/1-3.ipynb#真理値を返す関数)\n", "- 真理値配列によるインデックスアクセス [7/7-1#データの条件取り出し](7/7-1.ipynb#データの条件取り出し), [5/5-3#▲真理値配列によるインデックスアクセス](5/5-3.ipynb#▲真理値配列によるインデックスアクセス)\n", "- ジェネレータ式 [6/6-1#▲ジェネレータ式](6/6-1.ipynb#▲ジェネレータ式)\n", "- 次元削減 [7/7-2#教師なし学習・次元削減の例](7/7-2.ipynb#教師なし学習・次元削減の例)\n", "- 辞書 [3/3-1#3-1. 辞書 (dictionary)](3/3-1.ipynb#3-1.-辞書-(dictionary))\n", "- 辞書型の可変長引数 [3/3-3#▲辞書型の可変長引数](3/3-3.ipynb#▲辞書型の可変長引数)\n", "- 辞書内包表記 [6/6-1#▲辞書内包表記](6/6-1.ipynb#▲辞書内包表記)\n", "- 実行時エラー [1/1-4#実行時エラー](1/1-4.ipynb#実行時エラー), [1/1-1#エラー](1/1-1.ipynb#エラー)\n", "- 実数 [1/1-1#整数と実数](1/1-1.ipynb#整数と実数)\n", "- 実引数 [3/3-3#引数](3/3-3.ipynb#引数)\n", "- 条件付き内包表記 [6/6-1#▲条件付き内包表記](6/6-1.ipynb#▲条件付き内包表記)\n", "- 条件分岐 [1/1-3#if文による条件分岐](1/1-3.ipynb#if文による条件分岐), [2/2-3#2-3. 条件分岐](2/2-3.ipynb#2-3.-条件分岐)\n", "- 剰余 [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- 除算 [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- 数値誤差 [1/1-1#数値誤差](1/1-1.ipynb#数値誤差)\n", "- スライス [7/7-1#データの参照](7/7-1.ipynb#データの参照), [2/2-1#文字列とスライス](2/2-1.ipynb#文字列とスライス), [5/5-3#スライス](5/5-3.ipynb#スライス)\n", "- 正規表現 [appendix/5-re#▲正規表現](appendix/5-re.ipynb#▲正規表現)\n", "- 整数 [1/1-1#整数と実数](1/1-1.ipynb#整数と実数)\n", "- 整数除算 [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- 積集合 [appendix/2-set#集合演算](appendix/2-set.ipynb#集合演算), [appendix/2-set#union, intersection, difference](appendix/2-set.ipynb#union,-intersection,-difference)\n", "- セット [appendix/2-set#▲セット (set)](appendix/2-set.ipynb#▲セット-(set))\n", "- セット内包表記 [6/6-1#▲セット内包表記](6/6-1.ipynb#▲セット内包表記)\n", "- 線形回帰 [appendix/4-csv#東京の7月の気温](appendix/4-csv.ipynb#東京の7月の気温), [7/7-2#教師あり学習・回帰の例](7/7-2.ipynb#教師あり学習・回帰の例)\n", "- 選択 [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- 絶対パス [4/4-3#パス](4/4-3.ipynb#パス)\n", "- 相対パス [4/4-3#パス](4/4-3.ipynb#パス)\n", "- 祖先 [4/4-3#木構造](4/4-3.ipynb#木構造)\n", "- 属性 [6/6-3#初期化と属性](6/6-3.ipynb#初期化と属性)\n", "- 属性名 [6/6-3#初期化と属性](6/6-3.ipynb#初期化と属性)\n", "- 対称差 [appendix/2-set#集合演算](appendix/2-set.ipynb#集合演算), [appendix/2-set#union, intersection, difference](appendix/2-set.ipynb#union,-intersection,-difference)\n", "- 足し算 [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- 多次元配列 [5/5-3#多次元配列](5/5-3.ipynb#多次元配列)\n", "- 多重代入 [2/2-2#多重代入](2/2-2.ipynb#多重代入)\n", "- 多重リスト [2/2-2#多重リスト](2/2-2.ipynb#多重リスト)\n", "- タプル [2/2-2#タプル (tuple)](2/2-2.ipynb#タプル-(tuple))\n", "- 単項演算子 [1/1-1#単項の `+` と `-`](1/1-1.ipynb#単項の-+-と--)\n", "- 代入 [1/1-2#代入文](1/1-2.ipynb#代入文)\n", "- 代入演算子 [1/1-2#累積代入文](1/1-2.ipynb#累積代入文)\n", "- 代入文 [1/1-2#代入文](1/1-2.ipynb#代入文)\n", "- 置換 [2/2-1#置換](2/2-1.ipynb#置換)\n", "- テスト [1/1-4#仕様・テスト・デバッグ](1/1-4.ipynb#仕様・テスト・デバッグ)\n", "- テストケース [1/1-4#仕様・テスト・デバッグ](1/1-4.ipynb#仕様・テスト・デバッグ)\n", "- ディレクトリ [4/4-3#ディレクトリと階層構造](4/4-3.ipynb#ディレクトリと階層構造)\n", "- デバッグ [1/1-2#`print`](1/1-2.ipynb#print), [1/1-4#仕様・テスト・デバッグ](1/1-4.ipynb#仕様・テスト・デバッグ)\n", "- データ型 [2/2-1#2-1. 文字列 (string)](2/2-1.ipynb#2-1.-文字列-(string))\n", "- データフレーム [7/7-1#シリーズとデータフレーム](7/7-1.ipynb#シリーズとデータフレーム)\n", "- 特殊メソッド [6/6-3#特殊メソッド](6/6-3.ipynb#特殊メソッド)\n", "- 特徴量 [7/7-2#データ](7/7-2.ipynb#データ)\n", "- トップレベル [1/1-2#▲グローバル変数](1/1-2.ipynb#▲グローバル変数)\n", "- 内包表記 [6/6-1#6-1. 内包表記](6/6-1.ipynb#6-1.-内包表記), [6/6-1#リスト内包表記](6/6-1.ipynb#リスト内包表記), [2/2-2#for文によるリスト初期化の短縮記法](2/2-2.ipynb#for文によるリスト初期化の短縮記法)\n", "- 根 [4/4-3#木構造](4/4-3.ipynb#木構造)\n", "- ネスト [6/6-1#内包表記の入れ子](6/6-1.ipynb#内包表記の入れ子), [3/3-2#for文の入れ子](3/3-2.ipynb#for文の入れ子), [2/2-3#`if` ... `else` による条件分岐](2/2-3.ipynb#if-...-else-による条件分岐)\n", "- ノード [4/4-3#木構造](4/4-3.ipynb#木構造)\n", "- 葉 [4/4-3#木構造](4/4-3.ipynb#木構造)\n", "- 配列 [2/2-2#2-2. リスト (list)](2/2-2.ipynb#2-2.-リスト-(list)), [5/5-3#配列の構築](5/5-3.ipynb#配列の構築)\n", "- 配列同士の演算 [5/5-3#配列同士の演算](5/5-3.ipynb#配列同士の演算)\n", "- 配列のスカラ演算 [5/5-3#配列のスカラ演算](5/5-3.ipynb#配列のスカラ演算)\n", "- 配列のデータ属性 [5/5-3#▲配列のデータ属性](5/5-3.ipynb#▲配列のデータ属性)\n", "- 破壊的 [2/2-2#破壊的(インプレース)な操作と非破壊的な生成](2/2-2.ipynb#破壊的(インプレース)な操作と非破壊的な生成)\n", "- 半角の空白 [1/1-1#空白](1/1-1.ipynb#空白)\n", "- バグ [1/1-2#`print`](1/1-2.ipynb#print), [1/1-4#仕様・テスト・デバッグ](1/1-4.ipynb#仕様・テスト・デバッグ)\n", "- パス [4/4-3#パス](4/4-3.ipynb#パス)\n", "- パターン [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- 比較演算 [appendix/2-set#比較演算](appendix/2-set.ipynb#比較演算)\n", "- 比較演算子 [1/1-3#様々な条件](1/1-3.ipynb#様々な条件)\n", "- 引き算 [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- 引数 [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [1/1-2#関数の定義と返値](1/1-2.ipynb#関数の定義と返値), [3/3-3#関数の定義](3/3-3.ipynb#関数の定義)\n", "- ヒストグラム [appendix/5-matplotlib#ヒストグラム](appendix/5-matplotlib.ipynb#ヒストグラム)\n", "- 否定文字クラス [appendix/5-re#文字クラス](appendix/5-re.ipynb#文字クラス)\n", "- 非破壊的 [2/2-2#破壊的(インプレース)な操作と非破壊的な生成](2/2-2.ipynb#破壊的(インプレース)な操作と非破壊的な生成)\n", "- ヒートマップ [appendix/5-matplotlib#ヒートマップ](appendix/5-matplotlib.ipynb#ヒートマップ)\n", "- ファイル [4/4-1#ファイルのオープン](4/4-1.ipynb#ファイルのオープン)\n", "- ファイルオブジェクト [4/4-1#ファイルのオープン](4/4-1.ipynb#ファイルのオープン)\n", "- フォルダ [4/4-3#ディレクトリと階層構造](4/4-3.ipynb#ディレクトリと階層構造)\n", "- 浮動小数点数 [1/1-1#整数と実数](1/1-1.ipynb#整数と実数)\n", "- 分割統治 [appendix/3-recursion#▲再帰](appendix/3-recursion.ipynb#▲再帰)\n", "- 閉包 [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- 変数 [1/1-2#変数](1/1-2.ipynb#変数), [2/2-1#初心者によくある誤解 --- 変数と文字列の混乱](2/2-1.ipynb#初心者によくある誤解-----変数と文字列の混乱)\n", "- 変数定義 [1/1-2#変数](1/1-2.ipynb#変数)\n", "- べき乗 [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- べき表示 [1/1-1#実数のべき表示](1/1-1.ipynb#実数のべき表示)\n", "- 棒グラフ [appendix/5-matplotlib#棒グラフ](appendix/5-matplotlib.ipynb#棒グラフ)\n", "- マジックコマンド [appendix/3-visualization#`matplotlib`](appendix/3-visualization.ipynb#matplotlib)\n", "- マッチする [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- 無名関数 [6/6-2#ラムダ式](6/6-2.ipynb#ラムダ式)\n", "- メソッド [2/2-1#文字列とメソッド](2/2-1.ipynb#文字列とメソッド)\n", "- 文字クラス [appendix/5-re#文字クラス](appendix/5-re.ipynb#文字クラス)\n", "- 文字コード [appendix/4-csv#東京の7月の気温](appendix/4-csv.ipynb#東京の7月の気温), [4/4-1#ファイルの読み書きにおける文字コード指定](4/4-1.ipynb#ファイルの読み書きにおける文字コード指定)\n", "- 文字コード宣言 [appendix/5-command#文字コード宣言](appendix/5-command.ipynb#文字コード宣言)\n", "- モジュール [1/1-1#数学関数(モジュールのインポート)](1/1-1.ipynb#数学関数(モジュールのインポート)), [5/5-1#モジュールのインポート](5/5-1.ipynb#モジュールのインポート), [5/5-2#5-2. モジュールの作り方](5/5-2.ipynb#5-2.-モジュールの作り方)\n", "- モジュール名 [5/5-2#自作モジュールの使い方](5/5-2.ipynb#自作モジュールの使い方)\n", "- モジュールレベル [1/1-2#▲グローバル変数](1/1-2.ipynb#▲グローバル変数)\n", "- 文字列 [2/2-1#2-1. 文字列 (string)](2/2-1.ipynb#2-1.-文字列-(string)), [2/2-1#初心者によくある誤解 --- 変数と文字列の混乱](2/2-1.ipynb#初心者によくある誤解-----変数と文字列の混乱)\n", "- 文字列の比較演算 [2/2-1#文字列の比較演算](2/2-1.ipynb#文字列の比較演算)\n", "- 優先順位 [1/1-1#演算子の優先順位と括弧](1/1-1.ipynb#演算子の優先順位と括弧)\n", "- ユニバーサル関数 [5/5-3#ユニバーサル関数](5/5-3.ipynb#ユニバーサル関数)\n", "- 読み込みモード [4/4-1#ファイルのオープン](4/4-1.ipynb#ファイルのオープン)\n", "- 予約語 [1/1-2#予約語](1/1-2.ipynb#予約語)\n", "- ライブラリ [1/1-1#数学関数(モジュールのインポート)](1/1-1.ipynb#数学関数(モジュールのインポート))\n", "- ラムダ式 [6/6-2#ラムダ式](6/6-2.ipynb#ラムダ式)\n", "- リスト [2/2-2#2-2. リスト (list)](2/2-2.ipynb#2-2.-リスト-(list))\n", "- 累算代入文 [1/1-2#累積代入文](1/1-2.ipynb#累積代入文)\n", "- ループ [3/3-2#for文による繰り返し](3/3-2.ipynb#for文による繰り返し)\n", "- 連結 [2/2-1#文字列の連結](2/2-1.ipynb#文字列の連結)\n", "- 連接 [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- ロジスティック回帰 [7/7-2#教師あり学習・分類の例](7/7-2.ipynb#教師あり学習・分類の例)\n", "- 論理エラー [1/1-4#論理エラー](1/1-4.ipynb#論理エラー)\n", "- ローカル変数 [1/1-2#ローカル変数](1/1-2.ipynb#ローカル変数), [3/3-3#引数](3/3-3.ipynb#引数), [3/3-3#変数とスコープ](3/3-3.ipynb#変数とスコープ)\n", "- 和 [appendix/5-re#正規表現の基本](appendix/5-re.ipynb#正規表現の基本)\n", "- ワイルドカード [5/5-1#`from`](5/5-1.ipynb#from)\n", "- 和集合 [appendix/2-set#集合演算](appendix/2-set.ipynb#集合演算), [appendix/2-set#union, intersection, difference](appendix/2-set.ipynb#union,-intersection,-difference)\n", "- 割り算 [1/1-1#簡単な算術計算](1/1-1.ipynb#簡単な算術計算)\n", "- ワーキングディレクトリ [4/4-3#カレントワーキングディレクトリ](4/4-3.ipynb#カレントワーキングディレクトリ)\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: docs/.buildinfo ================================================ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. config: 437ac5071ea112519a59ccef14f2ccf9 tags: 645f666f9bcd5a90fca523b33c5a78b7 ================================================ FILE: docs/.nojekyll ================================================ ================================================ FILE: docs/1/1-0.html ================================================ 1-0. Colaboratory (Colab) の使い方 — Pythonプログラミング入門 documentation

1-0. Colaboratory (Colab) の使い方

Colaboratory(通称 Colab)によるノートブックの操作方法について説明します。

Colaboratoryの立ち上げ

ブラウザにGoogleアカウント(個人でもECCSでもどちらでもよい)でログインした後に、以下のURLを開いてください。

教材のオープン

HTML版の教材の「Open in Colab」をクリックしたり、 Google Drive上の教材を直接Colabratoryでオープンした場合、 指定したノートブックがオープンされますが、ノートブックを操作した結果は Google Drive上に保存されません。 ノートブックの上方にある「ドライブにコピー」のボタンを押せば、 自分のGoogle Drive上にノートブックのコピーが作られてオープンされます。 ノートブックを操作した結果はコピーに保存されます。

なお、ノートブックには ipynb という拡張子(エクステンション)が付いています。

ノートブックの操作

ノートブックの上方のタイトルの下には、「ファイル」や「編集」などのメニュー、 その下には「+ コード」と「+ テキスト」というボタンが表示されています。

Ctrl+s(Macの場合は Cmd+s)を入力することによって、 編集・操作中のノートブックを Google Drive のファイルにセーブできます。 なお、ノートブックは適当なタイミングでオートセーブされます。 ファイルメニューの右に「すべての変更を保存しました」と表示されていれば、 Ctrl+s を入力する必要はありません。

以下の参考文献は、Jupyter Notebook に関する一般的な解説です。 jupyterコマンドを起動してブラウザでノートブックを使うのと、 Google Colaboratory によりノートブックを使うのでは、 インタフェースが大分異なっていることに注意してください。

セル

ノートブックはセルから成り立っています。

主に次の二種類のセルを使います。

  • Codeセル(コードセル): Pythonのコードが書かれたセルです。 Codeセルの左端には [ ] と表示されています。 Codeセルの中のコードを実行するには、 [ ] のところにマウスカーソルを移動してクリックします。 [ ] のところにマウスカーソルを移動すると、●の中に▷が表示されます。 これはプレイボタンを意味します。 プレイボタンを押すとコードが実行され、その結果がセルの下部に挿入されます。 (Shiftを押しながらEnterを押しても実行できます。)

  • Markdownセル(テキストセル): 説明が書かれたセルです。 このセル自身はMarkdownセルです。

[ ]:
1+1

セルの編集

Codeセル上のプレイボタンでないところにマウスカーソルを移動しクリックすると、 Codeセルが選択され、文字カーソルが表示されて、セルの編集が可能になります。 Ctrlの付かない文字はそのまま挿入されます。

以下のような編集コマンドが使えます。

  • Ctrl+c: copy

  • Ctrl+x: cut

  • Ctrl+v: paste

  • Ctrl+z: undo

Codeセルが選択されているとき、Shift+Enter(もしくはShift+Return)を入力すると、 セルの中のコードが実行されて、次のセルが選択されます。

練習

次のCodeセルを選択して 10/3 と入力して実行してください。

[ ]:

Codeセルの実行が終了し、別のセルが選択されると、 セルの左端は [2] のようになり、[ ] の中に番号が入ります。 この番号は、そのCodeセルが何番目に実行されたかを示すもので、 Codeセルが実行されるたびに1ずつ増えます。 同じセルを続けて実行すれば、この番号は1ずつ増えるでしょう。

セルの挿入

Codeセルを新たに挿入するには、 ファイルメニューの下の「+ コード」ボタンを押します。 現在選択されているセルの下にCodeセルが挿入されます。

たとえば、このMarkdownセルを選択してから、 「+ コード」ボタンを押してみてください。 このMarkdownセルを選択するには、マウスカーソルをここに持って来て クリックすればよいです。説明の全体が四角で囲まれるはずです。

Markdownセルを新たに挿入するには、 ファイルメニューの下の「+ テキスト」ボタンを押します。 なお、ここではMarkdownセルの説明は行っていません。

セルの実行が止まらないとき

Codeセルの左端の●の中に□が表示され、 その周りをノの字が回り続けているならば、セルのコードは実行中です。 いつまでたってもコードの実行が終了しない場合は、 そのアイコンを押して、コードの実行を強制終了してください。 ●の中に□が表示されたアイコンはストップボタンを意味します。

たとえば、次のような例です。 プレイボタンを押し実行中であることを確かめてから、 ストップボタンを押してください。

[ ]:
while True:
    pass

セルの操作

セルを選択するとセルの右上に色々なボタンが表示されます。 これらを押すことにより、セルの削除、セルの移動、コピーペーストなど、 セルに対する各種の操作を行うことができます。

ノートブックの参照

Colaboratoryが使用するノードブックは Google Drive 上にあります。 右上の「共有」のボタンを押すことにより、 ノートブックの共有設定を変えることができます。 その上で、ノートブックが表示されているブラウザ上のURLを伝えることにより、 教員やTAにノートブックを見せることができます。

ノートブックのダウンロード

Google Drive 上のノートブックをパソコンにダウンロードするには、 Colaboratoryのファイルメニューで「.ipynb をダウンロード」を選択します。

colab4.png

================================================ FILE: docs/1/1-1.html ================================================ 1-1. 数値演算 — Pythonプログラミング入門 documentation

1-1. 数値演算

数値演算について説明します。

参考

簡単な算術計算

CodeセルにPythonの式を入力して、プレイボタンを押すか、 Shiftを押しながらEnterを押すと、式が評価され、その結果の値がセルの下に挿入されます。

1+1 の計算をしてみましょう。次のセルに 1+1 と入力して、 Shiftを押しながらEnterを押してください。

[ ]:

このようにして、電卓の代わりにPythonを使うことができます。+ は言うまでもなく足し算を表しています。

[1]:
7-2
[1]:
5
[2]:
7*2
[2]:
14
[3]:
7**2
[3]:
49

-引き算*掛け算**べき乗を表しています。

式を適当に書き換えてから、Shiftを押しながらEnterを押すと、 書き換えた後の式が評価されて、セルの下の値はその結果で置き換わります。 たとえば、上の 2100 に書き換えて、7の100乗を求めてみてください。

割り算はどうなるでしょうか。

[4]:
7/2
[4]:
3.5
[5]:
7//2
[5]:
3

Pythonでは、割り算除算)は / で表され、整数除算// で表されます。 // は小数部を切り捨てた整数値()を返します。

整数同士の // の結果は整数になります。

[6]:
7/1
[6]:
7.0
[7]:
7//1
[7]:
7

整数除算の余り剰余)を求めたいときは、別の演算子 % を用います。

整数同士の % の結果は整数になります。

[8]:
7%2
[8]:
1

コメント

Pythonでは一般に、コードの中に # が出現すると、それ以降、その行の終わりまでがコメントになります。 コメントは行頭からも、行の途中からでも始めることができます。

プログラムの実行時には、コメントは無視されます。

[9]:
# このように行頭に '#' をおけば、行全体をコメントとすることができます。

# 次のようにコード行に続けて直前のコードについての説明をコメントとして書くこともできます。
2**10  # 2の10乗を計算します
[9]:
1024
[10]:
# 次のようにコード行自体をコメントとすることで、その行を無視させる(コメントアウトする)こともよく行われます。
# 2**10  # 2の10乗を計算します この行が「コメントアウト」された
2**12  # 実は計算したいのは2の12乗でした
[10]:
4096

整数と実数

Pythonでは、整数と小数点のある数(実数)は、数学的に同じ数を表す場合でも、 コンピュータの中で異なる形式で記憶されますので、表示は異なります。 (実数は浮動小数点数ともいいます。)

[11]:
7/1
[11]:
7.0
[12]:
7//1
[12]:
7

しかし、以下のように、比較を行うと両者は等しいものとして扱われます。 値同士が等しいかどうかを調べる == という演算子については、後で紹介します。

[13]:
7/1 == 7//1
[13]:
True

+-*//%** では、2つの数が整数ならば結果も整数になります。 2つの数が実数であったり、整数と実数が混ざっていたら、結果は実数になります。

[14]:
2+5
[14]:
7
[15]:
2+5.0
[15]:
7.0

/ の結果は必ず実数となります。

[16]:
7/1
[16]:
7.0

ここで、自分で色々と式を入力してみてください。 以下に、いくつかセルを用意しておきます。 足りなければ、Insertメニューを使ってセルを追加することができます。

[ ]:

[ ]:

[ ]:

実数のべき表示

[17]:
2.0**1000
[17]:
1.0715086071862673e+301

非常に大きな実数は、10のべきとともに表示(べき表示)されます。 e+301 は10の301乗を意味します。

[18]:
2.0**-1000
[18]:
9.332636185032189e-302

非常に小さな実数も、10のべきとともに表示されます。 e-302 は10の-302乗を意味します。

いくらでも大きくなる整数

[19]:
2**1000
[19]:
10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

このように、Pythonでは整数はいくらでも大きくなります。 もちろん、コンピュータのメモリに納まる限りにおいてですが。

[20]:
2**2**2**2**2
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File ~/Projects/utpython/lib/python3.12/site-packages/IPython/core/formatters.py:711, in PlainTextFormatter.__call__(self, obj)
    704 stream = StringIO()
    705 printer = pretty.RepresentationPrinter(stream, self.verbose,
    706     self.max_width, self.newline,
    707     max_seq_length=self.max_seq_length,
    708     singleton_pprinters=self.singleton_printers,
    709     type_pprinters=self.type_printers,
    710     deferred_pprinters=self.deferred_printers)
--> 711 printer.pretty(obj)
    712 printer.flush()
    713 return stream.getvalue()

File ~/Projects/utpython/lib/python3.12/site-packages/IPython/lib/pretty.py:394, in RepresentationPrinter.pretty(self, obj)
    391 for cls in _get_mro(obj_class):
    392     if cls in self.type_pprinters:
    393         # printer registered in self.type_pprinters
--> 394         return self.type_pprinters[cls](obj, self, cycle)
    395     else:
    396         # deferred printer
    397         printer = self._in_deferred_types(cls)

File ~/Projects/utpython/lib/python3.12/site-packages/IPython/lib/pretty.py:787, in _repr_pprint(obj, p, cycle)
    785 """A pprint that just redirects to the normal repr function."""
    786 # Find newlines and replace them with p.break_()
--> 787 output = repr(obj)
    788 lines = output.splitlines()
    789 with p.group():

ValueError: Exceeds the limit (4300 digits) for integer string conversion; use sys.set_int_max_str_digits() to increase the limit

整数と実数の間の変換

実数を整数に変換するには、int という関数を用います。 (関数に関する一般的な説明は1-2を参照してください。) int(x) は、実数 x を(0 の方向に)切り下げた結果を返します。

[21]:
int(2.9)
[21]:
2
[22]:
int(-2.9)
[22]:
-2

逆に、整数を実数に変換するには、float という関数を用います。 float(i) は、整数 i を実数に変換した結果を返します。 たとえば i+0.0 としても、i を実数に変換できます。

[23]:
float(2)
[23]:
2.0
[24]:
2+0.0
[24]:
2.0

数値誤差

浮動小数点数には、数値誤差が不可避です。 これは、有限のビット数で、無限に小さくなり得る小数刻みを表現しようとするためです。 (参照:Wikipedia - 浮動小数点数

Pythonでは、整数は無限桁で表現されるため、整数演算には誤差が生じません。 しかし、整数を実数に変換したときには、一般に誤差が生じます。

[25]:
10**60
[25]:
1000000000000000000000000000000000000000000000000000000000000
[26]:
float(10**60)
[26]:
1e+60
[27]:
int(float(10**60))
[27]:
999999999999999949387135297074018866963645011013410073083904

数え上げのような離散的な値を扱う時には、実数を経由せずに、整数のみで演算するようにしましょう。

演算子の優先順位と括弧

掛け算や割り算は足し算や引き算よりも先に評価されます。 すなわち、掛け算や割り算の方が足し算や引き算よりも優先順位が高いと定義されています。

括弧を使って式の評価順序を指定することができます。

なお、数式 \(a(b-c)\)\((a-b)(c-d)\) は、それぞれ \(a\)\(b-c\)\(a-b\)\(c-d\) の積を意味しますが、 コードでは、a*(b-c)(a-b)*(c-d) のように積の演算子である * を明記する必要があることに注意してください。

また、数や演算子の間には、自由に空白を入れることができます。(後でもう一度説明します。)

[28]:
7 - 2 * 3
[28]:
1
[29]:
(7 - 2) * 3
[29]:
15
[30]:
17 - 17//3*3
[30]:
2
[31]:
56 ** 4 ** 2
[31]:
9354238358105289311446368256
[32]:
56 ** 16
[32]:
9354238358105289311446368256

上の例では、4**2 が先に評価されて、56**16 が計算されます。 つまり、x**y**z = x**(y**z) が成り立ちます。 このことをもって、** は右に結合するといいます。

[33]:
16/8/2
[33]:
1.0
[34]:
(16/8)/2
[34]:
1.0

上の例では、16/8 が先に評価されて、2/2 が計算されます。 つまり、x/y/z = (x/y)/z が成り立ちます。 このことをもって、/ は左に結合するといいます。

*/ をまぜても左に結合します。

[35]:
10/2*3
[35]:
15.0

以上のように、演算子によって式の評価の順番がかわりますので注意してください。

ではまた、自分で色々と式を入力してみてください。 以下に、いくつかセルを用意しておきます。

[ ]:

[ ]:

[ ]:

単項の +-

+- は、単項の演算子(単項演算子)としても使えます。 (これらの演算子の後に1つだけ数が書かれます。 前と後の両方に数が書かれる演算子は2項演算子と言います。)

[36]:
-3
[36]:
-3
[37]:
+3
[37]:
3

算術演算子のまとめ

算術演算子を、評価の優先順位にしたがって、すなわち結合力の強い順にまとめておきましょう。

まず、2項のべき演算子 ** が最も強く結合します。 ** は右の方から計算され、このことを「右に結合する」と表します。

次に、単項の +- が強く結合します。 なお、 ** の右側に単項の +- がある場合は、+- がより強く結合します。 例えば、 -10 ** 2 では ** がより強く結合し -100 となり、 10 ** -2 では - がより強く結合し 0.01 となります。

その次に、2項の *///% が強く結合します。これらは左に結合します。

最後に、2項の +- は最も弱く結合します。これらも左に結合します。

空白

既に 7 - 2 * 3 のような例が出てきましたが、 演算子と数の間や、演算子と変数(後述)の間には、空白を入れることができます。 ここで空白とは、半角の空白のことで、英数字と同様に1バイトの文字コードに含まれているものです。

複数の文字から成る演算子、たとえば **// の間に空白を入れることはできません。 エラーになることでしょう。

[38]:
7 **2
[38]:
49
[39]:
7* *2
  Cell In[39], line 1
    7* *2
       ^
SyntaxError: invalid syntax

全角の空白

日本語文字コードである全角の空白は、空白とはみなされませんので注意してください。

[40]:
7 **2
  Cell In[40], line 1
    7 **2
     ^
SyntaxError: invalid non-printable character U+3000

エラー

色々と試していると、エラーが起こることもあったでしょう。 以下は典型的なエラーです。

[41]:
10/0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[41], line 1
----> 1 10/0

ZeroDivisionError: division by zero

このエラーは、ゼロによる割り算を行ったためです。 実行時エラーの典型的なものです。

エラーが起こった場合は、修正して評価し直すことができます。 上の例で、0 をたとえば 3 に書き換えて評価し直してみてください。

[42]:
10/
  Cell In[42], line 1
    10/
       ^
SyntaxError: invalid syntax

こちらのエラーは構文エラーです。 つまり、入力がPythonの構文に違反しているため実行できなかったのです。

数学関数(モジュールのインポート)

[43]:
import math
[44]:
math.sqrt(2)
[44]:
1.4142135623730951

数学関係の各種の関数は、モジュールライブラリ)として提供されています。 これらの関数を使いたいときは、上のように、import で始まる import math というおまじないを一度唱えます。 そうしますと、math というライブラリが読み込まれて(インポートされて)、 math.関数名 という形で関数を用いることができます。 上の例では、平方根を計算する math.sqrt という関数が用いられています。

もう少し例をあげておきましょう。sinとcosは math.sinmath.cos で求まります。

[45]:
math.sin(0)
[45]:
0.0
[46]:
math.pi
[46]:
3.141592653589793

math.pi は、円周率を値とする変数です。

変数については後に説明されます。

[47]:
math.sin(math.pi)
[47]:
1.2246467991473532e-16

この結果は本当は 0 にならなければならないのですが、 数値誤差のためにこのようになっています。

[48]:
math.sin(math.pi/2)
[48]:
1.0
[49]:
math.sin(math.pi/4) * 2
[49]:
1.414213562373095

練習

黄金比を求めてください。黄金比とは、5 の平方根に 1 を加えて 2 で割ったものです。約 1.618 になるはずです。

[ ]:

================================================ FILE: docs/1/1-2.html ================================================ 1-2. 変数と関数の基礎 — Pythonプログラミング入門 documentation

1-2. 変数と関数の基礎

変数と関数の基礎について説明します。

参考

変数

プログラミング言語における変数とは、値に名前を付ける仕組みであり、名前はその値を指し示すことになります。

[1]:
h = 188.0

以上のように = を用いる構文によって、188.0 という値に h という名前が付きます。これを変数定義と呼びます。

定義された変数は、式の中で使うことができます。h という変数自体も式なので、h という式を評価することができ、変数が指し示す値が返ります。

[2]:
h
[2]:
188.0

異なる変数は、いくらでも導入できます。たとえば、以下では w を変数定義します。

[3]:
w = 104.0

ここで、h を身長 (cm)、w を体重 (kg) の意味と考えると、次の式によってBMI(ボディマス指数)を計算できます。

[4]:
w / (h/100.0) ** 2
[4]:
29.425079221367138

なお、演算子 ** の方が / よりも先に評価されることに注意してください。

変数という名前の通り、変数が指し示す値を変えることもできます。

[5]:
w = 104.0-10

このように変数を再定義すれば、元々 w が指し示していた値 104.0 を忘れて、新たな値 94.0 を指し示すようになります。 この後で、前と同じBMIの式を評価してみると、w の値の変化に応じて、BMIの計算結果は変わります。

[6]:
w / (h/100.0) ** 2
[6]:
26.595744680851066

なお、未定義の変数(たとえば BMI)を式の中で用いると、次のようにエラーが生じます。

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-b910749d4383> in <module>
----> 1 BMI  # 未定義の変数

NameError: name 'BMI' is not defined

次のセルの行頭にある # を削除して実行してみましょう。

[7]:
# BMI  # 未定義の変数

以降では、単純のため、変数が指し示す値を、変数の値として説明していきます。

代入文

変数定義に用いた = による構文を、Pythonでは代入文 (assignment statement) と呼びます。 そして、代入文を実行することを代入 (assignment) と言います。 代入文は、= の左辺に右辺の式の評価結果の値を割り当てる文です。 上記の例のように、左辺が変数の場合には、代入文は変数定義と解釈されます。

代入文は、右辺を評価した後に左辺に割り当てるという順番に従います。右辺に出現する変数が左辺に出て来てもかまいません。

[8]:
w = w-10

上の代入文は、w の値を 10 減らす操作となります。= は数学的な等号ではないことに注意してください。

もう一度BMIを計算してみると、w の値が減ったことで、先と結果が変わります。

[9]:
w / (h/100.0) ** 2
[9]:
23.766410140334994

注意: 数学における代入は、substitution(置換)であり、プログラミング言語における代入 (assignment) とは異なります。代入という単語よりも、assignment(割り当て)という単語で概念を覚えましょう。

累積代入文

上の例のように変数の値を減らす操作は、次のような累算代入文 (augmented assignment statement) を使って簡潔に記述することができます。

[10]:
w -= 10

ここで、-= という演算子は、-= を結合させた演算子で、w = w - 10 という代入文と同じ意味になります。 これは代入文と2項演算が複合したものであり、- に限らず、他の2項演算についても同様に複合した累算代入文が利用できます。たとえば、変数の値を増やすには += という演算子を用いることができます。

[11]:
w += 10

= も含めて、これらの演算子は代入演算子と呼ばれています。代入演算子によって変数の値がどのように変わるか、確かめてください。

[ ]:

関数の定義と返値

前述のように、変数の値が変わるたびにBMIの式を入力するのは面倒です。以下では、身長 height と体重 weight をもらって、BMIを計算する関数 bmi を定義してみましょう。関数を定義すると、BMIの式の再入力を省けて便利です。

次のような形式で、関数定義を記述できます。

関数定義など、複数行のコードセルには、行番号を振るのがよいかもしれません。行番号を振るかどうかは、コマンドモードでエルの文字(大文字でも小文字でもよいです)を入力することによって、スイッチできます。行番号があるかないかは、コードの実行には影響しません。

[12]:
def bmi(height, weight):
    return weight / (height/100.0) ** 2

Python では、関数定義は、上のような形をしています。 最初の行は以下のように def で始まります。

def 関数名(引数, ...):

引数(ひきすう)とは、関数が受け取る値を指し示す変数のことです。仮引数(かりひきすう)ともいいます。

: 以降は関数定義の本体であり、関数の処理を記述する部分として以下の構文が続きます。

return 式

この構文は return で始まり、return文と呼ばれます。return文は、return に続く式の評価結果を、関数の呼び出し元に返して(これを返値と言います)、関数を終了するという意味を持ちます。この関数を、入力となる引数とともに呼び出すと、return の後の式の評価結果を返値として返します。

ここで、Pythonでは、 return の前に空白が入ることに注意してください。 このような行頭の空白をインデントと呼びます。 Pythonでは、インデントの量によって、 構文の入れ子を制御するようになっています。このことについては、 より複雑な構文が出てきたときに説明しましょう。

上記では、def の後に続く bmi が関数名です。それに続く括弧の中に書かれた heightweight は、引数です。また、return の後にBMIの計算式を記述しているので、関数の呼び出し元にはBMIの計算結果が返値として返ります。

では、定義した関数 bmi を呼び出してみましょう。

[13]:
bmi(188.0,104.0)
[13]:
29.425079221367138

第1引数を身長(cm)、第2引数を体重(kg)としたときのBMIが計算されていることがわかります。

関数呼び出しは演算式の一種なので、引数の位置には任意の式を記述できますし、 関数呼び出し自体も式の中に記述できます。

[14]:
1.1*bmi(174.0, 119.0 * 0.454)
[14]:
19.628947020742505

もう1つ関数を定義してみましょう。

[15]:
def felt_air_temperature(temperature, humidity):
    return temperature - 1 / 2.3 * (temperature - 10) * (0.8 - humidity / 100)

この関数は、温度と湿度を入力として、体感温度を返します。 このように、関数名や変数名には _ (アンダースコア)を含めることができます。 アンダースコアで始めることもできます。

数字も関数名や変数名に含めることができますが、 名前の最初に来てはいけません。

[16]:
felt_air_temperature(28, 50)
[16]:
25.652173913043477

なお、return の後に式を書かないと、何も返されなかったことを表現するために、「何もない」ことを表す None という特別な値が返ります。 (None という値は色々なところで現れることでしょう。)

return文に到達せずに関数定義本体の最後まで行ってしまったときも、None という値が返ります。

予約語

Pythonでの defreturn は、関数定義やreturn文の始まりを記述するための特別な記号であり、それ以外の用途に用いることができません。 このように構文上で役割が予約されている語は、予約語と呼ばれます。 Codeセルの構文ハイライトで(太字緑色などで)強調されるものが予約語だと覚えておけば大体問題ありません。

練習 ft_to_cm

f フィート i インチをセンチメートルに変換する関数 ft_to_cm(f,i) を定義してください。 ただし、1 フィート = 12 インチ = 30.48 cm としてよい。

[17]:
def ft_to_cm(f, i):
    ...

定義ができたら、次のセルを実行して、エラーがでないことを確認してください。

[18]:
assert round(ft_to_cm(5, 2) - 157.48, 6) == 0
assert round(ft_to_cm(6, 5) - 195.58, 6) == 0
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[18], line 1
----> 1 assert round(ft_to_cm(5, 2) - 157.48, 6) == 0
      2 assert round(ft_to_cm(6, 5) - 195.58, 6) == 0

TypeError: unsupported operand type(s) for -: 'NoneType' and 'float'

練習 quadratic

二次関数 \(f(x) = ax^2+bx+c\) の値を求める quadratic(a,b,c,x) を定義してください。

[19]:
def quadratic(a, b, c, x):
    ...

定義ができたら、次のセルを実行して、エラーがでないことを確認してください。

[20]:
assert quadratic(1, 2, 1, 3) == 16
assert quadratic(1, -5, -2, 7) == 12
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[20], line 1
----> 1 assert quadratic(1, 2, 1, 3) == 16
      2 assert quadratic(1, -5, -2, 7) == 12

AssertionError:

ローカル変数

次の関数は、ヘロンの公式によって、 与えられた三辺の長さに対して三角形の面積を返すものです。

[21]:
import math

def heron(a,b,c):
    s = 0.5*(a+b+c)
    return math.sqrt(s * (s-a) * (s-b) * (s-c))

math.sqrt を使うために import math を行っています。

次の式を評価してみましょう。

[22]:
heron(3,4,5)
[22]:
6.0

この関数の中では、まず、3辺の長さを足して 2 で割った(0.5 を掛けた)値を求めています。 そして、その値を s という変数に代入しています。 この s という変数は、この関数の中で代入されているので、この関数の中だけで利用可能な変数となります。 そのような変数をローカル変数と呼びます。

そして、s を使った式が計算されてreturn文で返されます。 ここで、関数定義のひとまとまりの本体であることを表すために、s への代入文もreturn文も、同じ深さでインデントされていることに注意してください。

Pythonでは、関数の中で定義された変数は、その関数のローカル変数となります。関数の引数もローカル変数です。関数の外で同じ名前の変数を使っても、それは関数のローカル変数とは「別もの」と考えられます。

heron を呼び出した後で、関数の外で s の値を参照しても、以下のように、s が未定義という扱いになります。

[23]:
s
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[23], line 1
----> 1 s

NameError: name 's' is not defined

以下では、heron の中では、s というローカル変数の値は 3 になりますが、関数の外では、s という変数は別もので、その値はずっと 100 です。

[24]:
s = 100
heron(3,4,5)
[24]:
6.0
[25]:
s
[25]:
100

print

上の例で、ローカル変数は関数の返値を計算するのに使われますが、それが定義されている関数の外からは参照することができません。

ローカル変数の値など、関数の実行途中の状況を確認するには、 print というPythonが最初から用意してくれている関数(組み込み関数)を用いることができます。この print を関数内から呼び出すことでローカル変数の値を確認できます。

print は任意個の引数を取ることができ、コンマ , の区切りには空白文字が出力されます。引数を与えずに呼び出した場合には、改行のみを出力します。

[26]:
def heron(a,b,c):
    s = 0.5*(a+b+c)
    print('The value of s is', s)
    return math.sqrt(s * (s-a) * (s-b) * (s-c))
[27]:
heron(1,1,1)
The value of s is 1.5
[27]:
0.4330127018922193

このように print 関数を用いて変数の値を観察することは、プログラムの誤り(バグ)を見つけ、修正(デバッグ)する最も基本的な方法です。これは1-4でも改めて説明します。

なお、以降の説明では、 print 関数を呼び出して値を出力することを「印字する」と表現します。

コメントと空行

コメントについては既に説明しましたが、 関数定義にはコメントを付加して、後から読んでもわかるようにしましょう。

コメントだけの行は空行(空白のみから成る行)と同じに扱われます。

関数定義の中に空行を自由に入れることができますので、 長い関数定義には、区切りとなるところに空行を入れるのがよいでしょう。

[28]:
# heronの公式により三角形の面積を返す
def heron(a,b,c): # a,b,c は三辺の長さ

    # 辺の合計の半分をsに置く
    s = 0.5*(a+b+c)
    print('The value of s is', s)

    return math.sqrt(s * (s-a) * (s-b) * (s-c))

関数の参照の書き方

関数は、

  関数 heron は、三角形の三辺の長さをもらって三角形の面積を返します。

というように、名前だけで参照することもありますが、

  heron(a,b,c) は、三角形の三辺の長さ a, b, c をもらって三角形の面積を返します。

というように、引数を明示して参照することもあります。

ときには、

  heron() は三角形の面積を返します。

のように、関数名に () を付けて参照することがあります。 この記法は、heron が関数であることを明示しています。

関数には引数がゼロ個のものがあるのですが、heron() と参照するとき、 heron は必ずしも引数の数がゼロ個ではないことに注意してください。

後に学習するメソッドという関数の親戚に対しても同様の記法が用いられます。

練習 qe_disc qe_solution1 qe_solution1

二次方程式 \(ax^2 + bx + c = 0\) に関して以下のような関数を定義してください。

  1. 判別式 \(b^2 - 4ac\) を求める qe_disc(a,b,c)

  2. 解のうち、大きくない方を求める qe_solution1(a,b,c)

  3. 解のうち、小さくない方を求める qe_solution2(a,b,c)

ただし、qe_solution1qe_solution2qe_disc を使って定義してください。 二次方程式が実数解を持つと仮定してよいです。

[29]:
import math

def qe_disc(a, b, c):
    ...

def qe_solution1(a, b, c):
    ...

def qe_solution2(a, b, c):
    ...

定義ができたら、次のセルを実行して、エラーがでないことを確認してください。

[30]:
assert qe_disc(1, -2, 1) == 0
assert qe_disc(1, -5, 6) == 1
assert round(qe_solution1(1, -2, 1) - 1, 6) == 0
assert round(qe_solution2(1, -2, 1) - 1, 6) == 0
assert round(qe_solution1(1, -5, 6) - 2, 6) == 0
assert round(qe_solution2(1, -5, 6) - 3, 6) == 0
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[30], line 1
----> 1 assert qe_disc(1, -2, 1) == 0
      2 assert qe_disc(1, -5, 6) == 1
      3 assert round(qe_solution1(1, -2, 1) - 1, 6) == 0

AssertionError:

▲グローバル変数

Pythonでは、関数の中で代入が行われない変数は、グローバル変数とみなされます。

グローバル変数とは、関数の外(トップレベルもしくはモジュールレベルと呼ばれます)で定義される変数のことです。

グローバル変数は、関数の中から参照することができます。

[31]:
g = 9.8
[32]:
def force(m):
    return m*g

以上のように force を定義すると、 force の中で g というグローバル変数を参照することができます。

[33]:
force(104)
[33]:
1019.2
[34]:
g = g/6

以上のように、g の値を変更してから force を実行すると、 変更後の値が用いられます。

[35]:
force(104)
[35]:
169.86666666666667

以下はより簡単な例です。

[36]:
a = 10
def foo():
    return a
def bar():
    a = 3
    return a
[37]:
foo()
[37]:
10
[38]:
bar()
[38]:
3
[39]:
a
[39]:
10
[40]:
a = 20
[41]:
foo()
[41]:
20

bar の中では a への代入があるので、a はローカル変数になります。 ローカル変数の a とグローバル変数の a は別ものと考えてください。 ローカル変数 a への代入があっても、グローバル変数の a の値は変化しません。 foo の中の a はグローバル変数です。

[42]:
def boo(a):
    return a
[43]:
boo(5)
[43]:
5
[44]:
a
[44]:
20

関数の引数もローカル変数の一種と考えられ、グローバル変数とは別ものです。

練習の解答

[45]:
def ft_to_cm(f, i):
    return 30.48*f + (30.48/12)*i
[46]:
def quadratic(a, b, c, x):
    return a*x*x + b*x + c
[47]:
import math

def qe_disc(a, b, c):
    return b*b - 4*a*c

def qe_solution1(a, b, c):
    return (-b - math.sqrt(qe_disc(a, b, c))) / (2*a)

def qe_solution2(a, b, c):
    return (-b + math.sqrt(qe_disc(a, b, c))) / (2*a)
================================================ FILE: docs/1/1-3.html ================================================ 1-3. 論理・比較演算と条件分岐の基礎 — Pythonプログラミング入門 documentation

1-3. 論理・比較演算と条件分岐の基礎

論理・比較演算と条件分岐の基礎について説明します。

参考

if文による条件分岐

制御構造については第2回と第3回で本格的に扱いますが、 ここでは if による条件分岐if文)の基本的な形だけ紹介します。

[1]:
def bmax(a,b):
    if a > b:
        return a
    else:
        return b

上の関数 bmax は、2つの引数の大きい方 (正確には小さくない方)を返します。

ここで if による条件分岐が用いられています。

if a > b:
    return a
else:
    return b

ab より大きければ a が返され、そうでなければ、b が返されます。

ここで、return a が、if より右にインデントされていることに注意してください。 return a は、a > b が成り立つときのみ実行されます。

elseif の右の条件が成り立たない場合を示しています。 else: として、必ず : が付くことに注意してください。

また、return b も、else より右にインデントされていることに注意してください。 ifelse は同じインデントになります。

[2]:
bmax(3,5)
[2]:
5

関数の中で return と式が実行されますと、関数は即座に返りますので、 関数定義の中のその後の部分は実行されません。

たとえば、上の条件分岐は以下のように書くこともできます。

if a > b:
    return a
return b

ここでは、if から始まる条件分岐には else: の部分がありません。 条件分岐の後に return b が続いています。 (ifreturn b のインデントは同じです。)

a > b が成り立っていれば、return a が実行されて a の値が返ります。 したがって、その次の return b は実行されません。

a > b が成り立っていなければ、return a は実行されません。 これで条件分岐は終わりますので、その次にある return b が実行されます。

なお、Pythonでは、max という関数があらかじめ定義されています。(すなわち、max は組み込み関数です。)

[3]:
max(3,5)
[3]:
5

様々な条件

if の右などに来る条件として様々なものを書くことができます。これらの条件には >< などの比較演算子が含まれています。

x < y         # x は y より小さい
x <= y        # x は y 以下
x > y         # x は y より大きい
x >= y        # x は y 以上
x == y        # x と y は等しい
x != y        # x と y は等しくない

特に等しいかどうかの比較には == という演算子が使われることに注意してください。 = は代入の演算子です。

<= は小さいか等しいか、>= は大きいか等しいかを表します。 != は等しくないことを表します。

さらに、このような基本的な条件を、 andor を用いて組み合わせることができます。

i >= 0 and j > 0   # i は 0 以上で、かつ、j は 0 より大きい
i < 0 or j > 0     # i は 0 より小さいか、または、j は 0 より大きい

i が 1 または 2 または 3 である、という条件は以下のようになります。

i == 1 or i == 2 or i == 3

これを i == 1 or 2 or 3 と書くことはできませんので、注意してください。

また、not によって条件の否定をとることもできます。

not x < y          # x は y より小さくない(x は y 以上)

比較演算子は、以下のように連続して用いることもできます。

[4]:
1 < 2 < 3
[4]:
True
[5]:
3 >= 2 < 5
[5]:
True

練習 absolute

数値 x の絶対値を求める関数 absolute(x) を定義してください。 Pythonには abs という絶対値を求める組み込み関数が用意されていますが、それを使わずに定義してください。

[6]:
def absolute(x):
    ...

定義ができたら、次のセルを実行して、エラーがでないことを確認してください。

[7]:
assert absolute(5) == 5
assert absolute(-5) == 5
assert absolute(0) == 0
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[7], line 1
----> 1 assert absolute(5) == 5
      2 assert absolute(-5) == 5
      3 assert absolute(0) == 0

AssertionError:

練習 sign

x が正ならば 1、負ならば -1、ゼロならば 0 を返す関数 sign(x) を定義してください。

[8]:
def sign(x):
    ...

定義ができたら、次のセルを実行して、エラーがでないことを確認してください。

[9]:
assert sign(5) == 1
assert sign(-5) == -1
assert sign(0) == 0
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[9], line 1
----> 1 assert sign(5) == 1
      2 assert sign(-5) == -1
      3 assert sign(0) == 0

AssertionError:

真理値を返す関数

ここで、真理値を返す関数について説明します。

Pythonが扱うデータには様々な種類があります。 数については既に見て来ました。

真理値とは、 True または False のどちらかの値のことです。 これらは変数ではなく、組み込み定数であることに注意してください。

  • True は、正しいこと()を表します。

  • False は、間違ったこと()を表します。

実は、if の後の条件の式は、TrueFalse を値として持ちます。

[10]:
x = 3
[11]:
x > 1
[11]:
True

上のように、x に 3 を代入しておくと、 x > 1 という条件は成り立ちます。 したがって、x > 1 という式の値は True になるのです。

[12]:
x < 1
[12]:
False
[13]:
x%2 == 0
[13]:
False

そして、真理値を返す関数を定義することができます。

[14]:
def is_even(x):
    return x%2 == 0

この関数は、x を 2 で割った余りが 0 に等しいかどうかという 条件の結果である真理値を返します。

x == y は、xy が等しいかどうかという条件です。 この関数は、この条件の結果である真理値を return によって返しています。

[15]:
is_even(2)
[15]:
True
[16]:
is_even(3)
[16]:
False

このような関数は、if の後に使うことができます。

[17]:
def is_odd(x):
    if is_even(x):
        return False
    else:
        return True

このように、直接に TrueFalse を返すこともできます。

[18]:
is_odd(2)
[18]:
False
[19]:
is_odd(3)
[19]:
True

オブジェクト

Pythonにおける値(式の評価結果)は全てオブジェクトと総称されます。 変数の値もオブジェクトです。

したがって、数や真理値もオブジェクトです。 今後、文字列やリストなど、様々な種類のデータが登場しますが、 それらは全てオブジェクトです。

今後、オブジェクトという用語がところどころで出て来ますが、 オブジェクトとデータは同義と思って差し支えありません。 正確には、式の評価結果や変数の値となるデータがオブジェクトです。

None

None というデータがあります。

セルの中の式を評価した結果が None になると、 何も表示されません。

[20]:
None

print で無理やり表示させると以下のようになります。

[21]:
print(None)
None

None という値は、特段の値が何もない、 ということを表すために使われることがあります。

条件としては、None は偽と同様に扱われます。

[22]:
if None:
    print('OK')
else:
    print('NG')
NG

return の後に式を書かないことがあります。

return

この場合、以下のように None が指定されているとみなされます。

return None

このようなreturn文を実行すると、関数の実行はそこで終了して None が返ります。

▲条件として使われる他の値

TrueFalse の他に、他の種類のデータも、条件としても用いることができます。

たとえば:

  • 数のうち、0 や 0.0 は偽、その他は真とみなされます。

  • 文字列では、空文字列 '' のみ偽、その他は真とみなされます。(文字列については2-1を参照。)

  • 組み込み定数 None は偽とみなされます。(None については上記参照。)

[23]:
if 0:
    print('OK')
else:
    print('NG')
NG
[24]:
if -1.1:
    print('OK')
else:
    print('NG')
OK

▲再帰

一般に、定義しようとするもの自身を定義の中で参照することを、 再帰と言います。 再帰による定義を再帰的定義と言います。

たとえば、数列の漸化式は再帰的定義と考えられます。 実際に、n 番目のフィボナッチ数を fib(n) とおくと、 fib(n) は次のような漸化式を満たします。

fib(n) = n  ただし n<2
fib(n) = fib(n-1) + fib(n-2)  ただし n>=2

この漸化式を用いて以下のように実際にフィボナッチ数を計算することができます。

fib(0) = 0
fib(1) = 1
fib(2) = fib(1) + fib(0) = 1 + 0 = 1
fib(3) = fib(2) + fib(1) = 1 + 1 = 2
fib(4) = fib(3) + fib(2) = 2 + 1 = 3
fib(5) = fib(4) + fib(3) = 3 + 2 = 5
...

この漸化式から、以下のように fib(n) の再帰的定義が得られます。

[25]:
def fib(n):
    if n < 2:
        return n
    else:
        return fib(n-1) + fib(n-2)

実際に、以下のように fib(n) の値が求まります。

[26]:
fib(10)
[26]:
55

練習の解答

[27]:
def absolute(x):
    if x < 0:
        return -x
    else:
        return x
[28]:
def sign(x):
    if x < 0:
        return -1
    if x > 0:
        return 1
    return 0
================================================ FILE: docs/1/1-4.html ================================================ 1-4. テストとデバッグ — Pythonプログラミング入門 documentation

1-4. テストとデバッグ

テストとデバッグについて説明します。

参考

仕様・テスト・デバッグ

プログラムを書くときに、実現しようとしている事柄を仕様と呼びます。

対象のプログラムが仕様に適合しているかを、実際にプログラムを動作させて検査することを、テストと呼びます。 テストの際に、テスト対象に与える入出力ペアのことを、テストケースと呼びます。

書いたプログラムが仕様に適合しているかは、一般に自明ではありません。 テストによって、仕様に反したプログラムの振舞いが、しばしば浮き彫りになります。 仕様に反したプログラムの振舞いの原因を、バグと呼び、それを取り除くことをデバッグと呼びます。

プログラミングでは、典型的には

  • 仕様を分析する

  • プログラムを書く

  • テストする

  • デバッグする

という4つの行いを、必要に応じて繰り返すことになります。

assert文

テストとデバッグに有用なのが、assert文です。 これは、assert の次に書かれた条件式が真であるべきだと仕様を宣言する文です。 偽であった場合は、AssertionError が発生してプログラムがそこで停止します。

与えられた引数を二乗する関数 square を用いた具体例を示します。

[1]:
def square(x):
    return x*x

x = -2
assert square(x) >= 0

このassert文では、仕様として条件式 square(x) >= 0 を宣言しています。 square 関数が「二乗する」という仕様に沿っているなら、その条件式は真であるべきです。 そして、実際 square はその仕様に適合しているので、ここではassert文が実行されても何も起きません。

しかし、square にバグがあった場合は、話が変わります。

[2]:
def square(x):
    return x+x # バグがある

x = -2
assert square(x) >= 0
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[2], line 5
      2     return x+x # バグがある
      4 x = -2
----> 5 assert square(x) >= 0

AssertionError:

上のセルを実行すると、 AssertionError が生じます。

このように、assert文は、それが存在する場所で、満たされていなければならない前提条件を記述するために用います。 assert文で停止したら、記述された前提条件に関わる部分にバグがあることが判明します。

テストケースは、テスト対象が満たすべき仕様という側面があるので、assert文はテストにも用いられます。

[3]:
def square(x):
    return x*x

assert square(2) == 4
assert square(-2) == 4
assert square(0) == 0

上の例では、squareに対する3つのテストケースについて、assert文でテストしています。テストケースが満たされた(つまりassert文で停止しなかった)からと言って、テスト対象の square が正しいとは言えませんが、仕様への適合度が高いことから、尤もらしいとは言えます。

エラーの分類

不正なプログラムからは、様々なエラーが生じます。

エラーには大きく分けて、構文エラー・実行時エラー・論理エラーの3つがあります。 以下では、それぞれの意味と、典型例を示します。

構文エラー

構文エラー(syntax error)とは、プログラムコードが、Pythonの構文に違反しているときに生じるエラーです。

Pythonにおける構文エラーの典型例として、

  • クォートや括弧の閉じ忘れ

  • コロンのつけ忘れ

  • インデントの崩れ

  • 全角スペースの利用

  • == の代わりに = を使う

  • 変数の代わりに文字列を使う(Cf. 2-1 文字列

などが挙げられます。

[4]:
print('This is the error) # クォートの閉じ忘れ
  Cell In[4], line 1
    print('This is the error) # クォートの閉じ忘れ
          ^
SyntaxError: unterminated string literal (detected at line 1)

[5]:
def f()  # コロンの付け忘れ
   return 1
  Cell In[5], line 1
    def f()  # コロンの付け忘れ
             ^
SyntaxError: expected ':'

[6]:
def f():
return 1 # インデントの崩れ
  Cell In[6], line 2
    return 1 # インデントの崩れ
    ^
IndentationError: expected an indented block after function definition on line 1

[7]:
1 + 1 # 全角スペースの利用
  Cell In[7], line 1
    1 + 1 # 全角スペースの利用
       ^
SyntaxError: invalid non-printable character U+3000

上の例を実行するとわかるように、構文エラーがあると SyntaxErrorIndentationError などが発生します。 それに付随するエラーメッセージが、構文エラーの具体的内容とおおよその位置を説明してくれます。

構文エラーに直面した際は、エラーメッセージをよく読んで、原因を推察しましょう。 上の例が示すように、エラーメッセージの説明は、必ずしも分かり易くないですが、原因の位置を絞りこむには有用です。

Pythonでは、構文エラーが実行時に発生しているように見えますが、実際には、実行しようとするプログラムコードの解釈に失敗することでエラーが生じています。 つまり、構文エラーは、プログラムの実行によって生じるエラーではなく、実行できなかったことで生じるエラーです。

実行時エラー

実行時エラー(runtime error)とは、プログラムを実行した際に生じるエラー全般を指します。 簡単に言えば、プログラムを異常停止させるエラーです。

実行時エラーが生じる典型的な状況として、

  • 存在しない名前の利用(変数名・関数名・メソッド名の誤植)

  • グローバル変数のつもりでローカル変数を参照(Cf. 3-3 関数

  • ゼロによる除算

  • 辞書に登録されていないキーに対する値を取得(Cf. 3-1 辞書

  • 存在しないファイルの読み込み(Cf. 4-1 ファイル入出力

  • assert文における条件の不成立

などが挙げられます。

[8]:
undefined_variable # 未定義の変数の参照
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[8], line 1
----> 1 undefined_variable # 未定義の変数の参照

NameError: name 'undefined_variable' is not defined
[9]:
x = 1
def f():
    x = x # グローバル変数のつもりでローカル変数を参照
f()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Cell In[9], line 4
      2 def f():
      3     x = x # グローバル変数のつもりでローカル変数を参照
----> 4 f()

Cell In[9], line 3, in f()
      2 def f():
----> 3     x = x

UnboundLocalError: cannot access local variable 'x' where it is not associated with a value
[10]:
1/0 # ゼロによる除算
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
Cell In[10], line 1
----> 1 1/0 # ゼロによる除算

ZeroDivisionError: division by zero
[11]:
{'a': 1}['b'] # 登録されていないキーに対する値を参照
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[11], line 1
----> 1 {'a': 1}['b'] # 登録されていないキーに対する値を参照

KeyError: 'b'
[12]:
open('non-existent.txt', 'r') # 存在しないファイルの読み込み
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[12], line 1
----> 1 open('non-existent.txt', 'r') # 存在しないファイルの読み込み

File ~/Projects/utpython/lib/python3.12/site-packages/IPython/core/interactiveshell.py:324, in _modified_open(file, *args, **kwargs)
    317 if file in {0, 1, 2}:
    318     raise ValueError(
    319         f"IPython won't let you open fd={file} by default "
    320         "as it is likely to crash IPython. If you know what you are doing, "
    321         "you can use builtins' open."
    322     )
--> 324 return io_open(file, *args, **kwargs)

FileNotFoundError: [Errno 2] No such file or directory: 'non-existent.txt'

実行時エラーについては、送出される例外名(上の例では NameErrorUnboundLocalErrorZeroDivisionErrorKeyErrorFileNotFoundError)が自己説明的であり、それに付随するエラーメッセージも、大抵原因を分かり易く説明してくれます。

実行時エラーに直面した際は、発生した例外名とエラーメッセージをよく読んで、エラーに関連する言語機能(たとえば辞書やファイル)の仕組みを改めて確認しましょう。

論理エラー

論理エラー(logic error)とは、プログラムを実行できるが、意図したように動作しないことを意味します。 これは、プログラムから発生するエラーではなく、プログラムを書いた人のエラーです。

バグと呼ばれるものの多くは、論理エラーです。 したがって、デバッグでは、プログラムを書いた人の意図と、プログラムの振舞いを比較検証することになります。

assert文は、仕様違反という論理エラーを、 AssertionError という実行時エラーに変換していると見做すことができます。

デバッグの具体例

デバッグの具体的なシナリオを説明します。 次の関数 median(x, y, z) は、xyz の中央値(真ん中の値)を求めようとするものです。 ただし、 xyz は相異なる数であると仮定します。

[13]:
def median(x, y, z):
    if x > y:
        x = y
        y = x
    if z < x:
        return x
    if z < y:
        return z
    return y

assert median(3, 1, 2) == 2
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[13], line 11
      8         return z
      9     return y
---> 11 assert median(3, 1, 2) == 2

AssertionError:

このように、この median は間違っています。

さて、median は、ローカル変数の xyz のいずれかを返す関数です。 これらの変数の値が期待通りの値であるか、 print を入れて印字し、観察してみましょう。

[14]:
def median(x, y, z):
    print(x, y, z)
    if x > y:
        x = y
        y = x
    print(x, y, z)
    if z < x:
        return x
    if z < y:
        return z
    return y

assert median(3, 1, 2) == 2
3 1 2
1 1 2
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[14], line 13
     10         return z
     11     return y
---> 13 assert median(3, 1, 2) == 2

AssertionError:

関数の入口にある最初の print では、期待通りに実引数となる 312 が、xyz に代入されています。 しかし、2番目の print では、 3 が消えて 1 が複製されています。 このことから、この2つの print の間にあるif文が疑わしいことが分かります。

問題のif文は、xy の値を入れ替える意図があるものでした。 その意図を正しく反映すると、次のようになります。

[15]:
def median(x, y, z):
    print(x, y, z)
    if x > y:
        w = x
        x = y
        y = w
    print(x, y, z)
    if z < x:
        return x
    if z < y:
        return z
    return y

assert median(3, 1, 2) == 2
3 1 2
1 3 2

期待通りに動きました。 最後に、デバッグ用に導入した print は、median の仕様には含まれないので、きちんと消しましょう。

[16]:
def median(x, y, z):
    if x > y:
        w = x
        x = y
        y = w
    if z < x:
        return x
    if z < y:
        return z
    return y

assert median(3, 1, 2) == 2

コーディングスタイル

実は、生じたバグを取る対処法よりも、そもそもバグが生じにくくする予防法の方が大切です。 Pythonにおいて特に重要視されているのが、コーディングスタイル、つまりコードの書き方です。 読みにくい(可読性の低い)コードだと、些細なミスが生じやすく、また見つけにくいからです。

PythonではPEP8非公式日本語訳)と呼ばれる公式のスタイルガイドがあります。 PEP8には様々な側面でスタイルに関する規則があり、コードの可読性を高めることが強く推奨されています。 ここまでに扱った言語の要素について、たとえば、

  • インデントは半角スペースを4つで1レベル

  • = += == などの演算子の前後に半角スペースを1つ入れる

  • *+ の複合式では + の前後に半角スペースを1つ入れる(例:2*x + y

  • 関数の開き括弧の前にスペースを入れない

  • l I O を変数名として使わない

  • 真理値の比較に ==is を使わない

などが代表的です。

PEP8に基づいたコーディングスタイルの自動検査器もあります(参照:pycodestyle)。 オンラインサービスもいくつか利用できるので(例:PEP8 online)、適宜活用してみましょう。

PEP8には陽に言及されていないものの、プログラミング一般に重要なこともあります。 たとえば、

  • 自己説明的でない“マジックナンバー”ではなく記号的に意味がわかる変数を使う

  • 不要なコードは削除する

  • 1つの関数では1つのタスクだけを処理する

などは、可読性を上げる代表的なポイントです。

勘違いはバグを引き起こします。自らが勘違いしないコードを書くことが肝要です。

[ ]:

================================================ FILE: docs/2/2-1.html ================================================ 2-1. 文字列 (string) — Pythonプログラミング入門 documentation

2-1. 文字列 (string)

文書処理などに必要な文字列について説明します。

参考

Pythonが扱うデータには様々な種類がありますが、文字列はいくつかの文字の並びから構成されるデータです。 Pythonは標準で多言語に対応しており、 英語アルファベットだけではなく日本語をはじめとする多くの言語を取り扱えます。

文字列は、文字の並びをシングルクォート '...'、もしくはダブルクォート "..." で囲んで記述します。

以下の例では文字列をそれぞれ、変数 word1, word2 に代入しています。

[1]:
word1 = 'hello'
word1
[1]:
'hello'
[2]:
word2 = 'Hello'
word2
[2]:
'Hello'

上の変数の値が確かに文字列であることは、組み込み関数 type によって確認できます。 type は、任意のデータを引数として、そのデータの種類を返します。 データの種類は、データ型もしくはと呼ばれます。

[3]:
type(word1)
[3]:
str

str は文字列のデータ型を意味します。

[4]:
type(word2)
[4]:
str

str は組み込み関数としても用いられます。 組み込み関数 str を使えば、任意のデータを文字列に変換できます。 一般に、データ型は、そのデータ型への変換を行う関数として用いられることが多いです。

1-1で学んだ数値を文字列に変換したい場合、次のように行います。

[5]:
word3 = str(123)
word3
[5]:
'123'

逆に、'123' という文字列を整数に変換するには、1-1で述べた int という関数を用いることができます。 (実は int は整数の型でもあります。)

[6]:
i = int('123')
i
[6]:
123

関数 float を用いれば文字列を実数に変換できます。

[7]:
f = float('123.4')
f
[7]:
123.4

文字列の長さは、組み込み関数 len を用いて次のようにして求めます。

[8]:
len(word1)
[8]:
5

複数行にわたる文字列を記述するには、トリプルクォート('''...''' もしくは """...""")を用いることができます。 上記の参考URLを参照してください。 トリプルクォートはコメントとしても用いられます。 なお、1-4 のコーディングスタイルのところで紹介したスタイルガイドのPEP8では、 トリプルクォートには """...""" を使うのが適切と定められています。

文字列とインデックス

文字列はいくつかの文字によって構成されています。

文字列 'hello' の3番目の文字を得たい場合は、以下のような記法を用います。

[9]:
'hello'[2]
[9]:
'l'

文字列を値とする変数に対しても同様の記法を用います。多くの場合は変数に対してこの記法を用います。

[10]:
word1 = 'hello'
word1[2]
[10]:
'l'

この括弧内の数値のことをインデックスと呼びます。インデックスは 0 から始まるので、 ある文字列の x 番目の要素を得るには、インデックスとして x-1 を指定する必要があります。

こうして取得した文字は、Pythonでは長さが 1 の文字列として扱われます。 (プログラミング言語によっては、文字列ではなく別の型のデータとして扱われるものもありますので注意してください。)

文字列に対して、インデックスを指定してその要素を変更することはできません。(次のセルはエラーとなります) Pythonのデータは、大きく、変更可能なものと変更不可能なものに分類できますが、 文字列は変更不可能なデータです。 したがって、文字列を加工する場合は、新たに別の文字列を作成します。

[11]:
word1 = 'hello'
word1[0] = 'H'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[11], line 2
      1 word1 = 'hello'
----> 2 word1[0] = 'H'

TypeError: 'str' object does not support item assignment

また、文字列の長さ以上のインデックスを指定することはできません。(次はエラーとなります)

[12]:
word1[100]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Cell In[12], line 1
----> 1 word1[100]

IndexError: string index out of range

インデックスに負数を指定すると、 文字列を後ろから数えた順序に従って文字列を構成する文字を得ます。 たとえば、文字列の最後の文字を取得するには、-1 を指定します。

[13]:
word1[-1]
[13]:
'o'

まとめると文字列 hello の正負のインデックスは以下の表の関係になります。

インデックス

h

e

l

l

o

0か正

0

1

2

3

4

-5

-4

-3

-2

-1

文字列とスライス

スライスと呼ばれる機能を利用して、文字列の一部(部分文字列)を取得できます。

具体的には、取得したい部分文字列の先頭の文字のインデックスと最後の文字のインデックスに 1 を加えた値を指定します。 たとえば、ある文字列の2番目の文字から4番目までの文字の部分文字列を得るには次のようにします。

[14]:
digits1='0123456789'
digits1[1:4]
[14]:
'123'

文字列の先頭(すなわち、インデックスが 0 の文字)を指定する場合、次のように行えます。

[15]:
digits1[0:3]
[15]:
'012'

しかし、最初の 0 は省略しても同じ結果となります。

[16]:
digits1[:3]
[16]:
'012'

同様に、最後尾の文字のインデックスも、値を省略することもできます。

[17]:
digits1[3:]
[17]:
'3456789'
[18]:
digits1[3:5]
[18]:
'34'

スライスにおいても負数を指定して、 文字列の最後の方から部分文字列を取得できます。

[19]:
digits1[-4:-1]
[19]:
'678'

スライスでは3番目の値を指定することで、とびとびの文字を指定できます。次のように digits1[3:9:2] と指定すると、インデックス 3 から2文字おきにインデックス 9 より小さい文字を並べた部分文字列を得ます。

[20]:
digits1[3:9:2]
[20]:
'357'

3番目の値に -1 を指定することもできます。これを使えば元の文字列の逆向きの文字列を得ることができます。

[21]:
digits1[8:4:-1]
[21]:
'8765'

空文字列

シングルクォート(もしくはダブルクォート)で、何も囲まない場合、長さ 0 の文字列(空文字列(くうもじれつ)もしくは、空列(くうれつ))となります。 具体的には、下記のように使用します。

blank = ''

空文字列は、次のように、たとえば文字列中からある部分文字列を取り除くのに使用します。 (replace は後で説明します。)

[22]:
price = '2,980円'
price.replace(',', '')
[22]:
'2980円'

文字列のスライスにおいて、指定したインデックスの範囲に文字列が存在しない場合、 たとえば、最初に指定したインデックス x に対して、 2番目のインデックスの値に x 以下のインデックスの値を指定するとどうなるでしょうか? (ただし、2つのインデックスは同じ符号を持つとし、スライスの3番目の値は用いないとします。) このような場合、結果は次のように空文字列となります(エラーが出たり、結果が None にはならないことに注意してください)。

[23]:
digits1='0123456789'
print('空文字列1 = ', digits1[4:2])
print('空文字列2 = ', digits1[-1:-4])
print('空文字列3 = ', digits1[3:3])
print('空文字列ではない = ', digits1[3:-1])
空文字列1 =
空文字列2 =
空文字列3 =
空文字列ではない =  345678

文字列の検索

文字列A文字列B を含むかどうかを調べるには、in 演算子を使います。 具体的には、次のように使用します。

文字列B in 文字列A

調べたい 文字列B が含まれていれば True が、そうでなければ False が返ります。

[24]:
'lo' in 'hello'
[24]:
True
[25]:
'z' in 'hello'
[25]:
False

実際のプログラムでは文字列を値とする変数を用いることが多いでしょう。

[26]:
word1 =  'hello'
substr1 = 'lo'
substr1 in word1
[26]:
True
[27]:
substr2 = 'z'
substr2 in word1
[27]:
False

not in 演算子は、in 演算子の逆を意味します。

[28]:
word1 =  'hello'
substr2 = 'z'
substr2 not in word1
[28]:
True

▲エスケープシーケンス

文字列を作成するにはシングル ' あるいはダブルクォート " で囲むと説明しました。 これらの文字を含む文字列を作成するには、エスケープシーケンスと呼ばれる特殊な文字列を使う必要があります。

たとえば、下のように文字列に ' を含む文字列を ' で囲むと文字列の範囲がずれてエラーとなります。

[29]:
non_escaped = 'This is 'MINE''
non_escaped
  Cell In[29], line 1
    non_escaped = 'This is 'MINE''
                            ^
SyntaxError: invalid syntax

エラーを避けるには、エスケープシーケンスで ' を記述します、具体的には ' の前に \ と記述すると、' を含む文字列を作成できます。

[30]:
escaped1 = 'This is \'MINE\''
escaped1
[30]:
"This is 'MINE'"

実は、シングルクォートで囲む代わりにダブルクォートを使えばエスケープシーケンスを使わずに記述できます。

[31]:
doublequated = "This is 'MINE'"
doublequated
[31]:
"This is 'MINE'"

他にも、ダブルクォートを表す \"\ を表す \\ 、改行を表す \n など、様々なエスケープシーケンスがあります。

[32]:
escaped2 = "時は金なり\n\"Time is money\"\nTime is \\"
print(escaped2)
時は金なり
"Time is money"
Time is \

3連のシングルクォート、もしくはダブルクォートを利用すれば、 \"\n を使わずに記述できます。

[33]:
triple_single_quated = '''時は金なり
'Time is money'
Time is \\'''
print(triple_single_quated)
時は金なり
'Time is money'
Time is \
[34]:
triple_double_quated = """時は金なり
'Time is money'
Time is \\"""
print(triple_single_quated)
時は金なり
'Time is money'
Time is \

なお、プログラムの一部を無効に(コメントアウト)したいとき、 3連のクォートで囲んで文字列にしてしまうことがあります。

バックスラッシュの表示と入力

エスケープシーケンスの先頭にある文字は、バックスラッシュ \(Unicode U+005C)です。 これはPythonに限った話ではないですが、バックスラッシュは環境(正確にはフォント)によって見え方が異なります。 Windows上のフォントでは、円記号 ¥ として見えることが多いです。 macOS上のフォントでは、そのままバックスラッシュとして見えることが多いです。

JIS配列キーボードでは、バックスラッシュキーがないことがあります。 Windows上では、円記号 ¥ キーでバックスラッシュが入力できます。 macOS上では、Alt + ¥ キーでバックスラッシュが入力できます。 ただし、IME設定によっても入力方法は変わるので注意してください。

[35]:
print('\n') # 改行文字(バックスラッシュ + n)
print('¥n') # 改行文字でない(円記号 + n)
print('⧵n') # 改行文字でない(Unicode U+29F5 のバックスラッシュ演算子 + n)


¥n
⧵n

文字列の連結

+ 演算子を用いれば文字列同士を連結できます。 この演算では新しい文字列が作られ、元の文字列は変化しません。

[36]:
word1 = 'hello'
word2 = ' world'
text1 = word1 + word2
text1
[36]:
'hello world'

* 演算子で文字列の繰り返し回数を指定できます。

[37]:
word1 = 'hello'
word1 * 3
[37]:
'hellohellohello'

文字列とメソッド

文字列に対する操作を行うため、様々なメソッド(関数のようなもの)が用意されています。

メソッドは必要に応じて (...) 内に引数を与え、以下のように使用します。

文字列.メソッド名(式, ...)
# あるいは
文字列変数.メソッド名(式, ...)

文字列には以下のようなメソッドが用意されています。

置換

replace メソッドは、指定した 部分文字列A を、別に指定した 文字列B で置き換えた文字列を作成します。 この操作では、元の文字列は変化しません。具体的には、次のように使用します。

文字列.replace(部分文字列A, 文字列B)
[38]:
word1 = 'hello'
word1.replace('l', '123')
[38]:
'he123123o'
[39]:
word1
[39]:
'hello'

練習

英語の文章からなる文字列 str_engsentences が引数として与えられたとき、str_engsentences 中に含まれる全ての句読点(., ,, :, ;, !, ?)を削除した文字列を返す関数 remove_punctuations を作成してください。 (練習の解答はこのノートブックの一番最後にあります。)

次のセルの ... のところを書き換えて remove_punctuations(str_engsentences) を作成してください。

[40]:
def remove_punctuations(str_engsentences):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[41]:
print(remove_punctuations('Quiet, uh, donations, you want me to make a donation to the coast guard youth auxiliary?') == 'Quiet uh donations you want me to make a donation to the coast guard youth auxiliary')
False

練習

ATGCの4種類の文字から成る文字列 str_atgc が引数として与えられたとき、文字列 str_pair を返す関数 atgc_bppair を作成してください。ただし、str_pair は、str_atgc 中の各文字列に対して、 AT に、TA に、GC に、CG に置き換えたものです。

次のセルの ... のところを書き換えて atgc_bppair(str_atgc) を作成してください。

[42]:
def atgc_bppair(str_atgc):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[43]:
print(atgc_bppair('AAGCCCCATGGTAA') == 'TTCGGGGTACCATT')
False

検索

index メソッドにより、指定した 部分文字列B文字列A のどこに存在するか調べることができます。具体的には、次のように使用します。

文字列A.index(部分文字列B)

ただし、指定した部分文字列が文字列に複数回含まれる場合、最初のインデックスが返されます。また、指定した部分文字列が文字列に含まれない場合は、エラーとなります。

[44]:
word1 = 'hello'
word1.index('lo')
[44]:
3
[45]:
word1.index('l')
[45]:
2

以下はエラーとなります。

[46]:
word1.index('a')
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[46], line 1
----> 1 word1.index('a')

ValueError: substring not found

find メソッドも index と同様に部分文字列を検索し、最初に出現するインデックスを返します。

index との違いは、部分文字列が含まれない場合エラーとはならず -1 が返されることです。

[47]:
word1 = 'hello'
word1.find('a')
[47]:
-1

練習

コロン (:) を1つだけ含む文字列 str1 を引数として与えると、コロンの左右に存在する文字列を入れ替えた文字列を返す関数 swap_colon(str1) を作成してください。

次のセルの ... のところを書き換えて swap_colon(str1) を作成してください。

[48]:
def swap_colon(str1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[49]:
print(swap_colon('hello:world') == 'world:hello')
False

数え上げ

count メソッドにより、指定した 部分文字列B文字列A にいくつ存在するか調べることができます。

文字列A.count(部分文字列B)
[50]:
word1 = 'hello'
word1.count('l')
[50]:
2
[51]:
'aaaaaaa'.count('aa')
[51]:
3

練習

ATGCの4種類の文字から成る文字列 str_atgc と塩基名(A, T, G, C のいずれか)を指定する文字列 str_bpname が引数として与えられたとき、str_atgc 中に含まれる塩基 str_bpname の数を返す関数 atgc_count を作成してください。

次のセルの ... のところを書き換えて atgc_count(str_atgc, str_bpname) を作成してください。

[52]:
def atgc_count(str_atgc, str_bpname):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[53]:
print(atgc_count('AAGCCCCATGGTAA', 'A') == 5)
False

大文字小文字

lower, capitalize, upper メソッドを用いると、文字列の中の英文字を小文字に変換したり、大文字に変換したりすることができます。

これらの操作では、元の文字列は変化しません。

[54]:
upper_dna = 'DNA'
upper_dna.lower() # 全ての文字を小文字にする
[54]:
'dna'
[55]:
upper_dna
[55]:
'DNA'
[56]:
lower_text = 'hello world!'
lower_text.capitalize() # 先頭文字を大文字にする
[56]:
'Hello world!'
[57]:
lower_text
[57]:
'hello world!'
[58]:
lower_text.upper() #全ての文字を大文字にする
[58]:
'HELLO WORLD!'
[59]:
lower_text
[59]:
'hello world!'

▲空白文字の削除

半角スペース ' '・改行文字 '\n'・タブ文字 '\t'・全角スペース ' ' などを総称して空白文字と呼びます。

strip メソッドを用いると、文字列の前後にある連続した空白文字を削除した文字列を取得できます。

[60]:
'  abc\n'.strip()
[60]:
'abc'
[61]:
' a b c \n'.strip()
[61]:
'a b c'

左側の空白だけ削除する lstrip と右側の空白だけ削除する rstrip もあります。

[62]:
'  abc\n'.lstrip()
[62]:
'abc\n'
[63]:
'  abc\n'.rstrip()
[63]:
'  abc'

文字列の比較演算

比較演算子、==, <, > などを用いて、2つの文字列を比較することもできます。

[64]:
print('abc' == 'abc')
print('ab' == 'abc')
True
False
[65]:
print('abc' != 'abc')
print('ab' != 'abc')
False
True

文字列の大小の比較は、いわゆる辞書式による比較で、文字列の最初の文字から順に比較して大小を決めます。 片方がもう片方を拡張したものであれば、拡張した方を大きいとします。

[66]:
print('abc' <= 'abc')
print('abc' < 'abc')
print('abc' < 'abd')
print('ab' < 'abc')
True
False
True
True

練習

英語の文字列 str_engsentences が引数として与えられたとき、それが全て小文字である場合、True を返し、そうでない場合、 False を返す関数 check_lower を作成してください。

次のセルの ... のところを書き換えて check_lower(str_engsentences) を作成してください。

[67]:
def check_lower(str_engsentences):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[68]:
print(check_lower('down down down') == True)
print(check_lower('There were doors all round the hall, but they were all locked') == False)
False
False

初心者によくある誤解 — 変数文字列の混乱

初心者によくある誤解として、変数と文字列を混乱する例が見られます。たとえば、文字列を引数に取る次のような関数 func を考えます( func は引数として与えられた文字列を大文字にして返す関数です)。

[69]:
def func(str1):
    return str1.upper()

ここで変数 str2 を引数として func を呼ぶと、str2 に格納されている文字列が大文字になって返ってきます。

[70]:
str2 = 'abc'
func(str2)
[70]:
'ABC'

次のように func を呼ぶと上とは結果が異なります。次の例では変数 str2 (に格納されている文字列 abc)ではなく、文字列 'str2' を引数として func を呼び出しています。

[71]:
str2 = 'abc'
func('str2')
[71]:
'STR2'

練習

コンマ (,) を含む英語の文章からなる文字列 str_engsentences が引数として与えられたとき、str_engsentences 中の一番最初のコンマより後の文章のみかならなる文字列 str_res を返す関数 remove_clause を作成してください。ただし、 str_res の先頭は大文字のアルファベットとしてください。

次のセルの ... のところを書き換えて remove_clause(str_engsentences) を作成してください。

[72]:
def remove_clause(str_engsentences):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[73]:
print(remove_clause("It's being seen, but you aren't observing.") == "But you aren't observing.")
False

練習の解答

[74]:
def remove_punctuations(str_engsentences):
    str1 = str_engsentences.replace('.', '') # 指定の文字を空文字に置換
    str1 = str1.replace(',', '')
    str1 = str1.replace(':', '')
    str1 = str1.replace(';', '')
    str1 = str1.replace('!', '')
    str1 = str1.replace('?', '')
    return str1
#remove_punctuations('Quiet, uh, donations, you want me to make a donation to the coast guard youth auxiliary?')
[75]:
def atgc_bppair(str_atgc):
    str_pair = str_atgc.replace('A', 't')# 指定の文字に置換。ただし全て小文字
    str_pair = str_pair.replace('T', 'a')
    str_pair = str_pair.replace('G', 'c')
    str_pair = str_pair.replace('C', 'g')
    str_pair = str_pair.upper() # 置換済みの小文字の列を大文字に変換
    return str_pair
#atgc_bppair('AAGCCCCATGGTAA')
[76]:
def swap_colon(str1):
    #コロンの位置を取得する # findでもOK
    col_index = str1.index(':')
    #コロンの位置を基準に前半と後半の部分文字列を取得する
    str2, str3 = str1[:col_index], str1[col_index+1:]
    #部分文字列の順序を入れ替えて結合する
    str4 = str3 + ':' + str2
    return str4
#swap_colon('hello:world')
[77]:
def atgc_count(str_atgc, str_bpname):
    return str_atgc.count(str_bpname)
#atgc_count('AAGCCCCATGGTAA', 'A')
[78]:
def check_lower(str_engsentences):
    if str_engsentences == str_engsentences.lower():#元の文字列と小文字に変換した文字列を比較する
        return True
    return False
#check_lower('down down down')
#check_lower('There were doors all round the hall, but they were all locked')
[79]:
def remove_clause(str_engsentences):
    int_index = str_engsentences.find(',')
    str1 = str_engsentences[int_index+2:]
    return str1.capitalize()
#remove_clause("It's being seen, but you aren't observing.")
[ ]:

================================================ FILE: docs/2/2-2.html ================================================ 2-2. リスト (list) — Pythonプログラミング入門 documentation

2-2. リスト (list)

複数のデータを要素としてまとめて取り扱うデータとして、リストとタプルについて説明します。

参考

文字列を構成する要素は文字のみでしたが、リストでは構成する要素としてあらゆる型のデータを指定できます。 他のプログラミング言語では、リストに相当するものとして配列(もしくはアレイ)やベクターなどがあります。

リストを作成するには、リストを構成する要素をコンマで区切り全体をかぎ括弧 [...] で囲みます。

以下のセルでは数値を要素とするリストを作成して、変数に代入しています。 さらに、文字列と同様に組み込み関数 type を用いて、変数の値がリストであることを確認しています。

[1]:
numbers = [0, 10, 20, 30, 40, 50]
numbers
[1]:
[0, 10, 20, 30, 40, 50]
[2]:
type(numbers)
[2]:
list

リストのデータ型は list です。 (なお、後で見るように、list は他のデータをリストに変換する関数としても用いられます。)

次に文字列を構成要素とするリストを作成してみます。

[3]:
fruits = ['apple', 'banana', 'chelly']
fruits
[3]:
['apple', 'banana', 'chelly']

リストの要素としてあらゆる型のデータを指定でき、それらは混在してもかまいません。 以下のセルでは、数値と文字列が混在しています。

[4]:
numbers_fruits = [10, 'apple', 20, 'banana', 30]
numbers_fruits
[4]:
[10, 'apple', 20, 'banana', 30]

次のように、何も要素を格納していないリスト(空リスト)を作成できます。 空リストはプログラム実行の途中結果を記録する場合などによく使われています。 具体的な例については、後述する append メソッドの項を参照してください。

[5]:
empty=[]
empty
[5]:
[]

なお、[] を用いて空リストを作成するたびに、 常に新しいオブジェクト(それまでに作られたオブジェクトとは同一でないオブジェクト)が生成されます。 詳しくは「▲オブジェクトの等価性と同一性」を参照してください。

リストとインデックス

文字列の場合と同様に、インデックスを指定してリストの要素を取り出せます。 リストの x 番目の要素を取得するには次のような記法を用います。 インデックスは 0 から始まることに注意してください。

リスト[x-1]
[6]:
abcd = ['a', 'b', 'c', 'd']
abcd[2]
[6]:
'c'

文字列の場合とは異なり、リストは変更可能なデータです。 すなわちインデックスで指定されるリストの要素は、代入によって変更できます。

[7]:
abcd = ['a', 'b', 'c', 'd']
abcd[2] = 'hello'
abcd
[7]:
['a', 'b', 'hello', 'd']

文字列と同様に、スライスを使った範囲指定も可能です。

[8]:
abcd = ['a', 'b', 'c', 'd']
abcd[1:3]
[8]:
['b', 'c']
[9]:
abcd = ['a', 'b', 'c', 'd']
abcd[0:4:2]
[9]:
['a', 'c']

リストのスライスに対しては、代入も可能です。

[10]:
abcd = ['a', 'b', 'c', 'd']
abcd[1:3] = ['x', 'y', 'z']
abcd
[10]:
['a', 'x', 'y', 'z', 'd']

練習

リスト ln を引数として取り、ln の偶数番目のインデックスの値を削除したリストを返す関数 remove_evenindex を作成してください(ただし、0 は偶数として扱うものとします)。

ヒント:スライスを使います。

以下のセルの ... のところを書き換えて remove_evenindex(ln) を作成してください。

[11]:
def remove_evenindex(ln):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[12]:
print(remove_evenindex(['a', 'b', 'c', 'd', 'e', 'f', 'g']) == ['b', 'd', 'f'] )
print(remove_evenindex([1, 2, 3, 4, 5]) == [2, 4])
False
False

多重リスト

リストの要素としてリストを指定することもできます。 リストを要素とするリストは多重リストと呼ばれます。 次は二重リストの例です。

[13]:
lns = [[1, 2, 3], [10, 20, 30], ['a', 'b', 'c']]

多重リストの要素指定は複数のインデックスで行います。 前の例で外側の [] で示されるリストの2番目の要素のリスト、 すなわち [10, 20, 30] の最初の要素は次のように指定します。

[14]:
lns[1][0]
[14]:
10

3番目のリストそのものを取り出したいときは、次のように指定します。

[15]:
lns[2]
[15]:
['a', 'b', 'c']

以下のようにリストの要素として、リストを値とする変数を指定することもできます。

[16]:
lns2 = [lns, ['x', 1, [11, 12, 13]], ['y', [100, 120, 140]] ]
lns2
[16]:
[[[1, 2, 3], [10, 20, 30], ['a', 'b', 'c']],
 ['x', 1, [11, 12, 13]],
 ['y', [100, 120, 140]]]
[17]:
lns2[0]
[17]:
[[1, 2, 3], [10, 20, 30], ['a', 'b', 'c']]

リストに対する関数・演算子・メソッド

リストの要素数

組み込み関数 len はリストの長さ、すなわち要素数、を返します。

[18]:
numbers = [0, 10, 20, 30, 40, 50]
len(numbers)
[18]:
6

maxmin

リストを引数とする関数は色々とあります。 関数 max は、数のリストが与えられると、その中の最大値を返します。 同様に関数 min はリストの中の最小値を返します。

[19]:
numbers = [30, 50, 10, 20, 40, 60]
max(numbers)
[19]:
60
[20]:
numbers = [30, 50, 10, 20, 40, 60]
min(numbers)
[20]:
10

maxmin は文字列のリストに対しても適用できます。文字列の比較は、いわゆる辞書順で行われます。

[21]:
characters = ['e', 'd', 'a', 'c', 'f', 'b']
min(characters)
[21]:
'a'

sum

関数 sum は、数のリストが与えられると、その要素の総和を返します。

[22]:
numbers = [30, 50, 10, 20, 40, 60]
sum(numbers)
[22]:
210
[23]:
sum([])
[23]:
0

リストと演算子

演算子 + によってリストの連結、* によって連結における繰り返し回数を指定することができます。

[24]:
numbers = [0, 10, 20, 30, 40, 50]
numbers + ['a', 'b', 'c']
[24]:
[0, 10, 20, 30, 40, 50, 'a', 'b', 'c']
[25]:
numbers*3
[25]:
[0, 10, 20, 30, 40, 50, 0, 10, 20, 30, 40, 50, 0, 10, 20, 30, 40, 50]

要素が全て同じ値(たとえば、0 )のリストを作る最も簡単な方法は、この * 演算子を使う方法です。

[26]:
zero10 = [0] * 10
zero10
[26]:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

*+ を繰り返し行うのと同じ結果を返します。 たとえば、x*3x+x+x と同じ結果を返します。

x が多重リストのとき、x の要素であるリストが y の中に複数回現れます。

[27]:
x = [[0, 1], [2, 3]]
y = x*3
y
[27]:
[[0, 1], [2, 3], [0, 1], [2, 3], [0, 1], [2, 3]]

このとき、x の要素が変更されると、y の中では複数箇所に変化が起こるので、注意してください。

[28]:
x[0][0] = 99
y
[28]:
[[99, 1], [2, 3], [99, 1], [2, 3], [99, 1], [2, 3]]

これは、y の中の複数個所にあるオブジェクトが同一だからです。 詳しくは、以下の「▲オブジェクトの等価性と同一性」を参照してください。

演算子 in は、左辺の要素がリストに含まれれば True を、それ以外では False を返します。

[29]:
10 in numbers
[29]:
True

リストに対する in 演算子は、論理演算 or を簡潔に記述するのに用いることもできます。 たとえば、

a1 == 1 or a1 == 3 or a1 == 7:

a1 in [1, 3, 7]:

と同じ結果を得られます。 or の数が多くなる場合は、in を用いた方がより読みやすいプログラムを書くことができます。

[30]:
a1 = 1
print(a1 == 1 or a1 == 3 or a1 == 7, a1 in [1, 3, 7])
a1 = 3
print(a1 == 1 or a1 == 3 or a1 == 7, a1 in [1, 3, 7])
a1 = 5
print(a1 == 1 or a1 == 3 or a1 == 7, a1 in [1, 3, 7])
True True
True True
False False

in 演算子は、左辺の要素がリストに含まれるかどうかを、 リストの要素を最初から順に調べることで判定しています。 したがって、リストの長さに比例した時間がかかります。 つまり、リストの長さが大きければ、それなりの時間がかかることに注意してください。

not in 演算子は、in 演算子の逆を意味します。

[31]:
10 not in numbers
[31]:
False
[32]:
11 not in numbers
[32]:
True

指定した要素のインデックス取得と数えあげ

index メソッドは引数で指定した要素のインデックスの番号を返します。 文字列には index に加えてこれと似た find メソッドもありましたが、リストでは使えません。

[33]:
numbers = [0, 10, 20, 30, 40, 50]
numbers.index(20)
[33]:
2

count メソッドは指定した要素の数を返します。

[34]:
all20 = [20]*3
all20.count(20) # 指定した要素のリスト内の数
[34]:
3

並べ替え(sort メソッド)

sort メソッドはリスト内の要素を並べ替えます。 引数に何も指定しなければ昇順でとなります。

[35]:
numbers = [30, 50, 10, 20, 40, 60]
numbers.sort()
[36]:
numbers
[36]:
[10, 20, 30, 40, 50, 60]
[37]:
characters = ['e', 'd', 'a', 'c', 'f', 'b']
characters.sort()
characters
[37]:
['a', 'b', 'c', 'd', 'e', 'f']

reverse = True オプションを指定すれば、要素を降順に並べ替えることもできます。 (これは 3.3 のキーワード引数と呼ばれるものですが、ここでは天下り的に、 並べ替えの方法を指定する情報と理解しておいてください。)

[38]:
numbers = [30, 50, 10, 20, 40, 60]
numbers.sort(reverse = True)
numbers
[38]:
[60, 50, 40, 30, 20, 10]

並べ替え(sorted 組み込み関数)

関数 sorted ではリストを引数に取って、そのリスト内の要素を昇順に並べ替えた結果をリストとして返します。

sorted(リスト)
[39]:
numbers = [30, 50, 10, 20, 40, 60]
sorted(numbers)
[39]:
[10, 20, 30, 40, 50, 60]

文字列の比較は、いわゆる辞書順で行われます。

[40]:
characters = ['e', 'd', 'a', 'c', 'f', 'b']
sorted(characters)
[40]:
['a', 'b', 'c', 'd', 'e', 'f']

sorted においても、 reverse = True と記述することで要素を降順に並べ替えることができます。

[41]:
numbers = [30, 50, 10, 20, 40, 60]
sorted(numbers, reverse=True)
[41]:
[60, 50, 40, 30, 20, 10]

ついでですが、多重リストをソートするとどのような結果が得られるか確かめてみてください。

[42]:
lns = [[20, 5], [10, 30], [40, 20], [30, 10]]
lns.sort()
lns
[42]:
[[10, 30], [20, 5], [30, 10], [40, 20]]

破壊的(インプレース)な操作と非破壊的な生成

上記では、sort メソッドと sorted 関数を紹介しましたが、両者の使い方が異なることに気が付きましたか?

具体的には、sort メソッドでは元のリストが変更されています。 一方、sorted 関数では元のリストはそのままになっています。もう一度確認してみましょう。

[43]:
numbers = [30, 50, 10, 20, 40, 60]
numbers.sort()
print('sortメソッドの実行後の元のリスト:', numbers)
numbers = [30, 50, 10, 20, 40, 60]
sorted(numbers)
print('sorted関数の実行後の元のリスト:', numbers)
sortメソッドの実行後の元のリスト: [10, 20, 30, 40, 50, 60]
sorted関数の実行後の元のリスト: [30, 50, 10, 20, 40, 60]

このように、sort メソッドは元のリストを変更してしまいます。 このような操作を破壊的あるいはインプレース (in-place) であるといいます。

一方、sorted 関数は新しいリストを生成し元のリストを破壊しません、このような操作は非破壊的であるといいます。

sorted 関数を用いた場合、その返値(並べ替えの結果)は新しい変数に代入して使うことができます。

一方、sort メソッドはリストを返さないためそのような使い方はできません。

[44]:
numbers = [30, 50, 10, 20, 40, 60]
numbers1 = sorted(numbers)
print('sorted関数の返値:', numbers1)

numbers = [30, 50, 10, 20, 40, 60]
numbers2 = numbers.sort()
print('sortメソッドの返値:', numbers2)
sorted関数の返値: [10, 20, 30, 40, 50, 60]
sortメソッドの返値: None

リストを操作するメソッドなど

ここからはリストを操作するためのメソッドなどを紹介していきます。

メソッドや組み込み関数が破壊的であるかどうかは、一般にその名称などからは判断できません。 それぞれ破壊的かどうか理解してから利用しなければなりません。

なお、次の append メソッド以外は、必要に応じて参照すればよく、 それ以降タプルの項まで飛ばして構いません。

リストに要素を追加する

append メソッドはリストの最後尾に指定した要素を付け加えます。

リスト.append(追加する要素)
[45]:
numbers = [10, 20, 30, 40, 50]
numbers.append(100)
numbers
[45]:
[10, 20, 30, 40, 50, 100]

append は、上述した空のリストと組み合わせて、あるリストから特定の条件を満たす要素のみからなる新たなリストを構成する、というような状況でしばしば用いられます。たとえば、リスト numbers1 = [10, -10, 20, 30, -20, 40, -30] から 0 より大きい要素のみを抜き出したリスト positives は次のように構成することができます。

[46]:
numbers1 = [10, -10, 20, 30, -20, 40, -30]
positives = [] # 空のリストを作成する
positives.append(numbers1[0])
positives.append(numbers1[2])
positives.append(numbers1[3])
positives.append(numbers1[5])
positives
[46]:
[10, 20, 30, 40]

▲リストにリストの要素を追加する

extend メソッドはリストの最後尾に指定したリストの要素を付け加えます。

リスト.extend(追加するリスト)
[47]:
numbers = [10, 20, 30, 40, 50]
numbers.extend([200, 300, 400, 200]) # numbers += [200, 300, 400, 200] と同じ
numbers
[47]:
[10, 20, 30, 40, 50, 200, 300, 400, 200]

▲リストに要素を挿入する

insert メソッドはリストのインデックスを指定した位置に新しい要素を挿入します。

リスト.insert(インデックス, 新しい要素)
[48]:
numbers = [10, 20, 30, 40, 50]
numbers.insert(1, 1000)
numbers
[48]:
[10, 1000, 20, 30, 40, 50]

▲リストから要素を削除する

remove メソッドは指定した要素をリストから削除します。

リスト.remove(削除したい要素)

ただし、指定した要素が複数個リストに含まれる場合、一番最初の要素が削除されます。また、指定した値がリストに含まれない場合はエラーとなります。

[49]:
numbers = [10, 20, 30, 40, 20]
numbers.remove(30) # 指定した要素を削除
numbers
[49]:
[10, 20, 40, 20]
[50]:
numbers.remove(20) # 指定した要素が複数個リストに含まれる場合、一番最初の要素を削除
numbers
[50]:
[10, 40, 20]
[51]:
numbers.remove(100) # リストに含まれない値を指定するとエラー
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[51], line 1
----> 1 numbers.remove(100) # リストに含まれない値を指定するとエラー

ValueError: list.remove(x): x not in list

▲リストからインデックスで指定した要素を削除する

pop メソッドはリストから指定したインデックスを削除し、その要素を返します。

リスト.pop(削除したい要素のインデックス)
[52]:
numbers = [10, 20, 20, 30, 20, 40]
print(numbers.pop(3))
print(numbers)
30
[10, 20, 20, 20, 40]

インデックスを指定しない場合、最後尾の要素を削除して返します。

リスト.pop()
[53]:
ln = [10, 20, 30, 20, 40]
print(ln.pop())
print(ln)
40
[10, 20, 30, 20]

▲リスト要素を削除する

del 文は指定するリストの要素を削除します。具体的には以下のように削除したい要素をインデックスで指定します。
del も破壊的であることに注意してください。
del リスト[x]
[54]:
numbers = [10, 20, 30, 40, 50]
del numbers[2]
numbers
[54]:
[10, 20, 40, 50]

スライスを使うことも可能です。

del リスト[x:y]
[55]:
numbers = [10, 20, 30, 40, 50]
del numbers[2:4]
numbers
[55]:
[10, 20, 50]

▲リストの要素を逆順にする

reverse メソッドはリスト内の要素の順序を逆順にします。

[56]:
characters = ['e', 'd', 'a', 'c', 'f', 'b']
characters.reverse()
characters
[56]:
['b', 'f', 'c', 'a', 'd', 'e']

copy

リストを複製します。 すなわち、ln の値がリストであるとき、ln.copy()ln と同じ長さのリストを新たに作って、 ln の要素を新しいリストに同じ順番で格納して、その新しいリストを返します。

複製されたリストに変更を加えたとしても、もとのリストは影響を受けません。

[57]:
numbers = [10, 20, 30, 40, 50]
numbers2 = numbers.copy()
del numbers[1:3]
numbers.reverse()
print(numbers)
print(numbers2)
[50, 40, 10]
[10, 20, 30, 40, 50]

一方、代入を用いた場合には影響を受けることに注意してください。

[58]:
numbers = [10, 20, 30, 40, 50]
numbers2 = numbers
del numbers[1:3]
numbers.reverse()
print(numbers)
print(numbers2)
[50, 40, 10]
[50, 40, 10]

リストと文字列の相互変換

文字列は変更不可能である一方、リスト変更可能です。 そのため、文字列処理をする際は、文字列のリストに一旦変換してから、変更を加えて、文字列に変換することが典型的です。 ここでは、文字列とリストの相互変換の方法を示します。

まず、文字列 slist 関数に渡すと、s を文字単位で区切ったリストが得られます。

[59]:
list('abc123')
[59]:
['a', 'b', 'c', '1', '2', '3']

文字単位ではなく、指定された文字列で区切ってリストにする際は、 split メソッドを使います。

[60]:
'banana'.split('n')
[60]:
['ba', 'a', 'a']
[61]:
'A and B and C'.split(' and ')
[61]:
['A', 'B', 'C']

split を無引数で呼び出すと、連続した空白文字を区切りと見做します。

[62]:
'A   B\nC  '.split()
[62]:
['A', 'B', 'C']

逆に、文字のリストを連結して1つの文字列にする際は、 join メソッドを次のように使います。

接合点に挿入する文字列.join(文字列のリスト)
[63]:
''.join(['a', 'b', 'c', '1', '2', '3'])
[63]:
'abc123'
[64]:
'n'.join(['ba', 'a', 'a'])
[64]:
'banana'

なお、 join の引数は、文字列のリストだけでなく、文字列のタプルでも問題ありません。 タプルについては、次で述べます。

練習

emailアドレス email とドメイン名 domain を引数に取って、email のドメイン名を domain に置き換える関数 change_domain(email, domain) を作成してください。 なお、emailアドレスのドメイン名とは、 '@' で区切られた右側の部分を意味します。

次のセルの ... のところを書き換えて change_domain(email, domain) を完成させてください。

[65]:
def change_domain(email, domain):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[66]:
print(change_domain('spam@utokyo-ipp.org', 'ipp.u-tokyo.ac.jp') == 'spam@ipp.u-tokyo.ac.jp')
False

タプル (tuple)

タプルは、リストと同じようにデータの並びであり、あらゆる種類のデータを要素にできます。 ただし、リストと違ってタプルは一度設定した要素を変更できません(文字列も同様でした)。 すなわち、タプルは変更不可能なデータです。 したがって、リストの項で説明したメソッドの多く、要素を操作するもの、は適用できないのですが、 逆にいうと、作成した後で要素を変更する必要がない場合は、 タプルの方が実装の効率がよいので、リストよりもタプルを使うべきです。

たとえば、関数が複数の値をリストにして返し、呼び出し側がすぐにリストをばらばらにして値を取り出すような場合は、 リストよりもタプルを使うべきです。 また、平面上の点を表そうとするとき、x座標とy座標を別々に変化させる必要がなければ、 (3, 5) のようなタプルを使うのが自然です。 このように、タプルを作成するには数学におけるのと同様に要素を丸括弧 (...) で囲みます。

例を見ましょう。

[67]:
x = 3
y = 5
point = (x, y)
[68]:
point
[68]:
(3, 5)
[69]:
type(point)
[69]:
tuple
[70]:
numbers3 = (1, 2, 3)
numbers3
[70]:
(1, 2, 3)

実は、丸括弧なしでもタプルを作成できます。

[71]:
numbers3 = 1,2,3
numbers3
[71]:
(1, 2, 3)

要素が1つだけの場合は、 t = (1) ではなく、次のようにします。

[72]:
onlyone = (1,)
onlyone
[72]:
(1,)

t = (1) だと、t = 1 と同じになってしまいます。

[73]:
onlyone = (1)
onlyone
[73]:
1

何も要素を格納していないタプル(空タプル)は () で作成できます。

[74]:
empty = ()
empty
[74]:
()

リストや文字列と同様に、インデックスや組み込み関数を使った操作が可能です。

[75]:
numbers3 = (1, 2, 3)
numbers3[1] # インデックスの指定による値の取得
[75]:
2
[76]:
len(numbers3) # lenはタプルを構成する要素の数
[76]:
3
[77]:
numbers3[1:3] # スライス
[77]:
(2, 3)

上述しましたが、一度作成したタプルの要素を後から変更することはできません。 したがって以下のプログラムはエラーとなります。

numbers3 = (1, 2, 3)
numbers3[1] = 5

組み込み関数 list を使って、タプルをリストに変換できます。 (list はリストのデータ型でもあります。)

[78]:
numbers3 = (1, 2, 3)
list(numbers3)
[78]:
[1, 2, 3]

組み込み関数 tuple を使って、逆にリストをタプルに変換できます。 (tuple はタプルのデータ型でもあります。)

[79]:
numbers2 = [1, 2]
tuple(numbers2)
[79]:
(1, 2)

練習

整数の要素からなるリスト ln を引数として取り、 ln に含まれる要素を逆順に格納したタプルを返す関数 reverse_totuple を作成してください。

以下のセルの ... のところを書き換えて reverse_totuple(ln) を作成してください。

[80]:
def reverse_totuple(ln):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[81]:
print(reverse_totuple([1, 2, 3, 4, 5]) == (5, 4, 3, 2, 1))
False

多重代入

多重代入では、左辺に複数の変数などを指定してタプルやリストの全ての要素を一度の操作で代入することができます。

[82]:
numbers = [0, 10, 20, 30, 40]
[a, b, c, d, e] = numbers
b
[82]:
10

以下のようにしても同じ結果を得られます。

[83]:
a, b, c, d, e = numbers
b
[83]:
10

多重代入は文字列に対しても実行可能です。

[84]:
a, b, c, d, e = 'hello'
d
[84]:
'l'

タプルに対しても実行可能です。

[85]:
numbers3 = (1, 2, 3)
(x,y,z) = numbers3
y
[85]:
2

以下のように様々な書き方が可能です。

[86]:
x,y,z = numbers3
print(y)
(x,y,z) = (1, 2, 3)
print(y)
x,y,z = (1, 2, 3)
print(y)
(x,y,z) = 1, 2, 3
print(y)
x,y,z = 1, 2, 3
print(y)
2
2
2
2
2

多重代入を使うことで、2つの変数に格納された値の入れ替えを行う手続きはしばしば用いられます。

[87]:
x = 'apple'
y = 'pen'
x, y = y, x
print(x, y) #w = x; x = y; y = w と同じ結果が得られる
pen apple

リストやタプルの比較演算

数値などを比較するのに用いた比較演算子を用いて、2つのリストやタプルを比較することもできます。

[88]:
print([1, 2, 3] == [1, 2, 3])
print([1, 2] == [1, 2, 3])
True
False
[89]:
print((1, 2, 3) == (1, 2, 3))
print((1, 2) == (1, 2, 3))
True
False
[90]:
print([1, 2, 3] != [1, 2, 3])
print([1, 2] != [1, 2, 3])
False
True
[91]:
print((1, 2, 3) != (1, 2, 3))
print((1, 2) != (1, 2, 3))
False
True

大小の比較は、いわゆる辞書式による比較で、リストやタプルの最初の要素から順に比較して大小を決めます。 片方がもう片方を拡張したものであれば、拡張した方を大きいとします。

[92]:
print([1, 2, 3] <= [1, 2, 3])
print([1, 2, 3] < [1, 2, 3])
print([1, 2, 3] < [1, 2, 4])
print([1, 2] < [1, 2, 3])
True
False
True
True
[93]:
print((1, 2, 3) <= (1, 2, 3))
print((1, 2, 3) < (1, 2, 3))
print((1, 2, 3) < (1, 2, 4))
print((1, 2) < (1, 2, 3))
True
False
True
True

for文による繰り返しとリスト・タプル

きまった操作の繰り返しはコンピュータが最も得意とする処理のひとつです。 リストのそれぞれの要素にわたって操作を繰り返したい場合はfor文を用います。

リスト ls の要素全てに対して、実行文 を繰り返すには次のように書きます。

for value in ls:
    実行文

for で始まる行の in の後に処理対象となるリスト ls が、in の前に変数 value が書かれます。

ls の最初の要素、すなわち ls[0]value に代入され 実行文 が処理されます。 実行文 の処理が終われば、ls の次の要素が value に代入され、処理が繰り返されます。 このようにして、ls の要素に対する処理が len(ls) 回繰り返されると、for文の処理が終了します。

ここでの in の働きは、先に説明したリスト要素の有無を検査する in とは異なることに、 そして、if文と同様、 実行文 の前にはスペースが必要であることに注意してください。

次に具体例を示します。 3つの要素を持つリスト ls から1つずつ要素を取り出し、変数 value に代入しています。 実行文 では value を用いて取り出した要素を参照しています。

[94]:
ls = [0,1,2]

for value in ls:
    print('For loop:', value)
For loop: 0
For loop: 1
For loop: 2

in の後に直接リストを記述することもできます。

[95]:
for value in [0,1,2]:
    print('For loop:', value)
For loop: 0
For loop: 1
For loop: 2

実行文 の前にスペースがないとエラーが出ます。

[96]:
for value in  [0,1,2]:
print('For loop:', value)
  Cell In[96], line 2
    print('For loop:', value)
    ^
IndentationError: expected an indented block after 'for' statement on line 1

エラーが出れば意図した通りにプログラムが組めていないのにすぐ気が付きますが、 エラーが出ないために意図したプログラムが組めていないことに気が付かないことがあります。 たとえば、次のような内容を実行しようとしていたとします。

[97]:
for value in  [0,1,2]:
    print('During for loop:', value)
    print('During for loop, too:', value)
During for loop: 0
During for loop, too: 0
During for loop: 1
During for loop, too: 1
During for loop: 2
During for loop, too: 2

後者の print の行のスペースの数が間違ってると、次のような結果になる場合がありますので注意してください。

[98]:
for value in [0,1,2]:
    print('During for loop:', value)
print('During for loop, too:', value) #この行のスペースの数が間違っていたがエラーは出ない
During for loop: 0
During for loop: 1
During for loop: 2
During for loop, too: 2

タプルの要素にまたがる処理もリストと同様に行えます。

[99]:
for value in (0,1,2):
    print('For loop:', value)
For loop: 0
For loop: 1
For loop: 2

以下はリストに対するfor文の典型例です。numbers は数のリストとします。

[100]:
numbers = [0,1,2,3,4,5]

以下のようにして、このリストの要素の自乗から成るリストを求めることができます。

[101]:
squares1 = []
for x in numbers:
    squares1.append(x**2)
squares1
[101]:
[0, 1, 4, 9, 16, 25]

squares1 には最初に空リストが代入されます。 そして、numbers の各要素の自乗がこのリストに次々と追加されます。

練習

整数の要素からなるリスト ln を引数として取り、ln の要素の総和を返す関数 sum_list を作成してください。

以下のセルの ... のところを書き換えて sum_list(ln) を作成してください。

[102]:
def sum_list(ln):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[103]:
print(sum_list([10, 20, 30]) == 60)
print(sum_list([-1, 2, -3, 4, -5]) == -3)
False
False

for文による繰り返しと文字列

for文を使うと文字列全体にまたがる処理も可能です。 文字列 str1 をまたがって一文字ずつの繰り返し処理を行う場合は次のように書きます。 ここで、c には取り出された一文字(の文字列)が代入されています。

for c in str1:
    実行文

str1 で与えられる文字列を一文字ずつ大文字で出力する処理は以下のようになります。

[104]:
str1 = 'Apple and pen'
for c in str1:
    print(c.upper())
A
P
P
L
E

A
N
D

P
E
N

練習

ATGCの4種類の文字から成る文字列 str_atgc が引数として与えられたとき、次のようなリスト list_count を返す関数 atgc_countlist を作成してください。ただし、 list_count の要素は、各塩基 bp に対して str_atgc 中の bp の出現回数と bp の名前を格納した(長さ2の)リストとします。

ヒント:文字列 'ATGC' に対する繰り返しを用いることができます。

以下のセルの ... のところを書き換えて atgc_countlist(str_atgc) を作成してください。

[105]:
def atgc_countlist(str_atgc):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[106]:
print(sorted(atgc_countlist('AAGCCCCATGGTAA')) == sorted([[5, 'A'], [2, 'T'], [3, 'G'], [4, 'C']]))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[106], line 1
----> 1 print(sorted(atgc_countlist('AAGCCCCATGGTAA')) == sorted([[5, 'A'], [2, 'T'], [3, 'G'], [4, 'C']]))

TypeError: 'NoneType' object is not iterable

for文によるリスト初期化の短縮記法

先に、リストの要素の自乗から成るリストを求める例を説明しました。

[107]:
numbers = [0,1,2,3,4,5]

squares1 = []
for x in numbers:
    squares1.append(x**2)
squares1
[107]:
[0, 1, 4, 9, 16, 25]

詳しくは6-1で説明されますが、内包表記を用いて書き換えると、以下のように1行で書くことができます。

[108]:
squares2 = [x**2 for x in numbers]
squares2
[108]:
[0, 1, 4, 9, 16, 25]

すなわち、

[x を含む式 for x in リストを返す式]

という式は、"リストを返す式" が返したリストの各要素を x に代入して "x を含む式" を計算し、 その結果をリストにして返します。 もちろん、変数は x でなくてもよいです。

[109]:
[y**2 for y in numbers]
[109]:
[0, 1, 4, 9, 16, 25]

▲オブジェクトの等価性と同一性

1-3で、Pythonにおける値はオブジェクトと総称されますと述べました。 ここでは、オブジェクトの等価性と同一性について説明します。

既に見てきたように、演算子 == を用いてオブジェクトの等価性を判定できます。

[110]:
a = []
b = []

このとき、ab の値はどちらも空リストなので、以下のように a の値と b の値は等価です。

[111]:
a == b
[111]:
True

しかし、[ で始まり ] で終わる式を評価すると、 必ず新しいリスト(オブジェクト)が作られて返されるので、 ab の値は同一ではありません。

オブジェクトの同一性は演算子 is を用いて判定できます。

[112]:
a is b
[112]:
False

リストの要素はオブジェクトなので、要素ごとに等価性と同一性が定まります。

例として、ab を要素とするリスト c を作ります。

[113]:
c = [a, b]
c
[113]:
[[], []]
[114]:
c[0] is c[1]
[114]:
False

a を変化させてみましょう。

[115]:
a.append(1)
a
[115]:
[1]

すると c は以下のようになります。

[116]:
c
[116]:
[[1], []]

ここで、ab は等価でなくなりました。

[117]:
a == b
[117]:
False

次に、b を要素として二重に含むリスト d を作ります。

[118]:
d = [b, b]
d
[118]:
[[], []]
[119]:
d[0] is d[1]
[119]:
True

b を変化させてみましょう。

[120]:
b.append(1)
b
[120]:
[1]

すると d は以下のようになります。

[121]:
d
[121]:
[[1], [1]]

演算子 == でリストを比較すると、要素まで見て等価性を判定します。

[122]:
print(a, b)
a == b
[1] [1]
[122]:
True

演算子 == は、要素の比較も == で行います。

[123]:
print(c, d)
c == d
[[1], [1]] [[1], [1]]
[123]:
True

一方、オブジェクトの同一性は変化しません。

[124]:
a is b
[124]:
False

== の否定形は != で、is の否定形は is not です。 not x == yx != y と書けます。not x is yx is not y と書けます。 is not はこれで1つの演算子なので注意してください。

[125]:
c != d
[125]:
False
[126]:
a is not b
[126]:
True

練習の解答

[127]:
def remove_evenindex(ln):
    ln2 = ln[1::2]
    return ln2
#remove_evenindex(['a', 'b', 'c', 'd', 'e', 'f', 'g'])
[128]:
def change_domain(email, domain):
    return '@'.join([email.split('@')[0], domain])
[129]:
def reverse_totuple(ln):
    ln.reverse()
    tup = tuple(ln)
    return tup
#reverse_totuple([1, 2, 3, 4, 5])
[130]:
def sum_list(ln):
    int_sum = 0
    for value in ln:
        int_sum += value
    return int_sum
#sum_list([10, 20, 30])
[131]:
def atgc_countlist(str_atgc):
    list_count = []
    for value in 'ATGC':
        int_bpcnt = str_atgc.count(value)
        list_count.append([int_bpcnt, value])
    return list_count
#atgc_countlist('AAGCCCCATGGTAA')
[ ]:

================================================ FILE: docs/2/2-3.html ================================================ 2-3. 条件分岐 — Pythonプログラミング入門 documentation

2-3. 条件分岐

制御構造のうち条件分岐について説明します。

参考:

if で始まり条件分岐を行う制御構造によって、条件に応じてプログラムの動作を変えることができます。

ここではまず「インデント」について説明し、そのあとで条件分岐について説明します。

インデントによる構文

条件分岐の前に、Pythonのインデント(行頭の空白、字下げ)について説明します。 Pythonのインデントは実行文をグループにまとめる機能を持ちます。

プログラム文はインデントレベル(深さ)の違いによって異なるグループとして扱われます。 細かく言えば、インデントレベルが進む(深くなる)とプログラム文はもとのグループの下に位置する 別のグループに属するものとして扱われます。 逆に、インデントレベルが戻る(浅くなる)までプログラム文は同じグループに属することになります。

具体例として、第1回で定義した関数 bmax() を使って説明します:

[1]:
def bmax(a,b):
    if a > b:
        return a
    else:
        return b

print('Hello World')
Hello World

この例では1行目の関数定義 def bmax(a,b): の後から第1レベルのインデントが開始され5行目まで続きます。 すなわち、5行目までは関数 bmax を記述するプログラム文のグループということです。

次に、3行目の一行のみの第2レベルのインデントの実行文は、 if文(if による条件分岐)の論理式 a > bTrue の場合にのみ実行されるグループに属します。 そして、4行目の else ではインデントが戻されています。 5行目から再び始まる第2レベルの実行文は2行目の論理式が False の場合に実行されるグループに属します。

最後に、7行目ではインデントが戻されており、これ以降は関数 bmax() の定義とは関係ないことがわかります。

Pythonではインデントとして半角スペース4つが広く利用されています。 本教材でもこの書式を利用します。 1-4 のコーディングスタイルのところで紹介したスタイルガイドのPEP8でも、 半角スペース4つが推奨されています。

Codeセルでは行の先頭でTabを入力すれば、自動的にこの書式のインデントが挿入されます。 また、インデントを戻すときはShift-Tabが便利です。 なお、Colaboratoryでは、Tabを入力すると半角スペース2つのインデントが挿入されます。

ifelse による条件分岐

これまで関数 bmax を例にとって説明しましたが、一般にif文では、 が真であれば if 直後のグループが、偽であれば else 直後のグループが、それぞれ実行されます。(真であった場合、else 直後のグループは実行されません。)

if 式:
    ここのグループは「式」が真のときにのみ実行される
else:
    ここのグループは「式」が偽のときにのみ実行される

また、else は省略することができます。省略した場合、「式」が真のときに if 直後のグループが実行されるのみになります。

if 式:
    ここのグループは「式」が真のときにのみ実行される
ここのグループは常に実行される

条件が複雑になってくると、if文の中にさらにif文を記述して、条件分岐を入れ子ネスト)にすることがあります。 この場合は、インデントはさらに深くなります。

そして、下の2つのプログラムの動作は明らかに異なることに注意が必要です。

if 式1:
    ここのグループは「式1」が真のときにのみ実行される
    if 式2:
        ここのグループは「式1」「式2」が共に真のときにのみ実行される
        if 式3:
            ここのグループは「式1」「式2」「式3」が全て真のときにのみ実行される
        ここのグループは「式1」と「式2」が共に真のときにのみ実行される
    ここのグループは「式1」が真のときにのみ実行される
ここのグループは常に実行される
if 式1:
    ここのグループは「式1」が真のときにのみ実行される
ここのグループは常に実行される
if 式2:
    ここのグループは「式2」が真のときにのみ実行される (「式1」には影響されない)
ここのグループは常に実行される
if 式3:
    ここのグループは「式3」が真のときにのみ実行される (「式1」「式2」には影響されない)
ここのグループは常に実行される

ifelifelse による条件分岐

ここまでで if ... else 文について紹介しましたが、複数の条件分岐を続けて書くことができる elif を紹介します。

たとえばテストの点数から評定(優、良、可、…)を計算したい場合など、「条件1のときは処理1、条件1に該当しなくても条件2であれば処理2、更にどちらでもない場合、条件3であれば処理3、…」という処理を考えます。 if ... else による文のみでこの処理を行う場合、次のようなプログラムになってしまいます:

if 式1:
    「式1」が真のときにのみ実行するグループ
else:
    if 式2:
        「式1」が偽 かつ「式2」が真のときにのみ実行するグループ
    else:
        if 式3:
            「式1」「式2」が偽 かつ「式3」が真のときにのみ実行するグループ
        else:
            ...

このような場合には、以下のように elif を使うとより簡潔にできます:

if 式1:
    ここのグループは「式1」が真のときにのみ実行される
elif 式2:
    ここのグループは「式1」が偽 かつ「式2」が真のときにのみ実行される
elif 式3:
    ここのグループは「式1」「式2」が偽 かつ「式3」が真のときにのみ実行される
else:
    ここのグループは「式1」「式2」「式3」がいずれも偽のときにのみ実行される

ifelifelse では、条件は上から順に評価され、式が真の場合、 直後の実行文グループのみが実行され終了します。 その他の場合、すなわち全ての条件が False のときは、else 以降のグループが実行されます。

なお、elif もしくは else 以降を省略することも可能です。

練習

関数 exception3(x,y,z) の引数は以下の条件を満たすとします。

  • xyz の値は整数です。

  • xyz のうち、2つの値は同じで、もう1つの値は他の2つの値とは異なるとします。

その異なる値を返すように、以下のセルの ... のところを書き換えて exception3(x,y,z) を定義してください。

[2]:
def exception3(x,y,z):
    ...

次のセルで動作を確認してください。

[3]:
print(exception3(1,2,2))
print(exception3(4,2,4))
print(exception3(9,3,9))
None
None
None

練習

関数 exception9(a) の引数は以下の条件を満たすとします。

  • 引数 a には、長さが9のリストが渡されます。

  • このリストの要素は整数ですが、1つの要素を除いて、残りは要素の値は全て同じとします。

その1つの要素の値を返すように、以下のセルの ... のところを書き換えて exception9(a) を定義してください。

[4]:
def exception9(a):
    ...

次のセルで動作を確認してください。

[5]:
print(exception9([1,2,2,2,2,2,2,2,2]))
print(exception9([4,4,4,4,4,2,4,4,4]))
print(exception9([9,9,9,9,9,9,9,9,3]))
None
None
None

▲複数行にまたがる条件式

複雑な条件式では複数行に分割した方が見やすい場合もありあます。 ここでは、式を複数行にまたがって記述する1つの方法を示します。 1つ目は、丸括弧で括られた式を複数の行にまたがって記述する方法です。 2つ目は、行末にバックスラッシュ \ を置く方法です。

[6]:
### 丸括弧で括る方法
x, y, z = (-1, -2, -3)
if (x < 0 and y < 0 and z < 0 and
    x != y and y != z and x != z):
    print('x, y and z are different and negatives.')

### 行末にバックスラッシュ(\) を入れる方法

x, y, z = (-1, -2, -3)
if x < 0 and y < 0 and z < 0 and \
    x != y and y != z and x != z:
    print('x, y and z are different and negatives.')
x, y and z are different and negatives.
x, y and z are different and negatives.

ifelifelse における条件の評価

ifelif による条件分岐では、if あるいは elif に続く条件式が True の場合、 それ以降の elif に続く条件式の評価は行われません。

以下のプログラムで x3, 0, -4 とした際に何が表示されるかを予想したのちに実行してみましょう。

特に、 x = -4 としたときの動作に注意してください。(x is zero. は表示されません。)

[7]:
x = 3  # example: 3, 0, -4

if x > 0:
    print('x is greater than zero.')
elif x < 0:
    print('x is less than zero, but x will be 0')
    x = 0
else:
    print('x is zero.')

print(x)
x is greater than zero.
3

練習

以下のプログラムはプログラマの意図どおりに動作しません。 print の出力内容から意図を判断して条件分岐を書き換えてください。

[8]:
x = -1
if x < 3:
    print('x is larger than or equal to 2, and less than 3')
elif x < 2:
    print('x is larger than or equal to 1, and less than 2')
elif x < 1:
    print('x is less than 1')
else:
    print('x is larger or equal to 3')
x is larger than or equal to 2, and less than 3

or もしくは and で結合された条件の評価

if文に与える条件が or もしくは and で結合されている場合、条件は左から順に評価され、 不要(以降の式を評価するまでもなく自明)な評価は省かれます。

たとえば、if a == 0 or b == 0: において 最初の式 a == 0True の場合、式全体の結果が True となることは自明なので、 二番目の式 b == 0 を評価することなく続く実行文グループが実行されます。

逆に、if a == 0 and b == 0: において、 最初の式が False の場合、以降の式は評価されることなく処理が進みます。

以下のセルで示す例の1行目で、x の値を 0, -4 に変更し、表示される内容を予想し、予想通りか確認してください。

[9]:
x = 10          # del x のエラーを抑制するため
y = 10

del x           # x を未定義に

if x > 5 or y > 5:
    print("'x' or 'y' is larger than 5")
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[9], line 6
      2 y = 10
      4 del x           # x を未定義に
----> 6 if x > 5 or y > 5:
      7     print("'x' or 'y' is larger than 5")

NameError: name 'x' is not defined
[10]:
x = 10
y = 10          # del y のエラーを抑制するため

del y           # y を未定義に

if x > 5 or y > 5:
    print("'x' or 'y' is larger than 5")
'x' or 'y' is larger than 5

3項演算子(条件式)

Pythonでは以下のように if ... else を1行に書くこともできます。

[11]:
x = 0
sign = 'positive or zero' if x >= 0 else 'negative'
print(sign)
positive or zero

これは、以下と等価です。

[12]:
x = 0
if x >= 0 :
    sign = 'positive or zero'
else:
    sign = 'negative'
print(sign)
positive or zero

練習の解答

以下は解答例です。これ以外にも様々な解答があり得ます。

[13]:
def exception3(x,y,z):
    if x==y:
        return z
    elif x==z:
        return y
    else:
        return x
[14]:
def exception9(a):
    x = a[0] + a[1] + a[2]
    y = a[3] + a[4] + a[5]
    z = a[6] + a[7] + a[8]
    if x==y:
        return exception3(a[6], a[7], a[8])
    elif x==z:
        return exception3(a[3], a[4], a[5])
    else:
        return exception3(a[0], a[1], a[2])

練習の解説

最後の練習では、条件文の順番を修正する必要があります。 条件は上から順に処理され、式が真の場合にその「直後の実行文グループのみ」が処理されます。

[15]:
x = -1
if x < 1:
    print('x is less than 1')
elif x < 2:
    print('x is larger or equal to 1, and less than 2')
elif x < 3:
    print('x is larger or equal to 2, and less than 3')
else:
    print('x is larger or equal to 3')
x is less than 1
[ ]:

================================================ FILE: docs/3/3-1.html ================================================ 3-1. 辞書 (dictionary) — Pythonプログラミング入門 documentation

3-1. 辞書 (dictionary)

キーと値を対応させるデータ構造である辞書について説明します。

参考

辞書は、キー (key) と (value) を対応づけるデータです。 キーとしては、文字列・数値・タプルなどの変更不可能なデータを使うことができますが、 変更可能なデータであるリスト・辞書を使うことはできません。 (辞書も変更可能なデータです。) 一方、値としては、変更の可否にかかわらずあらゆる種類のデータを指定できます。

たとえば、文字列 'apple' をキーとし値として数値 3 を、'pen' をキーとして 5 を対応付けた辞書は、 次のように作成します。

[1]:
ppap = {'apple' : 3, 'pen' : 5}
ppap
[1]:
{'apple': 3, 'pen': 5}
[2]:
type(ppap)
[2]:
dict

辞書の キー1 に対応する値を得るには、リストにおけるインデックスと同様に、

辞書[キー1]

とします。

[3]:
ppap = {'apple' : 3, 'pen' : 5}
ppap['apple']
[3]:
3

辞書に登録されていないキーを指定すると、エラーになります。

[4]:
ppap['orange']
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[4], line 1
----> 1 ppap['orange']

KeyError: 'orange'

キーに対する値を変更したり、新たなキーと値を登録するには代入文を用います。

[5]:
ppap = {'apple' : 3, 'pen' : 5}
ppap['apple'] = 10
ppap['pinapple'] = 7
ppap
[5]:
{'apple': 10, 'pen': 5, 'pinapple': 7}

上のようにキーから値は取り出せますが、値からキーを直接取り出すことはできません。 また、リストのようにインデックスを指定して値を取得することはできません。

[6]:
ppap[1]
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[6], line 1
----> 1 ppap[1]

KeyError: 1

キーが辞書に登録されているかどうかは、演算子 in を用いて調べることができます。

[7]:
ppap = {'apple': 3, 'pen': 5}
'apple' in ppap
[7]:
True
[8]:
'banana' in ppap
[8]:
False

組み込み関数 len によって、辞書に登録されている要素、キーと値のペア、の数が得られます。

[9]:
ppap = {'apple': 3, 'pen': 5}
len(ppap)
[9]:
2

del 文によって、登録されているキーの要素を削除することができます。具体的には、次のように削除します。

del 辞書[削除したいキー]
[10]:
ppap = {'apple' : 3, 'pen' : 5}
del ppap['pen']
ppap
[10]:
{'apple': 3}

空のリストと同様に空の辞書を作ることもできます。このような空のデータは繰り返し処理でしばしば使われます。

[11]:
empty_d = {}
empty_d
[11]:
{}

練習

リスト list1 が引数として与えられたとき、list1 の各要素 value をキー、valuelist1 におけるインデックスをキーに対応する値とした辞書を返す関数 reverse_lookup を作成してください。

以下のセルの ... のところを書き換えて reverse_lookup(list1) を作成してください。

[12]:
def reverse_lookup(list1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[13]:
print(reverse_lookup(['apple', 'pen', 'orange']) == {'apple': 0, 'orange': 2, 'pen': 1})
False

辞書のメソッド

辞書のメソッドを紹介しておきます。

キーを指定して値を得るメソッド

get メソッドは、引数として指定したキーが辞書に含まれてる場合にはその値を取得し、 指定したキーが含まれていない場合には None を返します。 get を利用することで、エラーを回避し、登録されているかどうかわからないキーを使うことができます。 先に説明したキーを括弧、[...]、で指定する方法では、 辞書にキーが存在しないとエラーとなりプログラムの実行が停止してしまいます。

[14]:
ppap = {'apple' : 3, 'pen' : 5}
print('キーappleに対応する値 = ', ppap.get('apple'))
print('キーorangeに対応する値 = ', ppap.get('orange'))
print('キーorangeに対応する値(エラー) = ', ppap['orange'])
キーappleに対応する値 =  3
キーorangeに対応する値 =  None
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[14], line 4
      2 print('キーappleに対応する値 = ', ppap.get('apple'))
      3 print('キーorangeに対応する値 = ', ppap.get('orange'))
----> 4 print('キーorangeに対応する値(エラー) = ', ppap['orange'])

KeyError: 'orange'

また、get に2番目の引数を与えると、その引数の値を「指定したキーが含まれていない場合」に get が返す値とすることができます。

[15]:
ppap = {'apple' : 3, 'pen' : 5}
print('キーappleに対応する値 = ', ppap.get('apple', -1))
print('キーorangeに対応する値 = ', ppap.get('orange', -1))
キーappleに対応する値 =  3
キーorangeに対応する値 =  -1

▲キーがない場合に登録を行う

setdefault メソッドは、 指定したキーが辞書に含まれてる場合には、対応する値を返します。 キーが含まれていない場合には、2番目の引数として指定した値を返すと同時に、キーに対応する値として登録します。

[16]:
ppap = {'apple' : 3, 'pen' : 5}
print('キーappleに対応する値 = ', ppap.setdefault('apple', 7))
print('setdefault("apple", 7)を実行後の辞書 = ', ppap)
print('キーorangeに対応する値 = ', ppap.setdefault('orange', 7))
print('setdefault("orange", 7)を実行後の辞書 = ', ppap)
キーappleに対応する値 =  3
setdefault("apple", 7)を実行後の辞書 =  {'apple': 3, 'pen': 5}
キーorangeに対応する値 =  7
setdefault("orange", 7)を実行後の辞書 =  {'apple': 3, 'pen': 5, 'orange': 7}

上のような setdefault を用いた手続きを、[...] を用いて書き換えるとたとえば次のようになります。

[17]:
ppap = {'apple' : 3, 'pen' : 5}
if 'apple' not in ppap:
    ppap['apple'] = 7
print('キーappleに対応する値 = ', ppap['apple'])
print('実行後の辞書 = ', ppap)
if 'orange' not in ppap:
    ppap['orange'] = 7
print('キーorangeに対応する値 = ', ppap['orange'])
print('実行後の辞書 = ', ppap)
キーappleに対応する値 =  3
実行後の辞書 =  {'apple': 3, 'pen': 5}
キーorangeに対応する値 =  7
実行後の辞書 =  {'apple': 3, 'pen': 5, 'orange': 7}

▲キーを指定した削除

pop メソッドは指定したキーおよびそれに対応する値を削除し、削除されるキーに対応付けられた値を返します。

[18]:
ppap = {'apple' : 3, 'pen' : 5}
print(ppap.pop('pen'))
print(ppap)
5
{'apple': 3}

▲全てのキーと値の削除

clear メソッドは全てのキーと値を削除します。その結果、辞書は空となります。

[19]:
ppap = {'apple' : 3, 'pen' : 5}
ppap.clear()
ppap
[19]:
{}

キーの一覧を得る

keys メソッドはキーの一覧を返します。これはリストのようなものとして扱うことができ、 for ループと組み合わせて繰り返し処理で利用されます(3-2を参照してください)。 以下のように、keys メソッドが返した結果に関数 list を適用すると、 通常のリストになります。

[20]:
ppap = {'apple' : 3, 'pen' : 5}
list(ppap.keys())
[20]:
['apple', 'pen']

値の一覧を得る

values メソッドはキーに対応する全ての値の一覧を返します。これもリストのようなものとして扱うことができます。

[21]:
list(ppap.values())
[21]:
[3, 5]

キーと値の一覧を得る

items メソッドはキーとそれに対応する値をタプルにした一覧を返します。 これもタプルを要素とするリストのようなものとして扱うことができ、forループなどで活用します(3-2を参照してください)。

[22]:
list(ppap.items())
[22]:
[('apple', 3), ('pen', 5)]

▲辞書を複製する

copy メソッドは辞書を複製します。リストの場合と同様に一方の辞書を変更してももう一方の辞書は影響を受けません。

[23]:
ppap = {'apple': 3, 'pen': 5, 'orange': 7}
ppap2 = ppap.copy()
ppap['banana'] = 9
print(ppap)
print(ppap2)
{'apple': 3, 'pen': 5, 'orange': 7, 'banana': 9}
{'apple': 3, 'pen': 5, 'orange': 7}

keys, values, items の返値

keys, values, items メソッドの一連の説明では、返値を「リストのようなもの」と表現してきました。 通常のリストとどう違うのでしょうか?

次の例では、ppapkeys, values, items メソッドの返値をそれぞれ ks, vs, itms に代入し、 print でそれぞれの内容を表示させています。

次いで、ppap に新たな要素を加えたのちに、同じ変数の内容を表示させています。 1, 2回目の print で内容が異なることに注意してください。 もとの辞書が更新されると、これらの内容も動的に変わります。

[24]:
ppap = {'apple': 3, 'pen': 5, 'orange': 7}
ks = ppap.keys()
vs = ppap.values()
itms = ppap.items()
print(list(ks))
print(list(vs))
print(list(itms))
ppap['kiwi'] = 9
print(list(ks))
print(list(vs))
print(list(itms))
['apple', 'pen', 'orange']
[3, 5, 7]
[('apple', 3), ('pen', 5), ('orange', 7)]
['apple', 'pen', 'orange', 'kiwi']
[3, 5, 7, 9]
[('apple', 3), ('pen', 5), ('orange', 7), ('kiwi', 9)]

辞書とリスト

冒頭で述べたように、辞書では値としてあらゆる型のデータを使用できます。 すなわち、次のように値としてリストを使用する辞書を作成可能です。 リストの要素を参照するには数字インデックスをさらに指定します。

[25]:
numbers = {'dozens': [10, 20, 40], 'hundreds': [100, 101, 120, 140]}
print(numbers['dozens'])
print(numbers['dozens'][1])
[10, 20, 40]
20

逆に、辞書を要素とするリストを作成することもできます。

[26]:
ppap = {'apple': 3, 'pen': 5}
pets = {'cat': 3, 'dog': 3, 'elephant': 8}
ld = [ppap, pets]
print(ld[1])
print(ld[1]['dog'])
{'cat': 3, 'dog': 3, 'elephant': 8}
3

練習

辞書 dic1 と文字列 str1 が引数として与えられたとき、 以下のように dic1 を変更する関数 handle_collision を作成してください。 ただし、dic1 のキーは整数、キーに対応する値は文字列を要素とするリストとします。

  1. dic1str1 の長さ n がキーとして登録されていない場合、str1 のみを要素とするリスト ls を作成し、 dic1 にキー nn に対応する値 ls を登録します。

  2. dic1str1 の長さ n がキーとして登録されている場合、そのキーに対応する値(リスト)に str1 を追加します。

以下のセルの ... のところを書き換えて handle_collision(dic1, str1) を作成してください。

[27]:
def handle_collision(dic1, str1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[28]:
dic1_orig = {3: ['ham', 'egg'], 6: ['coffee', 'brandy'], 9: ['port wine'], 15: ['curried chicken']}
dic1_result = {3: ['ham', 'egg', 'tea'], 6: ['coffee', 'brandy'], 9: ['port wine'], 15: ['curried chicken']}
handle_collision(dic1_orig, 'tea')
print(dic1_orig == dic1_result)
False

練習の解答

[29]:
def reverse_lookup(list1):
    dic1 = {}  # 空の辞書を作成する
    for value in list1:
        dic1[value] = list1.index(value)
    return dic1
#reverse_lookup(['apple', 'pen', 'orange'])
[30]:
def handle_collision(dic1, str1):
    if dic1.get(len(str1)) is None:
        ls = [str1]
    else:
        ls = dic1[len(str1)]
        ls.append(str1)
    dic1[len(str1)] = ls
#handle_collision({3: ['ham', 'egg'], 6: ['coffee', 'brandy'], 9: ['port wine'], 15: ['curried chicken']}, 'tea')
[ ]:

================================================ FILE: docs/3/3-2.html ================================================ 3-2. 繰り返し — Pythonプログラミング入門 documentation

3-2. 繰り返し

制御構造のうち繰り返しについて説明します。

参考:

繰り返しを行う制御構造 forwhile によって、同じ処理の繰り返しを簡単にプログラムすることができます。

for文による繰り返し

2-2で、リストと文字列に対するfor文の繰り返しについて説明しました。 Pythonにおけるfor文の一般的な文法は以下のとおりです。

for 変数 in 文字列・リスト・辞書など:
    実行文

if文と同様、 実行文のインデントは深くなっていることに注意してください。

for文では in 以降に与えられる、文字列・リスト・辞書など にわたって、 実行文 のグループを繰り返します。 一般に繰り返しの順番は文字列・リスト・辞書などに要素が現れる順番で、 要素は forin の間の 変数 に代入されます。

リストの場合、リストの要素が最初から順番に取り出されます。以下に具体例を示します。関数 len は文字列の長さを返します。

[1]:
words = ['dog', 'cat', 'mouse']
for w in words:
    print(w, len(w))
print('finish')
dog 3
cat 3
mouse 5
finish

このプログラムで、for文には3つの文字列で構成されるリスト words が与えられています。 リストの要素は変数 w に順番に代入され、文字列とその長さが印字されます。 そして、最後の要素の処理がおわればfor文の繰り返し(ループ)を抜け、完了メッセージを印字します。

次は文字列に対する for文の例です。文字列を構成する文字が先頭から一文字ずつ文字列として取り出されます。

[2]:
word = 'supercalifragilisticexpialidocious'
for c in word:
    print(c)
s
u
p
e
r
c
a
l
i
f
r
a
g
i
l
i
s
t
i
c
e
x
p
i
a
l
i
d
o
c
i
o
u
s

組み込み関数 ord は与えられた文字の番号(コード)を整数として返します。 組み込み関数 chr は逆に与えられた整数をコードとする文字を返します。

[3]:
print(ord('a'))
print(ord('b'))
print(ord('z'))

print(chr(97))
97
98
122
a

上で確認しているように、文字 'a', 'b', 'z' のコードはそれぞれ 97, 98, 112 です。文字のコードは 'a' から 'z' までは連続して 1 ずつ増えていきます。

これを用いて以下のように英小文字から成る文字列の中の各文字の頻度を求めることができます。

[4]:
height = [0] * 26
for c in word:
    height[ord(c) - ord('a')] += 1

print(height)
[3, 0, 3, 1, 2, 1, 1, 0, 7, 0, 0, 3, 0, 0, 2, 2, 0, 2, 3, 1, 2, 0, 0, 1, 0, 0]

height を視覚化してみましょう。詳しくは、付録の 5-matplotlib を参照してください。

[5]:
import matplotlib.pyplot as plt

plt.plot(height)
[5]:
[<matplotlib.lines.Line2D at 0x104efa090>]
../_images/3_3-2_11_1.png
[6]:
left = list(range(26))  # range関数については以下を参照してください。
labels = [chr(i + ord('a')) for i in range(26)]  # 内包表記については 6-1 を参照ください。
plt.bar(left,height,tick_label=labels)
[6]:
<BarContainer object of 26 artists>
../_images/3_3-2_12_1.png

for文による繰り返しと辞書

辞書の要素にわたって操作を繰り返したい場合もfor文を用います。 辞書 dic1 の全てのキーを変数 key に代入しながら、実行文 を繰り返すには次のように書きます。

for key in dic1:
    実行文

for の行の in の後を、dic1 の代わりに dic1.keys() としても振舞いは同等であり、辞書のキー一覧を返す keys メソッドが自動的に使われます。

次の例では、キーを1つずつ取り出し、key に代入した後、 key に対応する値を参照しています。

[7]:
dic1 = {'cat': 3, 'dog': 3, 'elephant': 8}
for key in dic1:
    print('key:', key, ', value:', dic1[key])
key: cat , value: 3
key: dog , value: 3
key: elephant , value: 8

values メソッドを使えば(キーを使わずに)値を1つずつ取り出すこともできます。

[8]:
dic1 = {'cat': 3, 'dog': 3, 'elephant': 8}
for value in dic1.values():
    print('value:', value)
value: 3
value: 3
value: 8

items メソッドを使えばキーと値を一度に取り出すこともできます。 次の例では、in の左辺に複数の変数を指定し多重代入を行っています。

[9]:
dic1 = {'cat': 3, 'dog': 3, 'elephant': 8}
for key, value in dic1.items():
    print('key:', key, 'value:', value)
key: cat value: 3
key: dog value: 3
key: elephant value: 8

実は、辞書の items でなくとも、タプルのリストもしくはリストのリストに対しても、同様に複数の変数を指定することができます。

[10]:
list1 = [[0, 10], [1, 20], [2, 30]]
for i, j in list1:
    print(i, j)
0 10
1 20
2 30

練習

辞書 dic1 が引数として与えられたとき、次のような辞書 dic2 を返す関数 reverse_lookup2 を作成してください。ただし、 dic1 のキー key の値が value である場合、 dic2 には value というキーが登録されており、その値は key であるとします。また、 dic1 は異なる2つのキーに対応する値は必ず異なるとします。

以下のセルの ... のところを書き換えて reverse_lookup2 を作成してください。

[11]:
def reverse_lookup2(dic1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[12]:
print(reverse_lookup2({'apple': 3, 'pen': 5, 'orange': 7}) == {3: 'apple', 5: 'pen', 7: 'orange'})
False

range

特定の回数の繰り返し処理が必要なときは、range 関数を用います。

for value in range(j):
    実行文

これによって実行文を j 回実行します。具体例を見てみましょう。

[13]:
for value in range(5):
    print('Hi!')
Hi!
Hi!
Hi!
Hi!
Hi!

さて、forin の間の value は変数ですが、 value には何が入っているのか確認してみましょう。

[14]:
for value in range(5):
    print(value)
0
1
2
3
4

すなわち、value04 を動くことがわかります。

この value の値を用いることでリスト ln の要素を順番に用いることもできます。 回数としてリストの長さ len(ln) を指定します。

[15]:
ln = ['e', 'd', 'a', 'c', 'f', 'b']
for value in range(len(ln)):
    print(ln[value])
e
d
a
c
f
b

range() 関数は:

  1. 引数を1つ与えると 0 から引数までの整数列を返します。 このとき引数の値は含まれないことの注意してください。

  2. 引数を2つあるいは3つ与えると:

    • 最初の引数を数列の開始 (start)、2番目を停止 (stop)、3番目を数列の刻み (step) とする整数列を返します。

    • 3番目の引数は省略可能で、既定値は 1 となっています。

    • 2番目の引数の値は含まれないことの注意してください。

以下の例は、0 から 9 までの整数列の総和を計算、印字するプログラムです:

[16]:
s = 0
for i in range(10):
    s = s + i

print(s)
45

以下の例は、1 から 9 までの奇数の総和を計算、印字するプログラムです。

[17]:
s = 0
for i in range(1,10,2):
    s = s + i

print(s)
25

練習

引数で与えられる2つの整数 x, y 間(x, y を含む)の整数の総和を返す関数 sum_n を for文を利用して作成してください。 たとえば、sum_n(1,3) の結果は 1 + 2 + 3 = 6 となります。

以下のセルの ... のところを書き換えて sum_n を作成してください。

[18]:
def sum_n(x, y):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[19]:
print(sum_n(1, 3) == 6)
False

練習

整数 int_size を引数として取り、 長さが int_size であるリスト ln を返す関数 construct_list を作成してください。 ただし、 lni 番目の要素は i とします(i は 0 以上 int_size-1 以下の整数)。

以下のセルの ... のところを書き換えて construct_list(int_size) を作成してください。

[20]:
def construct_list(int_size):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[21]:
print(construct_list(10) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
False

range とリスト

range 関数は整数列を返しますが、リストを返さないことに注意してください。 これは、繰り返し回数の大きな for文などで大きなリストを作ると無駄が大きくなるためです。

range 関数を利用して整数列のリストを生成するには、 以下のように list を関数として用いて、明示的にリスト化する必要があります。

[22]:
seq_list = list(range(5))
print(seq_list)
[0, 1, 2, 3, 4]

for文の入れ子

for文を多重に入れ子ネスト)して使うこともよくあります。 まずは次の例を実行してみてください。

[23]:
list1 = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]

for i in range(4):
    for j in range(3):
        print('list1の', i + 1, '番目の要素(リスト)の', j + 1, '番目の要素 =', list1[i][j])
list1の 1 番目の要素(リスト)の 1 番目の要素 = a
list1の 1 番目の要素(リスト)の 2 番目の要素 = b
list1の 1 番目の要素(リスト)の 3 番目の要素 = c
list1の 2 番目の要素(リスト)の 1 番目の要素 = d
list1の 2 番目の要素(リスト)の 2 番目の要素 = e
list1の 2 番目の要素(リスト)の 3 番目の要素 = f
list1の 3 番目の要素(リスト)の 1 番目の要素 = g
list1の 3 番目の要素(リスト)の 2 番目の要素 = h
list1の 3 番目の要素(リスト)の 3 番目の要素 = i
list1の 4 番目の要素(リスト)の 1 番目の要素 = j
list1の 4 番目の要素(リスト)の 2 番目の要素 = k
list1の 4 番目の要素(リスト)の 3 番目の要素 = l

i = 0 のときに、2番目(内側)のfor文において、 j0 から 2 までの値が順に代入されて、各場合に print が実行されます。 その後、2番目の for文の実行が終わると、1番目(外側)のfor文の最初に戻って、 i の値に新しい値が代入されて、i = 1 になります。 その後、再度 2番目のfor文を実行することになります。 このときに、この2番目の for文の中で j には再度、0 から 2 までの値が順に代入されることになります。

決して、「最初に j = 2 まで代入したから、 もう2番目のfor文は実行しない」という訳ではないことに注意してください。 一度for文の実行を終えて、再度同じfor文(上の例でいうところの2番目の for文)に戻ってきた場合、 その手続きはまた最初からやり直すことになるのです。

以下のプログラムは、変数 C に組み合わせの数をリストのリストとして求めます。

C[i][j] は、i 個から j 個を選ぶ組み合わせの数になります。

[24]:
C = [[1]]
for i in range(100):
    C.append([1]+[0]*i+[1])
    for j in range(i):
        C[i+1][j+1] = C[i][j] + C[i][j+1]

C[:10]
[24]:
[[1],
 [1, 1],
 [1, 2, 1],
 [1, 3, 3, 1],
 [1, 4, 6, 4, 1],
 [1, 5, 10, 10, 5, 1],
 [1, 6, 15, 20, 15, 6, 1],
 [1, 7, 21, 35, 35, 21, 7, 1],
 [1, 8, 28, 56, 70, 56, 28, 8, 1],
 [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]]

C[100] を視覚化してみましょう。

[25]:
plt.plot(C[100])
[25]:
[<matplotlib.lines.Line2D at 0x1050aa090>]
../_images/3_3-2_51_1.png

練習

次のような関数 sum_lists を作成してください。

  • sum_lists はリスト list1 を引数とします。

  • list1 の各要素はリストであり、そのリストの要素は数です。

  • sum_lists は、list1 の各要素であるリストの総和を求め、それらの総和を足し合せて返します。

以下のセルの ... のところを書き換えて sum_lists を作成してください。

[26]:
def sum_lists(list1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[27]:
print(sum_lists([[20, 5], [6, 16, 14, 5], [16, 8, 16, 17, 14], [1], [5, 3, 5, 7]]) == 158)
False

練習

リスト list1list2 が引数として与えられたとき、次のようなリスト list3 を返す関数 sum_matrix を作成してください。

  • list1, list2, list3 は、3つの要素を持ちます。

  • 各要素は大きさ3のリストになっており、そのリストの要素は全て数です。

  • list3[i][j] (ただし、ij は共に、0以上2以下の整数)は list1[i][j]list2[i][j] の値の和になっています。

以下のセルの ... のところを書き換えて sum_matrix を作成してください。

[28]:
def sum_matrix(list1, list2):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[29]:
print(sum_matrix([[1,2,3],[4,5,6],[7,8,9]], [[1,4,7],[2,5,8],[3,6,9]]) == [[2, 6, 10], [6, 10, 14], [10, 14, 18]])
False

for文の計算量

山口和紀編「情報」第2版(東京大学出版会)には、「計算量とは、 アルゴリズムをもとにしたプログラムの実行時間を見積もるための指標である。」と書かれています。 さらに、「この見積もりは計算量のオーダーと呼ばれる非常におおまかな尺度で考える。」と書かれています。 (太字は引用時に追加しました。)

たとえば、リストに対するfor文

for x in リスト:
    要素xに対する処理

では、「要素に対する処理」が要素の数だけ実行されます。 この処理の時間が一定であるとすると、要素の数を \(n\) としたとき、 全体の処理には \(n\) に比例する時間がかかります。 このことを、オーダー \(n\) といって、\(O(n)\) と書きます。 一方、

for x in リスト:
    for y in 同じリスト:
        要素の組み合わせ(x,y)に対する処理

という二重のループでは、要素の組み合わせに対する処理が一定時間で終わるとしても、 ループの中でループが実行されるので、 全体の処理には、\(n^2\) に比例する時間がかかります。 このことを \(O(n^2)\) と書きます。 \(n\) が10倍になったとき、 一重のループの実行時間は10倍にしかなりませんが、 二重ループの実行時間は100倍になります。 \(n\) が100倍になったときは、前者は100倍ですが後者は10000倍になります。

二重ループが明らかでないこともあります。 以下の関数は、リストとして与えられたデータの平均と分散を計算するものです。

[30]:
def average(d):
    s = 0
    for x in d:
        s = s + x
    return s/len(d)

def variance(d):
    s = 0
    for x in d:
        s = s + (x-average(d))**2
    return s/len(d)

ガウス分布から100個のデータと10000個のデータを生成して分散を計算してみましょう。

[31]:
import random
d100 = []
for i in range(100):
    d100.append(random.gauss(0,10))
d10000 = []
for i in range(10000):
    d10000.append(random.gauss(0,10))
[32]:
variance(d100)
[32]:
119.19853794590166
[33]:
variance(d10000)
[33]:
102.13222070717606

10000個の場合は相当に時間がかかることがわかります。 これは、variance のfor文の中で average を呼んでいるためです。 見かけ上は一重ループなのですが、average の中にもループがあるため、 二重ループと同じ時間がかかります。 したがって、10000個の場合は、100個の場合に比べて10000倍時間がかかります。

ローカル変数を用いて variance の定義を書き直してみましょう。

[34]:
def variance(d):
    av = average(d)
    s = 0
    for x in d:
        s = s + (x-av)**2
    return s/len(d)
[35]:
variance(d100)
[35]:
119.19853794590166
[36]:
variance(d10000)
[36]:
102.13222070717606

10000個の場合でも一瞬で実行が終わったことでしょう。 この場合、一重のループを2回実行しているだけだからです。

enumerate

for文の繰り返し処理では、要素の順序を把握したいことがあります。 これまで学んだ方法では以下のように書けます。

i = 0
for val in some_list:
    print(i, val)
    # 繰り返させたい処理
    i += 1

Pythonでは enumerate() 関数が用意されており、上のプログラムは以下のように書き換えることができます。

for i, val in enumerate(some_list):
    # 繰り返させたい処理

2つの変数 i, val が指定されています。 i には 0, 1, 2, … が順に代入されます。 val にはリストの要素が順に代入されます。

たとえば、リストの要素をキー、そのインデックスを値とする辞書が欲しい場合は、以下のように書くことができます。

[37]:
words = ['dog', 'cat', 'mouse']
mapping = {}
for i, w in enumerate(words):
    mapping[w] = i

print(mapping)            # {'dog': 0, 'cat': 1, 'mouse': 2} が得られる。
{'dog': 0, 'cat': 1, 'mouse': 2}

in

Pythonでは for ループでリストを展開する in とは別に、 2-2 で説明したように、リスト内の要素の有無を検査する in 演算子と not in 演算子が定義されています。 以下のように、if 文の条件に in が出現した場合、for文とは動作が異なるので注意してください。

colors = ['red', 'green', 'blue']
color = 'red'

if color in colors:
    # do something

while文による繰り返し

while文では while の後の条件式が False となるまで、実行文グループを繰り返します。

下記のプログラムでは、\(\sum_{x=1}^{10}x\)total の値となります。

[38]:
x = 1
total = 0
while x <= 10:
    total += x
    x += 1

print(x, total)
11 55

条件式が False になったときに、 while文から抜けているので、 終了後の x の値が 11 になっていることに注意してください。 なお、上の例を for文で実行する場合には以下のようになります。

[39]:
total = 0
for x in range(11):
    total += x

print(x, total)
10 55

制御構造とreturn文

return文は1-2で説明したように関数を終了し、値を返す(返値)機能を持ちます。 if, for, while といった制御構造の中でreturn文が実行された場合、 ただちに関数の処理を終了し、その後の処理は行われません。

以下の関数 simple_lsearch は与えられたリスト、lstmyitem と等しいものがあれば True を、なければ False を返します。

  • 2行目のfor文で lst の各要素に対して繰り返しを実行するように指定されています。

  • 3行目のif文で要素 itemmyitem と等しい場合、4行目の return True でただちに関数を終了しています。

  • for文で全てのリスト要素に対してテストが終わり、等しいものがない場合は、5行目の return False が実行されます。

[40]:
def simple_lsearch(lst, myitem):
    for item in lst:
        if item == myitem:
            return True
    return False

break文

break文は、 for文もしくはwhile文の実行文グループで利用可能です。 break文は実行中のプログラムで最も内側の繰り返し処理を中断し、そのループを終了させる目的で利用されます。 以下のプログラムは、初項 256、公比 1/2、の等比級数の和を求めるものです。 ただし、総和が 500 をこえれば打ち切られます。

[41]:
x = 256
total = 0
while x > 0:
    if total > 500:
        break           # 500 を超えれば while ループを抜ける
    total += x
    x = x // 2          # // は少数点以下を切り捨てる除算

print(x, total)
4 504

練習

文字列 str1str2 が引数として与えられたとき、 str1str2 を部分文字列として含むかどうか判定する関数 simple_match を作成してください。 具体的には、str2 を含む場合、 その部分文字列が開始される str1 のインデックスを返値として返してください。 str2 を含まない場合、 -1 を返してください。 ただし、simple_match の中で文字列のメソッドやモジュール(正規表現など)を使ってはいけません。

以下のセルの ... のところを書き換えて simple_match を作成してください。

[42]:
def simple_match(str1, str2):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[43]:
print(simple_match('location', 'cat') == 2)
print(simple_match('soccer', 'cat') == -1)
print(simple_match('category', 'cat') == 0)
print(simple_match('carpet', 'cat') == -1)
False
False
False
False

continue文

continue文はbreak文同様に、for および while ループの実行文グループで利用可能です。 continue文は実行中のプログラムで最も内側の繰り返し処理を中断し、次のループの繰り返しの処理を開始します。

下記のプログラムでは、colors リストの 'black' は印字されませんが 'white' は印字されます。

[44]:
colors = ['red', 'green', 'blue', 'black', 'white']
for c in colors:
    if c == 'black':
           continue
    print(c)
red
green
blue
white

▲for文とwhile文における else

for文およびwhile文では else を書くこともできます。 この実行文グループは、ループの最後に一度だけ実行されます。

[45]:
colors = ['red', 'green', 'blue', 'black', 'white']
for c in colors:
    if c == 'black':
        continue
    print(c)
else:
    print('')
red
green
blue
white

for文およびwhile文の else ブロックの内容は continue で終了したときは実行されますが、一方で break でループを終了したときは実行されません。

pass文

Pythonでは空の実行文グループは許されていません。 一方で、空白のコードブロックを用いることでプログラムが読みやすくなる場合があります。 たとえば以下の、ifelifelse プログラムはエラーとなります。

[46]:
x = -1
if x < 0:
    print('x is positive')
elif x == 0:
    # IndentationError: expected an indented block
elif 0 < x < 5:
    print('x is positive and smaller than 5')
else:
    print('x is positive and larger than or equal to 5')
  Cell In[46], line 6
    elif 0 < x < 5:
    ^
IndentationError: expected an indented block after 'elif' statement on line 4

なにもしないpass文を用いて、以下のように書き換えることで正常に実行されます。

[47]:
x = -1
if x < 0:
    print('x is positive')
elif x == 0:
    # no error
    pass
elif 0 < x < 5:
    print('x is positive and smaller than 5')
else:
    print('x is positive and larger than or equal to 5')
x is positive

練習

以下のプログラムでは1秒おきに print が永久に実行されます。

from time import sleep

while True:
    print('Yeah!')
    sleep(1)

10回 print が実行された後にwhile文を終了するように書き換えてください。 実行中のセルを停止させるには、ストップボタンが使えます。

[ ]:

練習

英語の文章からなる文字列 str_engsentence が引数として与えられたとき、 str_engsentence 中に含まれる3文字以上の全ての英単語を要素とするリストを返す関数 collect_engwords を作成してください。ただし、同じ単語を重複して含んでいて構いません。

以下のセルの ... のところを書き換えて collect_engwords(str_engsentence) を作成してください。

[48]:
def collect_engwords(str_engsentence):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[49]:
print(collect_engwords('Unfortunately no, it requires something with a little more kick, plutonium.') == ['Unfortunately', 'requires',
'something', 'with', 'little', 'more', 'kick', 'plutonium'])
False

練習

2つの同じ大きさのリストが引数として与えられたとき、 2つのリストの奇数インデックスの要素を入れ替えて、 その結果得られる2つのリストをタプルにして返す関数 swap_lists を作成してください (ただし、0 は偶数として扱うものとします)。 与えられたリストは破壊しても構いません。

以下のセルの ... のところを書き換えて swap_lists(ln1, ln2) を作成してください。

[50]:
def swap_lists(ln1, ln2):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[51]:
print(swap_lists([1, 2, 3, 4, 5], ['a', 'b', 'c', 'd', 'e']) == ([1, 'b', 3, 'd', 5], ['a', 2, 'c', 4, 'e']))
False

練習

文字列 str1 を引数として取り、 str1 の中に含まれる大文字の数を返す関数 count_capitalletters を作成してください。

以下のセルの ... のところを書き換えて count_capitalletters(str1) を作成してください。

[52]:
def count_capitalletters(str1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[53]:
print(count_capitalletters('Que Será, Será') == 3)
False

練習

長さが 3 の倍数である文字列 str_augc が引数として与えられたとき、 str_augc を長さ 3 の文字列に区切り、それらを順に格納したリストを返す関数 identify_codons を作成してください。

以下のセルの ... のところを書き換えて identify_codons(str_augc) を作成してください。

[54]:
def identify_codons(str_augc):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[55]:
print(identify_codons('CCCCCGGCACCT') == ['CCC', 'CCG', 'GCA', 'CCT'])
False

練習

正の整数 int1 が引数として与えられたとき、 int1 の値の下桁から3桁毎にコンマ (,) を入れた文字列を返す関数 add_commas を作成してください。 ただし、数の先頭にコンマを入れる必要はありません。

以下のセルの ... のところを書き換えて add_commas を作成してください。

[56]:
def add_commas(int1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、全ての実行結果が True になることを確認してください。

[57]:
print(add_commas(14980) == '14,980')
print(add_commas(3980) == '3,980')
print(add_commas(298) == '298')
print(add_commas(1000000) == '1,000,000')
False
False
False
False

練習

リスト list1 が引数として与えられ、次のような文字列 str1 を返す関数 sum_strings を作成してください。

list1k 個の要素を持つとします(ただし、k は正の整数)。 list1 の要素が文字列でなければ文字列に変換してください。 その上で、list1 の1番目から k-2 番目の各要素の後ろにコンマとスペースからなる文字列 ', ' を加え、 k-1 番目の要素の後ろには、' and ' を加え、1番目から k 番目までの要素を繋げた文字列を str1 とします。

以下のセルの ... のところを書き換えて sum_strings を作成してください。

[58]:
def sum_strings(list1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[59]:
print(sum_strings(['a', 'b', 'c', 'd']) == 'a, b, c and d')
print(sum_strings(['a']) == 'a')
print(sum_strings([1, 2, 3]) == '1, 2 and 3')
False
False
False

練習

辞書 dic1 と長さ 10 以下の文字列 str1 が引数として与えられたとき、 以下のように dic1 を変更する関数 handle_collision2 を作成してください。 ただし、dic1 のキーは、1 以上 10 以下の整数、キーに対応する値は文字列とします。

  1. dic1str1 の長さ n がキーとして登録されていない場合、dic1 に キー nn に対応する値 str1 を登録します。

  2. dic1str1 の長さ n がキーとして登録されている場合、i の値を n+1, n+2, …と1つずつ増やしていき、dic1 にキーとして登録されていない値 i を探します。キーとして登録されていない値 i が見つかった場合、その i をキー、i に対応する値として str1 を登録してください。 ただし、i を 10 まで増やしても登録されていない値が見つからない場合は、i を 1 に戻した上で i を増やす作業を続行してください。

  3. 2の手順によって、登録可能な i が見つからなかった場合、dic1 を変更しません。

以下のセルの ... のところを書き換えて handle_collision2(dic1, str1) を作成してください。

[60]:
def handle_collision2(dic1, str1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[61]:
dic1_orig = {6: 'Styles', 4: 'Link', 7: 'Ackroyd'}
handle_collision2(dic1_orig, 'Big Four')
print(dic1_orig == {6: 'Styles', 4: 'Link', 7: 'Ackroyd', 8: 'Big Four'})
dic1_orig = {6: 'Styles', 4: 'Link', 7: 'Ackroyd', 8: 'Big Four', 10: 'Blue Train', 9: 'End House'}
handle_collision2(dic1_orig, 'Edgware')
print(dic1_orig == {6: 'Styles', 4: 'Link', 7: 'Ackroyd', 8: 'Big Four', 10: 'Blue Train', 9: 'End House', 1: 'Edgware'})
dic1_orig = {6: 'Styles', 4: 'Link', 7: 'Ackroyd', 8: 'Big Four', 10: 'Blue Train', 9: 'End House', 1: 'Edgware', 2: 'Orient', 3: 'Three Act', 5: 'Clouds'}
handle_collision2(dic1_orig, 'ABC')
print(dic1_orig == {6: 'Styles', 4: 'Link', 7: 'Ackroyd', 8: 'Big Four', 10: 'Blue Train', 9: 'End House', 1: 'Edgware', 2: 'Orient', 3: 'Three Act', 5: 'Clouds'})
False
False
True

練習

整数を最初の要素、文字列をその次の要素とするリスト(これを子リストと呼びます)を要素とするリスト list1 が引数として与えられたとき、次のような辞書 dic1 を返す関数 handle_collision3 を作成してください。

  • 各子リスト list2 に対して、dic1 のキーは list2 の最初の要素である整数とし、そのキーに対応する値は次の要素である文字列とします。

  • 2つ以上の子リストの最初の要素が同じ整数である場合、list1 においてより小さいインデックスを持つ子リストの文字列を、その整数のキーに対応する値とします。

以下のセルの ... のところを書き換えて handle_collision3(list1) を作成してください。

[62]:
def handle_collision3(list1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[63]:
print(handle_collision3([[3, 'Richard III'], [1, 'Othello'], [2, 'Tempest'], [3, 'King John'], [4, 'Midsummer'], [1, 'Lear']]) == {1: 'Othello', 2: 'Tempest', 3: 'Richard III', 4: 'Midsummer'})
False

練習の解答

[64]:
def reverse_lookup2(dic1):
    dic2 = {}  #辞書を初期化する
    for key, value in dic1.items():
        dic2[value] = key
    return dic2
#reverse_lookup2({'apple':3, 'pen':5, 'orange':7})
[65]:
def sum_n(x,y):
    sum = 0
    for i in range(x, y + 1):
        sum = sum + i
    return sum
#sum_n(1,3)
[66]:
def construct_list(int_size):
    ln = int_size * [0]
    for i in range(int_size):
        ln[i] = i
    return ln
#construct_list(10)
[67]:
def sum_lists(list1):
    total = 0
    for list2 in list1:  # for j in range(len(list1)):とlist2 = list1[j]としてもよい
        #print(list2)
        for i in range(len(list2)):
            #print(i, list2[i])
            total += list2[i]
    return total
[68]:
def sum_matrix(list1, list2):
    list3 = [[0,0,0],[0,0,0],[0,0,0]]  #結果を格納するリストを初期化する(これがない場合も試してみてください)
    for i in range(3):
        for j in range(3):
            list3[i][j] += list1[i][j] + list2[i][j]
            #print(i, j, list1[i][j],'+', list2[i][j], '=', list3[i][j])
    return list3
#sum_matrix([[1,2,3],[4,5,6],[7,8,9]], [[1,4,7],[2,5,8],[3,6,9]])
[69]:
def simple_match(str1, str2):
    for i in range(len(str1)-len(str2)+1):
        j = 0
        while j < len(str2) and str1[i+j] == str2[j]:  #str1とstr2が一致している限りループ(ただし、jがstr2の長さ以上にならないようにする)#この条件がないと…?
            j += 1
        if j == len(str2):  #str2の最後まで一致しているとこの条件が成立
            return i
    return -1
#for文による別解
#def simple_match(str1, str2):
#    for i in range(len(str1)-len(str2)+1):
#        #print('i=', i)
#        fMatch = True#マッチ判定
#        for j in range(len(str2)):
#            #print('j=', j, 'str1[i+j]=', str1[i+j], ' str2[j]=', str2[j])
#            if str1[i+j] != str2[j]:#str2が終了する前に一致しない箇所があるかどうか
#                fMatch = False
#                break
#        if fMatch:
#            return i
#    return -1
#print(simple_match('location', 'cat') == 2)
#print(simple_match('soccer', 'cat') == -1)
#print(simple_match('category', 'cat') == 0)
#print(simple_match('carpet', 'cat') == -1)

練習の解説

下のセルは、繰り返し回数として count 変数を利用した解答例です。回数を理解しやすくするため print() 関数で count 変数も印字しています。

[70]:
from time import sleep

count = 0
while True:
    print('Yeah!', count)
    count += 1
    if(count >= 10):
        break
    sleep(1)
Yeah! 0
Yeah! 1
Yeah! 2
Yeah! 3
Yeah! 4
Yeah! 5
Yeah! 6
Yeah! 7
Yeah! 8
Yeah! 9

練習の解答

[71]:
def collect_engwords(str_engsentences):
    list_punctuation = ['.', ',', ':', ';', '!', '?']
    for j in range(len(list_punctuation)):  #list_punctuationの中の文字列(この場合、句読点)を空文字列に置換する
        str_engsentences = str_engsentences.replace(list_punctuation[j], '')
    #print(str_engsentences)
    list_str1 = str_engsentences.split(' ')
    list_str2 = []
    for j in range(len(list_str1)):
        if len(list_str1[j]) >= 3:
            list_str2.append(list_str1[j])
    return list_str2
#collect_engwords('Unfortunately no, it requires something with a little more kick, plutonium.')
[72]:
def swap_lists(ln1, ln2):
    for j in range(len(ln1)):
        if j % 2 == 1:
            ln1[j], ln2[j] = ln2[j], ln1[j]
    return ln1, ln2
#swap_lists([1, 2, 3, 4, 5], ['a', 'b', 'c', 'd', 'e'])
[73]:
def count_capitalletters(str1):
    int_count = 0
    for i in range(len(str1)):
        str2 = str1[i].upper()
        str3 = str1[i].lower()
        if str1[i] == str2 and str2 != str3:#前者の条件で大文字であることを、後者の条件で句読点などでないことを判定する
            int_count += 1
    return int_count
#count_capitalletters('Que Será, Será')
[74]:
def identify_codons(str_augc):
    str_codons = []
    int_codonnum = int(len(str_augc)/3)
    for i in range(int_codonnum):
        str_codons.append(str_augc[i*3: i*3+3])
    return str_codons
#identify_codons('CCCCCGGCACCT')
[75]:
def add_commas(int1):
    list1 = list(str(int1))  #文字列に変換し、更にそれを1文字ずつリストに格納する
    str1 = ''
    ccnt = 1  #3の倍数の位を調べるのに使う
    for i in range(len(list1)-1, -1, -1):  #1の位の値から、大きい方の位の値に向かって処理を行う
        str1 = list1[i] + str1
        if ccnt % 3 == 0 and i != 0:  #3の倍数の位の前であり、一番大きい位でないならば
            str1 = ',' + str1  #コンマをうつ
        ccnt += 1
    return str1
#print(add_commas(14980) == '14,980')
#print(add_commas(2980) == '2,980')
#print(add_commas(298) == '298')
#print(add_commas(1000000) == '1,000,000')
[76]:
def sum_strings(list_str):
    str1 = ''
    for i in range(len(list_str)):
        if i < len(list_str) - 2:#後ろから3番目までの要素
            str1 = str1 + str(list_str[i]) + ', '
        elif i == len(list_str) - 2:#後ろから2番目の要素
            str1 += str(list_str[i]) + ' and '
        else:#一番後ろの要素
            str1 += str(list_str[i])
    return str1
#sum_strings(['a', 'b', 'c', 'd'])
#sum_strings(['a'])
[77]:
def handle_collision2(dic1, str1):
    n = len(str1)
    for i in range(n, 11):
        if  dic1.get(i) is None:# == None でもよい
            dic1[i] = str1
            return
    for i in range(1, n):
        if  dic1.get(i) is None:# == None でもよい
            dic1[i] = str1
            return
[78]:
def handle_collision3(list1):
    dic1 = {} # 空の辞書を作成する
    for i in range(len(list1)):
        list2 = list1[i]
        if dic1.get(list2[0]) is None:# == None でもよい
            dic1[list2[0]] = list2[1]
    return dic1
#handle_collision3([[3, 'Richard III'], [1, 'Othello'], [2, 'Tempest'], [3, 'King John'], [4, 'Midsummer'], [1, 'Lear']])
[ ]:

================================================ FILE: docs/3/3-3.html ================================================ 3-3. 関数 — Pythonプログラミング入門 documentation

3-3. 関数

関数について改めて説明します。

参考:

関数の定義

関数は処理(手続きの流れ)をまとめた再利用可能なコードです。関数には以下の特徴があります。

  • 名前を持つ。

  • 手続きの流れを含む。

  • 返値(明示的あるいは非明示的に)を返す。

len()sum() などの組み込み関数は関数の例です。

まず、関数の定義をしてみましょう。関数を定義するには def を用います。

[1]:
#'Hello'を表示する関数greeting
def greeting():
    print('Hello')

関数を定義したら、それを呼び出すことができます。

[2]:
#関数greetingを呼び出し
greeting()
Hello

関数定義の一般形は以下の通りです。

def 関数名(引数):
    関数本体

1行名はヘッダと呼ばれ、関数名はその関数を呼ぶのに使う名前、引数はその関数へ渡す変数の一覧です。 変数がない場合もあります。

関数本体はインデントした上で、処理や手続きの流れを記述します。

引数

関数を定義する際に、ヘッダの括弧の中に関数へ渡す変数の一覧を記述します。 これらの変数は関数のローカル変数となります。 ローカル変数とはプログラムの一部(ここでは関数内)でのみ利用可能な変数です。

[3]:
#引数greeting_localに渡された値を表示する関数greeting
def greeting(greeting_local):
    print(greeting_local)

関数を呼び出す際に引数に値を渡すことで、関数は受け取った値を処理することができます。

[4]:
#関数greetingに文字列'Hello'を渡して呼び出し
greeting('Hello')
Hello

このようにして引数に渡される値のことを、実引数argument)と呼ぶことがあります。 実引数に対して、ここまで説明してきた引数(ローカル変数である引数)は、仮引数parameter)と呼ばれます。 参考:公式FAQ:実引数と仮引数の違いは何ですか?

実引数のことを引数と呼ぶこともありますので、注意してください。

返値

関数は受け取った引数を元に処理を行い、その結果の返値(1-2で説明済み)を返すことができます。

返値は、return で定義します。関数の返値がない場合は、None が返されます。 return が実行されると、関数の処理はそこで終了するため、次に文があっても実行はされません。 また、ループなどの繰り返し処理の途中でも return が実行されると処理は終了します。 関数の処理が最後まで実行され、返値がない場合は最後に return を実行したことと同じになります。

return の後に式がない場合は、None が返されます。 (return が実行されずに関数の最後まで来たときも同様です。) return を式なしで実行することで、関数の処理を途中で抜けることができます。 また、このような関数は、与えられた配列を破壊的に変更するなど、 呼び出した側に何らかの変化を及ぼす際にも用いられます。

[5]:
#引数greeting_localに渡された値を返す関数greeting
def greeting(greeting_local):
    return greeting_local

#関数greetingに文字列'Hello'を渡して呼び出し
greeting('Hello')
[5]:
'Hello'
[6]:
#入力の平均を計算して返す関数average
def average(nums):
    #組み込み関数のsum()とlen()を利用
    return sum(nums)/len(nums)

#関数averageに数字のリストを渡して呼び出し
average([1,3,5,7,9])
[6]:
5.0

関数の返値を変数に代入することもできます。

[7]:
#関数greetingの返値を変数greetに代入
greet = greeting('Hello')
greet
[7]:
'Hello'

複数の引数

関数は任意の数の引数を受け取ることができます。 複数の引数を受け取る場合は、引数をコンマで区切ります。 これらの引数名は重複しないようにしましょう。

[8]:
#3つの引数それぞれに渡された値を表示する関数greeting
def greeting(en, fr, de):
    print(en + ', ' + fr + ', ' + de)

#関数greetingに3つの引数を渡して呼び出し
greeting('Hello', 'Bonjour', 'Guten Tag')
Hello, Bonjour, Guten Tag

関数は異なる型であっても引数として受け取ることができます。

[9]:
#文字列と数値を引数として受け取る関数greeting
def greeting(en, number, name):
    #文字列に数を掛け算すると、文字列を数の回だけ繰り返すことを指定します
    print(en*number+','+name)

#関数greetingに文字列と数値を引数として渡して呼び出し
greeting('Hello',3, 'World')
HelloHelloHello,World

変数とスコープ

関数の引数や関数内で定義される変数はローカル変数のため、それらの変数は関数の外からは参照できません。

[10]:
#引数greeting_localに渡された値を表示する関数greeting
def greeting(greeting_local):
    print(greeting_local)

greeting('Hello')

#ローカル変数(関数greetingの引数)greeting_localを参照
greeting_local
Hello
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[10], line 8
      5 greeting('Hello')
      7 #ローカル変数(関数greetingの引数)greeting_localを参照
----> 8 greeting_local

NameError: name 'greeting_local' is not defined

一方、変数がグローバル変数であれば、それらの変数は関数の外からも中からも参照できます。 グローバル変数とはプログラム全体、どこからでも利用可能な変数です。

[11]:
#グローバル変数greeting_globalの定義
greeting_global = 'Hello'

#グローバル変数greeting_globalの値を表示する関数greeting
def greeting():
    print(greeting_global)

greeting()

#グローバル変数greeting_globalを参照
greeting_global
Hello
[11]:
'Hello'

グローバル変数と同じ名前の変数を関数内で定義すると、 それは通常はグローバル変数とは異なる、関数内のみで利用可能なローカル変数の定義として扱われます。 グローバル変数と同じ名前の引数を用いる場合も同様です。

[12]:
#グローバル変数greeting_globalと同じ名前の変数に値を代入する関数greeting
def greeting():
    greeting_global = 'Bonjour'
    print(greeting_global)

greeting()

#変数greeting_globalを参照
greeting_global
Bonjour
[12]:
'Hello'

しかし、グローバル変数と同名のローカル変数を定義することは、一般に注意が必要です。 何故なら、ローカル変数としての定義を含む関数内では、同名のグローバル変数を参照できないからです。 たとえば、次のコードは、HelloBonjour が順に印字することを期待するかもしれませんが、

[13]:
def greeting():
    print(greeting_global) # 最初の参照
    greeting_global = 'Bonjour' # ローカル変数の定義
    print(greeting_global)

greeting()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Cell In[13], line 6
      3     greeting_global = 'Bonjour' # ローカル変数の定義
      4     print(greeting_global)
----> 6 greeting()

Cell In[13], line 2, in greeting()
      1 def greeting():
----> 2     print(greeting_global) # 最初の参照
      3     greeting_global = 'Bonjour' # ローカル変数の定義
      4     print(greeting_global)

UnboundLocalError: cannot access local variable 'greeting_global' where it is not associated with a value

最初の greeting_global の参照でエラーになります。 これは、関数内に greeting_global の定義があると、 その関数内どの場所でも greeting_global がローカル変数として参照されるためです。 最初の参照時には、ローカル変数の greeting_global が未定義なので、エラーが生じます。

このように、グローバル変数と同じ名前のローカル変数を使おうとするのは間違いの元です。 グローバル変数と名前が衝突しないように、ローカル変数を定義しましょう。

▲ global 宣言

関数内ではグローバル変数が更新されないのが基本です。 しかし、どうしても関数内でグローバル変数を更新したいときには、 global 宣言を使って更新したいグローバル変数を指定します。

[14]:
#グローバル変数greeting_globalに値を代入する関数greeting
def greeting():
    global greeting_global
    greeting_global = 'Bonjour'
    print(greeting_global)

greeting()

##変数greeting_globalを参照
greeting_global
Bonjour
[14]:
'Bonjour'

global 宣言された変数名は、関数内で常にグローバル変数として参照されます。 これを濫用すると間違いの元になるので、原則として利用しないようにしましょう。

▲キーワード引数

上記の一般的な引数(位置引数とも呼ばれます)では、 事前に定義した引数の順番に従って、関数は引数を受け取る必要があります。

キーワード付き引数(キーワード引数)を使うと、関数は引数の変数名とその値の組みを受け取ることができます。 その際、引数は順不同で関数に渡すことができます。

[15]:
#文字列と数値を引数として受け取る関数greeting
def greeting(en, number, name):
    print(en*number+','+name)

#関数greetingに引数の変数名とその値の組みを渡して呼び出し
greeting(en='Hello', name='Japan', number=2)
HelloHello,Japan

位置引数とキーワード引数を合わせて使う場合は、最初に位置引数を指定する必要があります。

[16]:
#位置引数とキーワード引数を組み合わせた関数greetingの呼び出し
greeting('Hello', name='Japan', number=2)
HelloHello,Japan

▲引数の初期値

関数を呼び出す際に、引数が渡されない場合に、初期値を引数として渡すことができます。

初期値のある引数に値を渡したら、関数はその引数の初期値の代わりに渡された値を受け取ります。

初期値を持つ引数は、位置引数の後に指定する必要があります。

[17]:
#引数の初期値(引数の変数enに対する'Hello')を持つ関数greeting
def greeting(name, en='Hello'):
    print(en+', '+name)

#引数の初期値を持つ関数greetingの呼び出し
greeting('World')
Hello, World

▲可変長引数

仮引数の前に * を付けて関数を定義すると、複数の引数をタプルとして受け取ることができます。 呼び出す側は、引数の個数を変えることができます。 一般に、個数が可変の引数は可変長引数と呼ばれます。

[18]:
#可変長の引数を受け取り、それらを表示する関数greeting
def greeting(*args):
    print(args)

#可変長の引数を受け取る関数greetingに複数の引数を渡して呼び出し
greeting('Hello','Bonjour','Guten Tag')
('Hello', 'Bonjour', 'Guten Tag')

リストやタプルの要素を可変長引数として関数に渡す場合は、* をリストやタプルの前につけて渡します。

[19]:
#リスト型オブジェクトgreeting_listを関数greetingに渡して呼び出し
greeting_list = ['Hello','Bonjour','Guten Tag']
greeting(*greeting_list)
('Hello', 'Bonjour', 'Guten Tag')

▲辞書型の可変長引数

仮引数の前に ** を付けて関数を定義すると、複数のキーワード引数を辞書として受け取ることができます。辞書として受け取られる引数は、辞書型の可変長引数と呼ばれます。

[20]:
#可変長のキーワード引数を受け取り、それらを表示する関数greeting
def greeting(**kwargs):
    print(kwargs)

#可変長のキーワード引数を受け取る関数greetingに複数の引数を渡して呼び出し
greeting(en='Hello', fr='Bonjour', de='Guten Tag')
{'en': 'Hello', 'fr': 'Bonjour', 'de': 'Guten Tag'}

辞書の各キーと値を複数のキーワード引数として関数に渡す場合は、 ** をその辞書の前につけて渡します。

[21]:
#辞書型オブジェクトgreeting_dictを関数greetingに渡して呼び出し
greeting_dict = {'en': 'Hello', 'fr': 'Bonjour', 'de': 'Guten Tag'}
greeting(**greeting_dict)
{'en': 'Hello', 'fr': 'Bonjour', 'de': 'Guten Tag'}

▲引数の順番

位置引数、初期値を持つ引数、可変長引数、辞書型の可変長引数は、同時に指定することができますが、 その際、これらの順番で指定する必要があります。

def 関数名(位置引数, 初期値を持つ引数, 可変長引数, 辞書型の可変長引数)
[22]:
#位置引数、初期値を持つ引数、可変長引数、辞書型の可変長引数
#それぞれを引数として受け取り、それらを表示する関数greeting
def greeting(greet, en='Hello', *args, **kwargs):
    print(greet)
    print(en)
    print(args)
    print(kwargs)

#可変長引数へ渡すリスト
greeting_list = ['Bonjour']

#辞書型の可変長引数へ渡す辞書
greeting_dict = {'de': 'Guten Tag'}

#関数greetingに引数を渡して呼び出し
greeting('Hi', 'Hello', *greeting_list, **greeting_dict)
Hi
Hello
('Bonjour',)
{'de': 'Guten Tag'}

▲変数としての関数

関数は変数でもあります。既存の変数と同じ名前の関数を定義すると、 元の変数はその新たな関数を参照するものとして変更されます。 一方、既存の関数と同じ名前の変数を定義すると、元の関数名の変数はその新たな変数を参照するものとして変更されます。

[23]:
#グローバル変数greeting_globalの定義と参照
greeting_global = 'Hello'
type(greeting_global)
[23]:
str
[24]:
#グローバル変数greeting_globalと同名の関数の定義
#変数greeting_globalは関数を参照する
def greeting_global():
    print('This is the greeting_global function')

type(greeting_global)
[24]:
function
================================================ FILE: docs/4/4-1.html ================================================ 4-1. ファイル入出力の基本 — Pythonプログラミング入門 documentation

4-1. ファイル入出力の基本

ファイル入出力の基本について説明します。

参考

ファイルのオープン

ファイルから文字列を読み込んだり、ファイルに書き込んだりするには、 まず、open() という関数によってファイルをオープンする(開く)必要があります。

[1]:
f = open('sample.txt', 'r')

変数 f には、ファイルを読み書きするためのデータが入ります。 これをファイルオブジェクトと呼びます。

'sample.txt' はファイル名で、そのファイルの絶対パス名か、このノートブックからの相対パス名を指定します。

ここでは、sample.txt という名前のファイルがこのノートブックと同じディレクトリにあることを想定しています。

たとえば、novel.txt というファイルが、ノートブックの1段上のディレクトリ(このディレクトリが入っているディレクトリ)にあるならば、'../novel.txt' と指定します。 ノートブックの1段上のディレクトリに置かれている data というディレクトリにあるならば、'../data/novel.txt' となります (4-3にもう少し詳しい解説があります)。

'r' はファイルをどのモードで開くかを指しており、'r'読み込みモードを意味します。 このモードで開いたファイルに書き込みすることはできません。

よく使われるモードは、次の3種類です。

引数 | モード

'r' | 読み込み 'w' | 書き込み 'a' | 追記

モードの引数がなかった場合は、'r' であると解釈されます。 書き込みについては後でも説明します。

モードの詳細は公式ドキュメントを参照。

ファイルのクローズ

ファイルオブジェクトを使い終わったら、原則として、close() メソッドを呼び出して、クローズする(閉じる)必要があります。

[2]:
f.close()

close() を呼び出さずに放置すると、そのファイルがまだ使用中だと認識されてしまいます。 これは、同じファイルを利用しようとする他のプログラムの働きを阻害します。(個室のトイレをイメージしてください。)

close() の呼び出しは重要ですが、忘れがちなものでもあります。 後述するwith文を使うのが安全です。

行の読み込み

ファイルオブジェクトには、readline() というメソッドを適用することができます。 ファイルから新たに1行を読んで文字列として返します。 この「1行」というのは、正確には、ファイルの先頭もしくは改行文字の次の文字から、ファイルの終わりもしくは改行文字までの文字列です。 1行は必ずしも改行文字で終わらないという点に注意して下さい。

ファイルの終わりに来たとき、readline()'' という空文字列を返します。

以下のようにして readline() を使ってファイルを行単位で読んでみましょう。

ファイルを読み終わると空文字列が返ることを確認してください。

[3]:
f = open('sample.txt', 'r')
[4]:
f.readline()
[4]:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n'
[5]:
f.readline()
[5]:
'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n'
[6]:
f.readline()
[6]:
'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n'
[7]:
f.readline()
[7]:
''
[8]:
f.close()

readline() メソッドの呼び出しは、ファイルオブジェクトを消費します。 改めて読み出したいときには、再度オープンして新しいオブジェクトを使ってください。

練習

文字列 name をファイル名とするファイルの最後の行を文字列として返す関数 last_line(name) を定義してください。

[9]:
def last_line(name):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[10]:
print(last_line('sample.txt')=="Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n")
False

ファイル全体の読み込み

ファイル全体を一括で読み込んで、1つの文字列を取得したいときには、read() メソッドを利用します。

[11]:
f = open('sample.txt', 'r')
f.read()
[11]:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n'

一度 read() を呼ぶと、ファイルの終端に達するので、それ以降は空文字列を返します。

[12]:
f.read()
[12]:
''
[13]:
f.close()

read() メソッドは、内部的には readline() メソッドを呼んでいます。 したがって、read() メソッドも同様にファイルオブジェクトを消費します。

練習

文字列 name をファイル名とするファイルをオープンして、 read() メソッドによってファイル全体を文字列として読み込み、 その文字数を返す関数 number_of_characters(name) を作成してください。

注意:return する前にファイルをクローズすることを忘れないようにしてください。

[14]:
def  number_of_characters(name):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[15]:
print(number_of_characters('sample.txt') == 446)
False

編集中のファイルの動作

プログラムでファイルを開くと、そのプログラム内でそのファイルを閉じるまでは、他のプログラムでそのファイルを編集することはできません。

下のセルを実行した後で、Windowsならエクスプローラ、macOSならFinderで上のファイルを探して、削除してみてください。 「ファイルを閉じてから再実行してください。(Windowsの場合)」といったメッセージが出て、削除ができないはずです。

[16]:
f = open('test.txt', 'r')

下のセルを実行した後だと削除できます。

[17]:
f.close()

ファイルに対するwith文

ファイルのオブジェクトは、with文に指定することができます。

with ファイルオブジェクト as 変数:
    ...

with の次には、open によってファイルをオープンする式を書きます。

また、as の次には、ファイルのオブジェクトが格納される変数を書きます。

with文は処理後にファイルのクローズを自動的にやってくれますので、 ファイルに対して close() を呼び出す必要がありません。

[18]:
with open('sample.txt', 'r') as f:
    print(f.read())
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

ファイルへの書き込み

ファイルへの書き込みは、print 関数を使って行えます。 file 引数に書き込み先のファイルオブジェクトを指定します。 file は3.3で説明されているキーワード引数と呼ばれる引数ですので、 以下のように file=... という形で指定します。

[19]:
with open('print-test.txt', 'w') as f:
    print('hello\nworld', file=f)

文字列の中の \n は改行文字を表します。\nエスケープシーケンス(2-1に説明があります)の一種です。 エスケープシーケンスには、この他に、復帰文字を表す \r やタブを表す \t などがあります。

ファイルの読み書きのモードとしては、書き込みモードを意味する 'w' を指定しています。既に同じ名前のファイルが存在する場合は上書きされます(以前の内容はなくなります)。ファイルがない場合は、新たに作成されます。

'a' を指定すると、ファイルが存在する場合、既存の内容の後に追記されます。ファイルがない場合は、新たに作成されます。

print 関数は、デフォルトで、与えられた文字列の末尾に改行文字を加えて印字します。 末尾に加える文字は、end 引数で指定できます。

[20]:
with open('print-test.txt', 'a') as f:
    print('hello', 'world\n', end='', file=f) # 改行文字を加えない

また、複数の印字対象を渡すと、デフォルトで、空白文字で区切って印字します。 この区切り文字は、sep 引数で指定できます。

[21]:
with open('print-test.txt', 'a') as f:
    print('hello', 'world', sep=', ', file=f) # 'hello, world'が印字される

この他にも、ファイルオブジェクトには、より原始的な書き込み用メソッドが用意されています。 write() メソッドは、与えられた1つの文字列を単に書き込みます。 次に示すように、write() メソッドと read() メソッドは、対で使うことが良くあります。

[22]:
with open('sample.txt') as src, open('sample.txt.bak', 'w') as dst:
    dst.write(src.read())

このコードは、sample.txtsample.txt.bak にコピーします。

練習

2つのファイル名 infile, outfile を引数として、infile の半角英文字を全て大文字にした結果を outfile に書き込む file_upper(infile, outfile) という関数を作成してください。

なお、半角英文字の小文字を大文字に変換するには upper() というメソッドが使えます。 たとえば line という名前の変数に半角文字列が入っている場合、line.upper() とすれば大文字に変換した文字列を返します。

[23]:
def file_upper(infile,outfile):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[24]:
with open('print-test.txt', 'w') as f:
    print('hello', 'world', file=f)
file_upper('print-test.txt', 'print-test-upper.txt')
with open('print-test-upper.txt', 'r') as f:
    print(f.read() == 'HELLO WORLD\n')
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[24], line 4
      2     print('hello', 'world', file=f)
      3 file_upper('print-test.txt', 'print-test-upper.txt')
----> 4 with open('print-test-upper.txt', 'r') as f:
      5     print(f.read() == 'HELLO WORLD\n')

File ~/Projects/utpython/lib/python3.12/site-packages/IPython/core/interactiveshell.py:324, in _modified_open(file, *args, **kwargs)
    317 if file in {0, 1, 2}:
    318     raise ValueError(
    319         f"IPython won't let you open fd={file} by default "
    320         "as it is likely to crash IPython. If you know what you are doing, "
    321         "you can use builtins' open."
    322     )
--> 324 return io_open(file, *args, **kwargs)

FileNotFoundError: [Errno 2] No such file or directory: 'print-test-upper.txt'

ファイルの読み書きにおける文字コード指定

open でファイルを開くと、通常そのファイルをテキストモードで開きます(テキストモード以外にバイナリモードもあります)。

テキストモードでファイルを開くときは、さらに特定の文字コードによってそのファイルを開こうとします。 文字コードを指定しないと、デフォルトの文字コードでそのファイルを開こうとしますが、 この文字コードがファイルを書き込む際に指定したものと異なる場合、エラーが出たり文字化けしてしまいます。

デフォルトの文字コードは、WindowsはShift_JIS、macOSやLinuxはUTF-8になっていることが多いです。 UTF-8で文字を記録されたファイルをWindowsで、ただ open('utf-8.txt', 'w') のように文字コードを指定せずに開くとエラーが出ます。 同じく、Shift_JISで文字を記録されたファイルをmacOSで open('shift_jis.txt', 'w') として開くとエラーが出ます。

なお、この教材の冒頭で open('sample.txt', 'r') と、文字コードを指定せずにファイルを開きましたがエラーは出ませんでしたね。 これは、sample.txt では半角英数字しか使われておらず、半角英数字に関しては、Shift_JISもUTF-8も共通のルールでエンコードされているためです。

[25]:
# macOSならこちらでエラー
with open('shift_jis.txt', 'r') as f:
    print(f.read())

# Windowsならこちらでエラー
with open('utf-8.txt', 'r') as f:
    print(f.read())
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
Cell In[25], line 3
      1 # macOSならこちらでエラー
      2 with open('shift_jis.txt', 'r') as f:
----> 3     print(f.read())
      5 # Windowsならこちらでエラー
      6 with open('utf-8.txt', 'r') as f:

File <frozen codecs>:322, in decode(self, input, final)

UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 0: invalid start byte

特に半角英数以外の文字を記録する際は文字コードを指定すること、またそのようなファイルを開くときは、記録するときに指定した文字コードでファイルを開いてください。

文字コードは、open のキーワード引数として encoding='utf-8'(文字コードにUTF-8を指定する場合)のように指定することができます。

なお、日本語の文字コードには UTF-8, Shift_JIS, EUC-JP などがありますが、PythonではOSの種類に限らず、UTF-8という文字コードがよく使われます。本授業でもUTF-8を推奨します。

[26]:
# 文字コードを指定しないとmacOSならこちらでエラー
with open('shift_jis.txt', 'r', encoding='shift_jis') as f:
    print(f.read())

# 文字コードを指定しないとWindowsならこちらでエラー
with open('utf-8.txt', 'r', encoding='utf-8') as f:
    print(f.read())

# 文字コードを指定してファイルに書き込む場合
with open('text.txt', 'w', encoding='utf-8') as f:
    f.write('かきくけこ')
with open('text.txt', 'r', encoding='utf-8') as f:
    print(f.read())
あいうえお
あいうえお
かきくけこ

改行文字の削除

ファイルをテキストモードで開いて read()readline() を呼び出すと、 str 型の文字列として読み込まれます。

文字列の末尾にある改行文字の削除には、2-1で紹介した rstrip メソッドが使えます。 ただし、無引数で呼び出すと、改行文字以外の空白文字もまとめて削除されます。

[27]:
'あいうえお \n'.rstrip()
[27]:
'あいうえお'

削除する空白文字を改行文字 '\n' に限定したい場合には、 rstrip の引数に指定します。

[28]:
'あいうえお \n\n'.rstrip('\n')
[28]:
'あいうえお '

上の例から分かるように、末尾の改行文字をただ1つ削除したい場合には、 rstrip('\n') は適していません。 しかし、 readline() の返す文字列には、末尾に高々1つの '\n' しか存在しないので、 rstrip('\n') で問題ありません。

[29]:
with open('text/novel.txt', 'r', encoding='utf-8') as f:
    while True:
        line = f.readline()
        if line == '':
            break
        print(line)

print('------ 末尾の改行文字を削除すると以下のようになります-------')
with open('text/novel.txt', 'r', encoding='utf-8') as f:
    while True:
        line = f.readline()
        if line == '':
            break
        print(line.rstrip('\n'))
二人の若い紳士が、すつかりイギリスの兵隊のかたちをして、ぴか/\する鉄砲をかついで、白熊のやうな犬を二疋つれて、だいぶ山奥の、木の葉のかさ/\したとこを、こんなことを云ひながら、あるいてをりました。

「ぜんたい、こゝらの山は怪しからんね。鳥も獣も一疋も居やがらん。なんでも構はないから、早くタンタアーンと、やつて見たいもんだなあ。」

「鹿の黄いろな横つ腹なんぞに、二三発お見舞まうしたら、ずゐぶん痛快だらうねえ。くる/\まはつて、それからどたつと倒れるだらうねえ。」

------ 末尾の改行文字を削除すると以下のようになります-------
二人の若い紳士が、すつかりイギリスの兵隊のかたちをして、ぴか/\する鉄砲をかついで、白熊のやうな犬を二疋つれて、だいぶ山奥の、木の葉のかさ/\したとこを、こんなことを云ひながら、あるいてをりました。
「ぜんたい、こゝらの山は怪しからんね。鳥も獣も一疋も居やがらん。なんでも構はないから、早くタンタアーンと、やつて見たいもんだなあ。」
「鹿の黄いろな横つ腹なんぞに、二三発お見舞まうしたら、ずゐぶん痛快だらうねえ。くる/\まはつて、それからどたつと倒れるだらうねえ。」

練習の解答

[30]:
def  number_of_characters(name):
    f = open(name, 'r')
    s = f.read()
    f.close()
    return len(s)
[31]:
def last_line(name):
    last = ''
    with open(name, 'r') as f:
        while True:
            line = f.readline()
            if line == '':
                return last
            last = line
[32]:
def file_upper(infile,outfile):
    with open(infile, 'r') as f:
        with open(outfile, 'w') as g:
            g.write(f.read().upper())

以下のように1つのwith文に複数の open を書くこともできます。

[33]:
def file_upper(infile,outfile):
    with open(infile, 'r') as f, open(outfile, 'w') as g:
        g.write(f.read().upper())
[ ]:

================================================ FILE: docs/4/4-2.html ================================================ 4-2. イテラブルとイテレータ — Pythonプログラミング入門 documentation

4-2. イテラブルとイテレータ

イテラブルとイテレータについて説明します。

参考

for文による繰り返しとファイルオブジェクト

ファイルオブジェクトは、for文の in の後に指定することができます。 このとき、ファイルから各行の文字列(改行文字を含む)を順次取り出します。

[1]:
lines = []
with open('sample.txt', 'r') as f:
    for line in f:
        lines.append(line)
lines
[1]:
['Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n',
 'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n',
 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n']

for文による行の取り出しは、readline メソッドと同様に、ファイルオブジェクトを消費します。

ファイルオブジェクト f をfor文で処理をすると、f が終端に到達するまで繰り返されます。 したがって、再度 f をfor文に与えても何も実行されません。

[2]:
with open('sample.txt', 'r') as f:
    print('---- 最初 ----')
    for line in f:
        print(line)
    print('---- もう一度 ----')
    for line in f:
        print(line)
---- 最初 ----
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

---- もう一度 ----

ファイルをfor文によって二度読みたい場合は、 もう一度ファイルをオープンして、ファイルのオブジェクトを新たに生成してください。

練習

文字列 name をファイル名とするファイルの最後の行を文字列として返す関数 last_line(name) を、 ファイルオブジェクトに対するfor文を用いて定義してください。

[3]:
def last_line(name):
    ...

定義ができたら、次のセルを実行して、エラーがでないことを確認してください。

[4]:
assert last_line('sample.txt') == 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n'
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[4], line 1
----> 1 assert last_line('sample.txt') == 'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n'

AssertionError:

for文とイテラブルとイテレータ

さて、3-2でも示したように、for文は、ファイルオブジェクトを含む様々なオブジェクトに対して繰り返す処理を記述できます (1-3で説明があったように、Pythonにおける値はオブジェクトと総称されます。)

for文によって繰り返すことができるオブジェクトのことを総称して、イテラブル (iterable) と呼びます。

for文が、様々なデータ型をイテラブルとして統一的に扱えるのは、繰り返して取り出す操作を表現するイテレータ (iterator) を経由するからです。

iterateは繰り返すという意味なので、itaratorは繰り返すもの(反復子とも呼ばれる)、iterableは繰り返すことができるもの、という意味です。

iter

組み込み関数 iter は、イテラブルからイテレータを作ります。たとえば、

[5]:
it = iter([0,1,2])

この it は、0 1 2 を順に取り出すイテレータです。

このとき、iter に渡されるオブジェクトの種類に応じて、適切なイテレータが構成されます。 この仕組みによって、様々なデータ型を統一的に扱えるわけです。

next

さて、iter が返したイテレータは、どのように使うのでしょうか。

組み込み関数 next は、イテレータに対して繰り返しを1回分先に進める操作を与えます。具体例を見ましょう。

[6]:
it = iter([0,1,2])
next(it)
[6]:
0
[7]:
next(it)
[7]:
1
[8]:
next(it)
[8]:
2

next(it) を呼び出す毎に、it から順に要素が取り出されています。

与えられたイテレータが繰り返しの終端に到達していたときには、StopIteration という例外(処理を緊急停止させる割り込み)が発生します。

[9]:
next(it)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In[9], line 1
----> 1 next(it)

StopIteration:

for文の仕組み

for文は、実は iter next StopIteration を使ったwhile文の形で表現できます。具体的には、

[10]:
for x in [0,1,2]:
    print(x)
0
1
2

このfor文は、次のwhile文と等価です。

[11]:
try:
    it = iter([0,1,2])
    while True:
        x = next(it)
        print(x)
except StopIteration:
    pass
0
1
2

このtry-except文は、発生した例外を捉えて、適切に処理するための構文です。 ここでは、発生した StopIteration を捉えて、何もせずに(pass)次に処理を進めるという意味になります。 結果として、コードセルの実行が成功裡に完了しています。 (例外とtry-except文の詳細は、公式チュートリアルを参照してください。)

イテレータは特殊なイテラブル

イテレータ自身も実はイテラブルです。したがって、イテレータをfor文で繰り返すことができます。

[12]:
it = iter([0,1,2])
for x in it:
    print(x)
0
1
2

しかし、単なるイテラブルではありません。1つのfor文で使い切りのイテラブルです。

[13]:
for x in it:
    print('これは実行されない')

これは、イテレータ it に対して iter を適用した時に、it 自体が返されるという仕組みによって実現されています。

[14]:
it = iter([0,1,2])
it is iter(it)
[14]:
True

この is は、2-2に説明がありますが、その両辺が同一オブジェクトかどうかを調べる演算子です。

最初のfor文の繰り返しによって終端に到達したイテレータ it は、その後の next(it) において StopIteration を発生させ続けます。 したがって、後続するfor文では、繰り返し処理に入ることなく即座に終了するわけです。 上に示したwhile文の形で考えると、わかりやすいでしょう。

練習

リストをもらって、そのイテレータを作り、最初の要素だけ取り出した後、 そのイテレータを返す関数 but_first(ls) を定義してください。

[15]:
def but_first(ls):
    ...

定義ができたら、次のセルを実行して、エラーがでないことを確認してください。

[16]:
it = but_first([0,2,4,6,8])
assert type(it) == type(iter([])) # type(it) では it は消費されない
assert list(it) == [2,4,6,8]
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Cell In[16], line 2
      1 it = but_first([0,2,4,6,8])
----> 2 assert type(it) == type(iter([])) # type(it) では it は消費されない
      3 assert list(it) == [2,4,6,8]

AssertionError:

ファイルオブジェクトはイテレータ

ファイルオブジェクトは readline メソッドによって、一行ずつ消費しながら、行の文字列を取り出せます。 そして、for文で末尾まで繰り返すと、for文で繰り返すことはもうできません。

ここまで読んだ方は既に気付いているでしょうが、ファイルオブジェクトはイテレータです。

[17]:
f = open('sample.txt', 'r')
[18]:
next(f)
[18]:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n'
[19]:
next(f)
[19]:
'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n'
[20]:
next(f)
[20]:
'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n'
[21]:
next(f)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In[21], line 1
----> 1 next(f)

StopIteration:

ファイルオブジェクト f に対する f.readline()next(f) の振舞いは、f が終端に到達していないときは同一です。 f が終端にあるときは、f.readline()'' を返しますが、next(f)StopIteration を発生させます。

[22]:
f.close()

イテラブルはイテレータではない

イテラブルは一般に、イテレータではありません。 具体的には、リスト・タプル・文字列・辞書はイテラブルですが、イテレータではありません。 3-2で紹介した range 関数の返す range オブジェクトも、イテラブルですがイテレータではありません。

したがって、next が適用可能ではなく、iter の適用によって毎回別のイテレータが返されます。 つまり、これまで見てきたように、複数のfor文で何度も繰り返す処理が実行できます。

[23]:
xs = [1,2,3]
for x in xs:
    print(x)
for x in xs:
    print(x)
1
2
3
1
2
3
[24]:
r = range(3)
for x in r:
    print(x)
for x in r:
    print(x)
0
1
2
0
1
2

イテレータを返す enumerate

3-2で紹介した組み込み関数の enumerate は、イテレータを返します。

[25]:
it = enumerate([10,20,30])
[26]:
next(it)
[26]:
(0, 10)
[27]:
for x in it:
    print(x)
(1, 20)
(2, 30)
[28]:
for i, c in enumerate('ACDB'):
    print(i, '番目の文字 =', c)
0 番目の文字 = A
1 番目の文字 = C
2 番目の文字 = D
3 番目の文字 = B

一方、enumerate はイテラブルを引数として受け取ります。上の例で、リストも文字列もイテラブルです。

イテレータもイテラブルなので、enumerate の引数になり得ます。 したがって、ファイルオブジェクトも、次のように enumerate に与えることができます。

[29]:
with open('sample.txt', 'r') as f:
    for i, s in enumerate(f):
        print(i, '行目:')
        print(s)
0 行目:
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

1 行目:
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

2 行目:
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

変数 i0 から順に増えていきます。変数 s には各行の文字列が代入されます。 i0 から始まりますが、各行の行番号と考えられます。

▲イテラブルとイテレータの定義

イテラブルとイテレータの形式的な定義をまとめます。

  • イテラブル:

    • iter を適用可能。 __iter__ メソッドを持つ。

  • イテレータ:

    • next を適用可能。 __next__ メソッドを持つ。

    • iter を適用したとき、引数のオブジェクトをそのまま返す。

iter(x)x.__iter__() と等価なので、iter を適用可能であることと、__iter__ メソッドを持つことは同義です。 同様に、next(x)x.__next__() と等価なので、 next を適用可能であることと、__next__ メソッドを持つことは同義です。

__iter__ メソッドと __next__ メソッドについては、6-3で改めて説明します。

練習の解答

[30]:
def last_line(name):
    with open(name, 'r', encoding='utf-8') as f:
        for line in f:
            pass
    return line
[31]:
def last_line(name):
    f = open(name, 'r', encoding='utf-8')
    for line in f:
        pass
    f.close()
    return line
[32]:
def but_first(ls):
    it = iter(ls)
    next(it)
    return it
[ ]:

================================================ FILE: docs/4/4-3.html ================================================ 4-3. ディレクトリと木構造 — Pythonプログラミング入門 documentation

4-3. ディレクトリと木構造

ディレクトリと木構造について説明します。 この内容はPythonというよりも、Windows・macOS・Linuxなどの一般的なOSに共通する概念です。 なお、Colaboratoryは、仮想マシン上のLinuxの上で動作しています。

ディレクトリと階層構造

OS上でのファイルは一般に、階層的に管理されています。 ファイルが置かれる場所のことを、ディレクトリと呼びます。 ファイルをまとめることから、フォルダとも呼ばれます。

zip版の教材を、IPP_textbook ディレクトリに展開すると、次のような階層構造になります。

IPP_textbook
├── 1
│   ├── 1-0.ipynb
│   ├── 1-1.ipynb
│   ├── 1-2.ipynb
│   ├── 1-3.ipynb
│   ├── 1-4.ipynb
│   ├── colab1.png
│   ├── colab2.png
│   ├── colab3.png
│   ├── colab4.png
│   └── colaboratory.png
├── 2
│   ├── 2-1.ipynb
│   ├── 2-2.ipynb
│   └── 2-3.ipynb
├── 3
│   ├── 3-1.ipynb
│   ├── 3-2.ipynb
│   └── 3-3.ipynb
├── 4
│   ├── 4-1.ipynb
│   ├── 4-2.ipynb
│   ├── 4-3.ipynb
│   ├── sample.txt
│   ├── shift_jis.txt
│   ├── test.txt
│   ├── text
│   │   └── novel.txt
│   └── utf-8.txt
├── 5
│   ├── 5-1.ipynb
│   ├── 5-2.ipynb
│   ├── 5-3.ipynb
│   ├── factorial.py
│   └── fig
│       ├── py_conv_1.png
│       ├── py_conv_2.png
│       ├── py_open_1.png
│       └── py_open_2.png
├── 6
│   ├── 6-1.ipynb
│   ├── 6-2.ipynb
│   ├── 6-3.ipynb
│   └── jugemu.txt
├── 7
│   ├── 7-1.ipynb
│   ├── 7-2.ipynb
│   └── iris.csv
├── appendix
│   ├── 1-jupyter-notebook.ipynb
│   ├── 2-set.ipynb
│   ├── 3-recursion.ipynb
│   ├── 3-visualization.ipynb
│   ├── 4-csv.ipynb
│   ├── 5-bokeh.ipynb
│   ├── 5-command.ipynb
│   ├── 5-matplotlib.ipynb
│   ├── 5-re.ipynb
│   ├── argsprint.py
│   ├── B1S.xml
│   ├── fig
│   │   ├── argsprint.png
│   │   ├── console_in_browser.png
│   │   ├── py_conv_1.png
│   │   ├── py_conv_2.png
│   │   ├── py_open_1.png
│   │   ├── py_open_2.png
│   │   ├── sample_py_browser.png
│   │   ├── sample_py_mac_1.png
│   │   ├── sample_py_mac_2.png
│   │   ├── sample_py_mac_3.png
│   │   ├── sample_py_win_1.png
│   │   ├── sample_py_win2_1.png
│   │   ├── sample_py_win2_2.png
│   │   ├── sample_py_win2_3.png
│   │   ├── sample_py_win_2.png
│   │   ├── sample_py_win_3.png
│   │   └── terminal_in_menu.png
│   ├── sample.py
│   ├── small.csv
│   ├── text-sample.txt
│   ├── tokyo-july-temps.csv
│   └── tokyo-temps.csv
├── index.ipynb
├── index_of_terms.ipynb
└── LICENSE

ここで、末端にあるものがファイルであり、末端以外にあるものがディレクトリ(フォルダ)です。

カレントワーキングディレクトリ

プログラムは、必ずどこかのディレクトリで動いています。 このプログラムが動作しているディレクトリのことを、ワーキングディレクトリ(もしくは作業ディレクトリ)と呼びます。 通例、特にWindowsやmacOSでは、何らかのファイルをクリックしてアプリケーションが起動したとき、その開いたファイルのある場所がワーキングディレクトリになります。

ワーキングディレクトリは、プログラムの実行中に変更できます。 Python上では os.chdir を使うことで変更できます。

プログラム実行中の現在のワーキングディレクトリのことを、カレントワーキングディレクトリ、もしくは単にカレントディレクトリと呼びます。 カレントディレクトリは頻繁に利用するので、 . という特別な記号によって表現できます。

パス

カレントディレクトリに置かれているファイルは、ファイル名を指定するだけで開くことができます。 だから、4-1で示したように、カレントディレクトリにある sample.txt は、ファイル名を指定するだけで開けます。

[1]:
open('sample.txt', 'r', encoding='utf-8')
[1]:
<_io.TextIOWrapper name='sample.txt' mode='r' encoding='utf-8'>

一方、それ以外の場所にあるファイルについては、そのファイルのディレクトリまで含めて指定しなければ、開くことができません。

[2]:
open('novel.txt', 'r')
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
Cell In[2], line 1
----> 1 open('novel.txt', 'r')

File ~/Projects/utpython/lib/python3.12/site-packages/IPython/core/interactiveshell.py:324, in _modified_open(file, *args, **kwargs)
    317 if file in {0, 1, 2}:
    318     raise ValueError(
    319         f"IPython won't let you open fd={file} by default "
    320         "as it is likely to crash IPython. If you know what you are doing, "
    321         "you can use builtins' open."
    322     )
--> 324 return io_open(file, *args, **kwargs)

FileNotFoundError: [Errno 2] No such file or directory: 'novel.txt'

カレントディレクトリに存在しない novel.txt を開こうとしたので FileNotFoundError が生じました。 novel.txt は、text というディレクトリの中にあるので、それ明示するために、/ で区切って、次のように指定します。

[3]:
open('text/novel.txt', 'r', encoding='utf-8')
[3]:
<_io.TextIOWrapper name='text/novel.txt' mode='r' encoding='utf-8'>

実は、カレントディレクトリにあるファイルが、ファイル名の指定だけで開けるのは、自動的に ./ が補われていたからでした。

open の第1引数に渡す文字列ような、ファイルやディレクトリの場所を指定する表記を、パスと呼びます。 パス(経路)と呼ぶのは、/ 区切りで1歩ずつ次に進むディレクトリを指定することに由来しています。

パスを記述する際、ルートディレクトリは / で表されます。 ルートディレクトリから始まるパスを、絶対パスと呼びます。 一方、カレントディレクトリからのパスを、相対パスと呼びます。 パス表記において / 以外から始まる場合は、自動的に先頭に ./ が補われて、相対パスとして扱われます。

さて、./text/ というパス表記は、カレントディレクトリにある一段下の text ディレクトリに進むことに対応します。 これに、一段上のディレクトリを表す .. を組み合わせることで、より柔軟にパスを指定できます。

たとえば、./text/.././ と同じディレクトリを指します。

[4]:
with open('sample.txt', 'r', encoding='utf-8') as f:
    print(f.read(), end='')
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
[5]:
with open('./text/../sample.txt', 'r', encoding='utf-8') as f:
    print(f.read(), end='')
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

また、カレントディレクトリを ./text/ に変化させた後に、sample.txt を開くときには、../sample.txt と指定することができます。

[6]:
import os
os.chdir('./text') # 1段下の text に行く
with open('../sample.txt', 'r', encoding='utf-8') as f:
    print(f.read())
os.chdir('..') # 元のディレクトリに戻る
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

木構造

ディレクトリの階層構造は、木を逆さにしたような形になっています。 このことから、木構造もしくは単に(tree)と呼ばれます。

木構造の観点で、最上位の階層は(root)と呼ばれ、末端は(leaf)と呼ばれます。 木構造を成す要素(ここではファイルやディレクトリ)は,一般にノード(node)と呼ばれます。

階層構造における包含関係は、木構造では親子関係と呼ばれます。 たとえば、教材のディレクトリ階層においては、ディレクトリ IPP_textbook の中に、ディレクトリ 1 とファイル LICENSE が含まれています。 木構造の観点で、IPP_textbook1LICENSE(parent)と呼ばれ、逆に 1LICENSEIPP_textbook(child)と呼ばれます。 また、1LICENSE のような共通の親を持つノード集合は、兄弟(sibling)と呼ばれます。 親子関係の推移閉包として、祖先(ancestor)や子孫(descendant)も定義されます。

データ表現としての木構造

OSのディレクトリ構造に限らず、木構造はデータ表現として広く用いられます。 Pythonにおいても、入れ子のデータ構造は、木構造と見做せます。

たとえば、教材のディレクトリ構造を、辞書の入れ子で表現すると、次のようになります.

IPP_textbook = {
  '1': {'1-0.ipynb': Data('1-0.ipynb'),
        ...,
        'colaboratory.png', Data('colaboratory.png')},
  '2': {'2-1.ipynb': Data('2-1.ipynb'),
        '2-1.ipynb': Data('2-2.ipynb'),
        '2-3.ipynb': Data('2-3.ipynb')},
  ...
  '5': {'5-1.ipynb': Data('5-1.ipynb'),
        '5-1.ipynb': Data('5-2.ipynb'),
        '5-3.ipynb': Data('5-3.ipynb'),
        'factorial.py', Data('factorial.py'),
        'fig': {'py_conv_1.png': Data('py_conv_1.png'),
                'py_conv_2.png': Data('py_conv_2.png'),
                'py_open_1.png': Data('py_open_1.png'),
                'py_open_2.png': Data('py_open_2.png')}
       },
   ...
}

ここで Data(...) は、... のファイルデータを意味しています。

このデータ表現では、パス IPP_textbook/2/2-2.ipynb へのアクセスが、IPP_textbook['2']['2-2.ipynb'] と表現されます。

データを階層的に管理する際は、データ全体を木構造として捉えて表現することを考えましょう。

[ ]:

================================================ FILE: docs/5/5-1.html ================================================ 5-1. モジュールの使い方 — Pythonプログラミング入門 documentation

5-1. モジュールの使い方

モジュールの使い方について説明します。

参考

モジュールのインポート

Pythonでは特別な関数や値をまとめたもの(これをモジュールといいます)を使うために、import という文を使います(第1回 (1-1) においても説明しました)。具体的には次のように記述します。

import モジュール名

たとえば、数学関係の機能をまとめた math というモジュールがあります。これらの関数や値を使いたいときは、以下のようにして math モジュールを importインポートします。そうすると、math.関数名 という形で関数を用いることができます。

[1]:
import math# importは大抵セルの一番上に記述します
print(math.sqrt(2)) # sqrt は平方根を計算する関数
print(math.pi) # πの値
print(math.sin(math.pi/4)) # sin関数
print(math.cos(0)) # cos関数
print(math.log(32,2)) # 2を底とする32の対数(texで記述すると、$\log_2 32$)
1.4142135623730951
3.141592653589793
0.7071067811865475
1.0
5.0

上の例では、math モジュールの中の関数や値を使用しています。

注意しなければならないのは、モジュールの中の関数を使う場合には、

モジュール名.モジュールの中の関数名

とする必要があるということです。

モジュールの中の値(たとえば math.pi)も同様です。

なお、複数の関数名をコンマ , で区切って並べて同時にインポートすることもできます。

from

モジュール内で定義されている関数を「モジュールの中の関数名」のようにして、「モジュール名.」を付けずにそのままの名前で、モジュールの読み込み元のプログラムで使いたい場合には、from を以下のように書くことで利用することができます。

from モジュール名 import モジュールの中の関数名

たとえば、次のようになります。

[2]:
from math import sqrt
print(sqrt(2)) # sqrt は平方根を計算する関数
from math import pi
print(pi) # πの値
from math import sin
print(sin(math.pi/4)) # sin関数
from math import cos
print(cos(0)) # cos関数
from math import log
print(log(32,2)) # 2を底とする32の対数(texで記述すると、$\log_2 32$)
1.4142135623730951
3.141592653589793
0.7071067811865475
1.0
5.0

この方法では、関数ごとに from を用いてインポートする必要があります。

なお、関数だけではなく、グローバル変数や後に学習するクラスも、 このようにしてインポートすることができます。

別の方法として、ワイルドカード * を利用する方法もあります。

from math import *

この方法ではアンダースコア _ で始まるものを除いた全ての名前が読み込まれるため、明示的に名前を指定する必要はありません。

[3]:
from math import *
print(factorial(5)) # 5 の階乗 # import mathを使う場合、math.factorial(5)
print(floor(2.31)) # 2.31以下の最大の整数  # import mathを使う場合、math.floor(2.31)
print(e) # ネイピア数 # import mathを使う場合、math.e
120
2
2.718281828459045

ただしこの方法は推奨されていません。理由は読み込んだモジュール内の未知の名前とプログラム内の名前が衝突する可能性があるためです。

[4]:
pi = 'パイ' # piという変数に文字列「パイ」を代入する
print(pi)
from math import *
print(pi) # mathモジュールのpiの値で上書きされる(衝突)
パイ
3.141592653589793

as

モジュール名が長すぎるなどの理由から別の名前としたい場合は、as を利用する方法もあります。 たとえば、5-3において学習するNumPyというライブラリは numpy モジュールとして提供されていますが、 次のように、 numpynp という略称で使うことがあります。

[5]:
import numpy
print(numpy.ones((3, 5))) # 3×5の行列を表示
import numpy as np
print(np.ones((3, 5))) # np という短い名称で同じ関数を利用する
[[1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1.]]
[[1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1.]
 [1. 1. 1. 1. 1.]]

個々の関数ごとに別の名前を付けることもできます。

[6]:
import math
print(math.factorial(5)) # 階乗を求める関数factorial # 5の階乗
from math import factorial as fact # fact という名前でmath.factorialを使用したい
print(fact(5))
120
120

練習

第1回では、数学関数を以下のようにインポートし、math.sqrt() のようにして、数学関数や数学関係の変数を利用していました。

import math
print(math.sqrt(2))
print(math.sin(math.pi))

以下のセルを、モジュール名を付けないでこれらの関数や変数を参照できるように変更してください。

[7]:
import ...
...

print(sqrt(2))
print(sin(pi))
  Cell In[7], line 1
    import ...
           ^
SyntaxError: invalid syntax

練習の解答

from を使ってモジュールを指定、参照する関数を import でインポートしてください。

[8]:
from math import sqrt, sin, pi
print(sqrt(2))
print(sin(pi))
1.4142135623730951
1.2246467991473532e-16
================================================ FILE: docs/5/5-2.html ================================================ 5-2. モジュールの作り方 — Pythonプログラミング入門 documentation

5-2. モジュールの作り方

モジュールの作り方について説明します。

参考

Pythonではプログラムをモジュールという単位で、複数のファイルに分割することができます。 通例、一度定義した便利な関数などを別のプログラムで再利用するときには、再利用される部分をモジュールとして切り出します。 プログラムが大きくなると、このように複数のファイルに分割した方が開発や保守が簡単になります。

モジュールファイル

本授業で扱ってきたノートブックファイル(拡張子 .ipynb)は、コードセル(Codeセル)にPythonソースコード、Markdownセルに文書を持ち、内部的に出力結果も保存しています。 一方、モジュールファイル(拡張子 .py)は、Pythonソースコードのみを含んだファイルです。

モジュールファイルを作るときには、Jupyter Notebook におけるコードセルの内容のみをファイルに記述することになります。

モジュールファイルの文字コードはUTF-8であることが公式に推奨されています。 原則としてUTF-8でエンコードして保存してください。

ノートブックファイルをモジュールファイルに変換する

本授業で利用しているノートブックファイルを .py としてセーブするには、 「ファイル」メニューの「.py をダウンロード」項目を選択します。

そうすると、コードセルだけがプログラム行として有効になり、その他の行はコメントアウトされたモジュールファイルがダウンロードできます。 ダウンロード先はブラウザによって定まりますが、ダウンロードフォルダになることが一般的でしょう。

この方法では、全てのコードセルの内容を一度に実行するプログラムとして保存されます。 ノートブックのようにセル単位の実行するわけではないことに注意する必要があります。

モジュールファイルをアップロードする

次に、ダウンロードしたモジュールファイルをColaboratoryで使うには、 Colaboratoryの実行環境の中のファイルシステムのカレントディレクトリに モジュールファイルをアップロードする必要があります。 このためには、以下のセルを実行してください。

[1]:
import sys
if 'google.colab' in sys.modules:
    from google.colab import files
    uploaded = files.upload() # Upload to the current directory

自作モジュールの使い方

モジュールで定義されている関数を利用するには、import を用いて import モジュール名 と書きます。 モジュール名は、モジュールファイル名から拡張子 .py を除いたものです。

すると、モジュールで定義されている関数は モジュール名.関数名 によって参照できます。

次の関数が記述された factorial.py というモジュールを読み込む場合を説明します。 ただし、読み込み元と同じディレクトリに factorial.py が存在すると仮定します。

factorial.py:

# 階乗n!を返す
def fact(n):
    prod = 1
    for i in range(1, n + 1):
        prod *= i
    return prod
[2]:
import factorial

factorial.fact(6)
[2]:
720

fromas の使い方も既存のモジュールと全く同じです。

モジュール内で定義されている名前を読み込み元のプログラムでそのまま使いたい場合は、from を用いて以下のように書くことができます。

[3]:
from factorial import fact

fact(6)
[3]:
720

ワイルドカード * を利用する方法もありますが、推奨されていません。 読み込まれるモジュール内の未知の名前と、読み込み元のプログラム中の名前が衝突する可能性があるためです。

[4]:
from factorial import *

モジュール名が長すぎるなどの理由から別の名前としたい場合は、as を利用する方法もあります。

[5]:
import factorial as f

f.fact(6)
[5]:
720
================================================ FILE: docs/5/5-3.html ================================================ 5-3. NumPyライブラリ — Pythonプログラミング入門 documentation

5-3. NumPyライブラリ

NumPyについて説明します。

参考

NumPyとは、多次元配列を効率的に扱うライブラリです。 Pythonの標準ライブラリではありませんが、科学技術計算や機械学習など、ベクトルや行列の演算が多用される分野では、事実上の標準ライブラリとしての地位を確立しています。

NumPyを用いるには、まず、numpy モジュールをインポートする必要があります。 慣習として、np と別名をつけて利用されます。

[1]:
import numpy as np

NumPyでは、Python標準の数値やリストの代わりに、特別な数値や配列を用いることで、格段に効率的な配列演算を実現します。 以下では、配列の基本的な操作や機能を説明します。

配列の構築

配列とは、特定の型の値の並びです。 numpy.array() 関数で構築できます。 このとき、配列の要素はPython標準のリストやタプルで指定します。 どちらを用いて作成しても全く同じ配列を作成できます。

[2]:
a = np.array([1,2,3]) # リストから配列作成
print(a)
b = np.array((1,2,3)) # タプルからの配列作成
print(b)
[1 2 3]
[1 2 3]

print の結果はリストと似ていますが、要素が , ではなく空白で区切られているに注意してください。 print ではなく、式の評価結果の場合、より違いが明示されます。

[3]:
a
[3]:
array([1, 2, 3])

配列は numpy.ndarray というデータ型によって実現されています。 組み込み関数 type() を使うと、データ型を調べられます。

[4]:
type(np.array([1,2,3,4,5])) # 配列の型
[4]:
numpy.ndarray
[5]:
type([1,2,3,4,5])
[5]:
list

array() が、リストではなく ndarray を返していることがわかります。

要素型

配列の要素を構成する値には幾つかの型がありますが、次の4つの型を知っていればとりあえずは十分です。

型名

説明

numpy.int32

整数(32-bit)を表す型

numpy.float64

実数(64-bit)を表す型

numpy.complex128

複素数(64-bit実数の組)を表す型

numpy.bool_

真理値を表す型

配列は、リストと異なり、型の異なる要素を混在させることはできません。

array()dtype 引数に、要素型を表すオブジェクトや文字列値を与えることで、指定された要素型の配列を構築できます。

[6]:
print(np.array([-1,0,1], dtype=np.int32)) # np.int32の代わりに'int32'でも同じ
[-1  0  1]

実数には、小数点が付与されて印字されます。

[7]:
print(np.array([-1,0,1], dtype=np.float64)) # np.float64の代わりに'float64'でも同じ
[-1.  0.  1.]

複素数は実部と虚部を表す実数の組であり、虚部には j が付与されて印字されます。

[8]:
print(np.array([-1,0,1], dtype=np.complex128)) # np.complex128の代わりに'complex128'でも同じ
[-1.+0.j  0.+0.j  1.+0.j]

数値から真理値への変換では、0False で、0 以外が True になります。

[9]:
print(np.array([-1,0,1], dtype=np.bool_)) # np.bool_の代わりに'bool'でも同じ
[ True False  True]

多次元配列

多次元配列は、配列の中に配列がある入れ子の配列です。 入れ子のリストやタプルを numpy.array() に渡すことで構築できます。

[10]:
print(np.array([[1,2],[3,4]])) # 2次元配列の構築
[[1 2]
 [3 4]]
[11]:
print(np.array([[[1,2],[3,4]],[[5,6],[7,8]]])) # 3次元配列の構築
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]

上の例からわかるように、2次元配列は行列のように、3次元配列は行列の配列のように印字されます。

多次元配列は、要素となる配列の長さが等しいことが想定されます。 つまり、2次元配列は、行列のように各行の長さが等しくなければなりません。

[12]:
print(np.array([[1,2],[3]])) # 行の長さが異なる場合
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[12], line 1
----> 1 print(np.array([[1,2],[3]])) # 行の長さが異なる場合

ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2,) + inhomogeneous part.

このように行の長さが異なる場合は、多次元配列とは見做されません。

多次元配列の各次元の長さの組を、多次元配列の (shape) と呼びます。 特に2次元配列の場合、行列と同様に、行数(内側にある配列の数)と列数(内側にある配列の要素数)の組を使って、行数×列数で形を表記します。

1次元配列に対して reshape() メソッドを使うと、引数で指定された形の多次元配列に変換することができます。

[13]:
a1 = np.array([0, 1, 2, 3, 4, 5]) # 1次元配列
a2 = a1.reshape(2,3)              # 2×3の2次元配列
a2
[13]:
array([[0, 1, 2],
       [3, 4, 5]])

ここで、reshape() を適用する前後の配列(ここでは a1a2)は、内部的にデータを共有していることに注意してください。 つまり、a1 の要素を更新すると、a2 にも影響を及ぼします。

[14]:
a1[1] = 6
print(a1)
print(a2)
[0 6 2 3 4 5]
[[0 6 2]
 [3 4 5]]

ravel() メソッドを使うと、多次元配列を1次元配列に戻すことができます。

[15]:
a = np.array([0, 1, 2, 3, 4, 5]).reshape(2,3)
print(a)
print(a.ravel())
[[0 1 2]
 [3 4 5]]
[0 1 2 3 4 5]

ravel() の結果も、reshape() と同様に、元の配列と要素を共有します。

[16]:
elems = np.array([0, 1, 2, 3, 4, 5])
a = elems.reshape(2,3).ravel() # ravel()は要素をelemsと共有
elems[1] = 6
print(a)
[0 6 2 3 4 5]

なお、要素をコピーして変換する flatten() メソッドもありますが、コピーしない ravel() の方が効率的です。

配列のデータ属性

配列はオブジェクトであり、その配列に関する様々な情報を属性として保持します。 (オブジェクトの属性については6-3に簡単な説明があります。) 配列が持つ代表的なデータ属性(メソッド以外の属性)を次の表にまとめます。

属性

意味

a.dtype

配列 a の要素型

a.shape

配列 a の形(各次元の長さのタプル)

a.ndim

配列 a の次元数(len(a.shape) と等しい)

a.size

配列 a の要素数(a.shape の総乗と等しい)

a.flat

配列 a の1次元表現(a.ravel() と等しい)

a.T

配列 a を転置した配列(a と要素を共有)

配列要素を生成する構築関数

要素を生成して配列を構築する代表的な関数を紹介します。 特に断りが無い場合、ここで紹介する関数は、array() と同様に dtype 引数で要素型を指定可能です。

arange

numpy.arange() は、組み込み関数 range() の配列版です(arange は array range の略)。 開始値・終了値・刻み幅を引数にとります。 デフォルトの開始値は 0、刻み幅は 1 です。 range() と違って、引数の値は整数に限定されません。

[17]:
print(np.arange(3)) # range(3)に対応する配列
print(np.arange(0, 1, 0.2)) # 0を開始値として0.2刻みで1未満の要素を生成
[0 1 2]
[0.  0.2 0.4 0.6 0.8]

linspace

numpy.linspace() 関数は、範囲を等分割した値からなる配列を生成します。 第1引数と第2引数には、それぞれ範囲の開始値と終了値、第3引数には分割数を指定します。

[18]:
print(np.linspace(0, 1, 4)) # 0から1の値を4分割した値を要素に持つ配列
[0.         0.33333333 0.66666667 1.        ]

zerosones

numpy.zeros() 関数は、0 からなる配列を生成します。 同様に、numpy.ones() 関数は、1 からなる配列を生成します。 どちらも、生成される形を第1引数に取ります。 デフォルトの要素型は、実数です。

[19]:
print(np.zeros(4))     # 長さ4の1次元配列
print(np.zeros((2,3))) # 2×3の2次元配列を生成
print(np.ones(4))     # 長さ4の1次元配列
print(np.ones((2,3))) # 2×3の2次元配列を生成
[0. 0. 0. 0.]
[[0. 0. 0.]
 [0. 0. 0.]]
[1. 1. 1. 1.]
[[1. 1. 1.]
 [1. 1. 1.]]

random.rand

numpy.random.rand() 関数は、0 以上 1 未満の乱数からなる配列を生成します。 引数には生成される配列の形を指定します。 要素型は実数に限定されます。

[20]:
print(np.random.rand(4))   # 長さ4の1次元配列
print(np.random.rand(2,3)) # 2×3の2次元配列を生成
[0.29417678 0.7695593  0.31245091 0.06876472]
[[0.82617042 0.8323276  0.42266024]
 [0.54479955 0.17532302 0.09897153]]

この他にも、numpy.random.randn()numpy.random.binomial()numpy.random.poisson() は、それぞれ、正規分布・二項分布・ポアソン分布の乱数からなる配列を生成します。

練習

引数に整数 \(n\) を取り、\(i\) から始まる連番の整数からなる配列を\(i\)番目 (\(i\ge 0\)) の行として持つ \(n\times n\) の2次元配列を返す関数 range_square_matrix() を、arange() を用いて定義してください。

たとえば、range_square_matrix(3) は、

[[0 1 2]
 [1 2 3]
 [2 3 4]]

と印字されるような2次元配列を返します。

[21]:
def arange_square_matrix(n):
    ...

以下のセルを実行して、True が表示されることを確認してください。

[22]:
print(all(map(all,(arange_square_matrix(3) == np.array([[0,1,2],[1,2,3],[2,3,4]])))))
False

配列要素の操作

インデックスアクセス

配列の要素には、リストの場合と同様に、0 から始まるインデックスを使って参照できます。 リストと同じく、配列の先頭要素のインデックスは 0、最後の要素のインデックスは -1 となります。

[23]:
a = np.arange(3)
print(a)
[0 1 2]
[24]:
a[0]
[24]:
np.int64(0)
[25]:
a[-1]
[25]:
np.int64(2)
[26]:
a[-1] = 3 # 要素への代入もできる
print(a)
[0 1 3]

多次元配列では、高次元(入れ子の外側)から順にインデックスを指定します。 特に2次元配列、すなわち行列の場合は、行インデックスと列インデックスを順に指定します。

[27]:
a = np.arange(6).reshape(2,3)
print(a)
[[0 1 2]
 [3 4 5]]
[28]:
a[1,2] # 行と列のインデックスをまとめて指定
[28]:
np.int64(5)
[29]:
a[1,2] = 6 # 要素への代入もできる
print(a)
[[0 1 2]
 [3 4 6]]

スライス

リストと同様に、配列のスライスを構築できます。

[30]:
a = np.arange(5)
print(a)
print(a[1:4])
print(a[1:])
print(a[:-2])
print(a[::2])
print(a[::-1])
[0 1 2 3 4]
[1 2 3]
[1 2 3 4]
[0 1 2]
[0 2 4]
[4 3 2 1 0]

配列のスライスに対して代入すると、右辺の値がコピーされて、スライス元の配列にまとめて代入されます。

[31]:
a = np.arange(5)
print(a)
a[1:4] = 6
print(a)
a = np.arange(5)
a[::2] = 6
print(a)
[0 1 2 3 4]
[0 6 6 6 4]
[6 1 6 3 6]

一方、リストに対しては、以下はエラーになります。

[32]:
a = [0,1,2,3,4]
print(a)
a[1:4] = 6
[0, 1, 2, 3, 4]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[32], line 3
      1 a = [0,1,2,3,4]
      2 print(a)
----> 3 a[1:4] = 6

TypeError: can only assign an iterable
[33]:
a = [0,1,2,3,4]
print(a)
a[1:4] = [6]
print(a)
[0, 1, 2, 3, 4]
[0, 6, 4]

このように、配列のスライスに対する代入の振舞いは、リストの場合と異なることに注意してください。

多次元配列に対しては、インデックスの参照と同様に、高い次元のスライスから順に並べて指定します。

[34]:
a = np.arange(9).reshape(3,3)
print(a)
print(a[:2,:2])
print(a[1:,1:])
[[0 1 2]
 [3 4 5]
 [6 7 8]]
[[0 1]
 [3 4]]
[[4 5]
 [7 8]]

多次元配列に対するスライスは、入れ子リストに対するスライスとは意味が異なることに注意してください。

for文

リストと同様に、for文を用いて、配列要素への反復処理を記述できます。

[35]:
for v in np.arange(3):
    print(v)
0
1
2

多次元配列の場合は、最外の配列に対して反復します。 つまり、2次元配列の場合、行の配列に対する反復処理となります。

[36]:
for row in np.arange(6).reshape(2,3):
    print(row)
[0 1 2]
[3 4 5]

for文と併用される enumerate() の多次元配列版として、numpy.ndenumerate() 関数が提供されています。 numpy.ndenumerate() は、(多次元)インデックスと要素の組を列挙します。

[37]:
for idx, e in np.ndenumerate(np.arange(6).reshape(2,3)):
    print(idx, e)
(0, 0) 0
(0, 1) 1
(0, 2) 2
(1, 0) 3
(1, 1) 4
(1, 2) 5
[38]:
for idx, e in np.ndenumerate(np.arange(3)):
    print(idx, e)
(0,) 0
(1,) 1
(2,) 2

要素毎の演算

配列に対する要素毎の演算は、簡潔に記述できます。 しかも、for文で記述するより、効率がよいです。 要素毎の演算を上手く使えるかどうかが、NumPyプログラミングの肝と言っても過言ではないでしょう。

配列のスカラ演算

配列とスカラとの算術演算を記述すると、要素毎のスカラ演算となります。 演算結果として、新しい配列が返ります。

[39]:
a = np.arange(4)
print(a)

print(a + 1) # 各要素に1を加算
print(a - 1) # 各要素に1を減算
print(a * 2) # 各要素に2を乗算
print(a / 2) # 各要素を2で除算
print(a // 2) # 各要素を2で整数除算
print(a % 2) # 各要素に2の剰余演算
print(a ** 2) # 各要素を2乗

print(1 + a) # 左側がスカラでもよい
print(1 - a) # 左側がスカラでもよい
print(2 * a) # 左側がスカラでもよい
b = a + 1
print(1 / b) # 左側がスカラでもよい
print(9 // b) # 左側がスカラでもよい
[0 1 2 3]
[1 2 3 4]
[-1  0  1  2]
[0 2 4 6]
[0.  0.5 1.  1.5]
[0 0 1 1]
[0 1 0 1]
[0 1 4 9]
[1 2 3 4]
[ 1  0 -1 -2]
[0 2 4 6]
[1.         0.5        0.33333333 0.25      ]
[9 4 3 2]

配列同士の演算

形が同じ配列同士の算術演算は、同じ位置の要素同士の演算となります。 演算結果として、新しい配列が返ります。

[40]:
a = np.arange(4).reshape(2,2)
b = np.arange(1,5).reshape(2,2)
print(a)
print(b)
print(a + b)
print(a - b)
print(a * b)
print(a / b)
c = 3 * a
print(c // b)
print(a % b)
print(a ** b)
[[0 1]
 [2 3]]
[[1 2]
 [3 4]]
[[1 3]
 [5 7]]
[[-1 -1]
 [-1 -1]]
[[ 0  2]
 [ 6 12]]
[[0.         0.5       ]
 [0.66666667 0.75      ]]
[[0 1]
 [2 2]]
[[0 1]
 [2 3]]
[[ 0  1]
 [ 8 81]]

実は、形が同じでない配列同士の算術演算も可能ですが、振舞いが複雑なので間違いやすいです。 配列同士の算術演算は、形が同じ配列に限定する方が賢明です。

ユニバーサル関数

NumPyにはユニバーサル関数と呼ばれる、任意の形の配列を取り、各要素に所定の演算を与えた結果を返す関数があります。 その代表例は、numpy.sqrt() 関数です。

[41]:
a = np.zeros(3) + 2
print(a)
print(np.sqrt(a)) # 各要素はsqrt(2)
b = np.zeros((2,2)) + 2
print(np.sqrt(b)) # 各要素はsqrt(2)
print(np.sqrt(2)) # スカラ(0次元配列)も扱える
[2. 2. 2.]
[1.41421356 1.41421356 1.41421356]
[[1.41421356 1.41421356]
 [1.41421356 1.41421356]]
1.4142135623730951

この他にも、多数のユニバーサル関数が提供されています。 詳しくは、ユニバーサル関数の一覧を参照してください。

よく使われる配列操作

dot

numpy.dot() は、2つの配列を引数に取り、そのドット積を返します。 両者が1次元配列のときは、ベクトル内積と等しいです。

[42]:
np.dot(np.arange(4), np.arange(1,5)) # 0*1 + 1*2 + 2*3 + 3*4
[42]:
np.int64(20)

2次元配列同士だと、行列乗算と等しいです。

[43]:
# [[0 1]     [[1 2]
#  [2 3]] と  [3 4]] の行列積
print(np.dot(np.arange(4).reshape(2,2), np.arange(1,5).reshape(2,2)))
[[ 3  4]
 [11 16]]

sort

numpy.sort() 関数は、昇順でソートされた新しい配列を返します。 これは、組み込み関数 sorted() の配列版です。

[44]:
a = np.array([3, 4, -1, 0, 2])
print(a)
print(np.sort(a))
[ 3  4 -1  0  2]
[-1  0  2  3  4]

一方、配列の sort() メソッドは、配列を破壊的に(インプレースで)ソートします。 これは、リストの sort() メソッドの配列版です。

[45]:
a = np.array([3, 4, -1, 0, 2])
print(a)
a.sort()
print(a)
[ 3  4 -1  0  2]
[-1  0  2  3  4]

sum, max, min, mean

配列のメソッド sum()max()min()mean() は、それぞれ総和・最大値・最小値・算術平均を返します。 これらのメソッドは、引数が与えられない場合、全要素を集計した結果を返します。 多次元配列の場合、集計する次元を指定できます。 具体的には、2次元配列の場合、0 を指定すると各列に、1 を指定すると各行に、対応するメソッドを適用した結果が返されます。

[46]:
a = np.arange(6).reshape(2,3)
print(a)
print(a.sum())
print(a.sum(0))
print(a.sum(1))
[[0 1 2]
 [3 4 5]]
15
[3 5 7]
[ 3 12]

この他にも、多数の数学・統計関連のメソッドや関数が提供されています。 詳しくは、数学関数統計関数を参照してください。

配列の保存と復元

配列は、ファイルに保存したり、ファイルから読み出したりすることが、簡単にできます。

numpy.savetxt() 関数は、与えられた配列を指定されたファイル名をつけてテキスト形式で保存します。

[47]:
np.savetxt('arange3.txt', np.arange(3))

この arange3.txt は、次のような内容になっているはずです。

0.000000000000000000e+00
1.000000000000000000e+00
2.000000000000000000e+00

2次元配列は、列が空白区切りで保存されます

[48]:
np.savetxt('arange2x3.txt', np.arange(6).reshape(2,3))

この arange2x3.txt は、次のような内容になっているはずです。

0.000000000000000000e+00 1.000000000000000000e+00 2.000000000000000000e+00
3.000000000000000000e+00 4.000000000000000000e+00 5.000000000000000000e+00

一方、numpy.loadtxt() 関数は、与えられた名前のファイルに保存された配列を復元します。

[49]:
a = np.loadtxt('arange2x3.txt')
print(a)
[[0. 1. 2.]
 [3. 4. 5.]]

保存するときに、列の区切り文字をデフォルトの ' ' 以外にしたい場合、savetxt()delimiter 引数に区切り文字(列)を指定します。これを復元するときには、loadtxt()delimiter 引数に同じ値を指定する必要があります。 ただし、区切り文字列はASCII(正確にはLatin-1)で解釈可能でなければなりません。

大規模な配列をテキスト形式で保存すると、ファイルサイズがとても大きくなります。 そういう場合、圧縮保存が有用です。

保存するファイル名の拡張子を .gz とすることで、savetxt() は自動的にGZip形式で圧縮して保存します。 復元するファイル名の拡張子が .gz であれば、loadtxt() はGZip形式だと判断して、自動的に解凍して復元します。

真理値配列によるインデックスアクセス

配列に対して、比較演算を適用すると、算術演算と同様に要素毎に演算されて、真理値の配列が返ります。

[50]:
a = np.arange(6)
print(a)
print(a < 3)
[0 1 2 3 4 5]
[ True  True  True False False False]

このように作られた真理値配列は、インデックスとして利用することができます。 これによって、条件を満たす範囲を取り出すような記述が可能になります。 次の具体例を見てみましょう。

[51]:
a = np.array([0,1,2,-3,-4,5,-6,-7])
print(a)
print(a[a < 0]) # 負の要素を取り出し
print(a[(a < 0) & (a % 2 == 0)]) # 負で偶数の要素を取り出し
a[a < 0] = 8 # 負の要素を8に上書き
print(a)
[ 0  1  2 -3 -4  5 -6 -7]
[-3 -4 -6 -7]
[-4 -6]
[0 1 2 8 8 5 8 8]

一見すると単なる条件式のように見えますが、インデックスとなるのは真理値ではなく真理値の配列です。 したがって、真理値を返す andornot の代わりに、要素毎の演算を行う &|~ を用いる必要があります。

同様の記法は、7-1で扱うpandasライブラリでも利用されます。

▲線形代数の演算

numpy.dot() は、2次元配列を与えたときには、行列積となりました。 それだけでなく、行列積専用の numpy.matmul() も提供されています。

また、単位行列は numpy.identity() 関数で作成することができます。 引数に行列のサイズを指定します。

[52]:
I = np.identity(3)
print(I)
a = np.arange(9).reshape(3,3)
print(a)
print(np.matmul(a, I))
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
[[0 1 2]
 [3 4 5]
 [6 7 8]]
[[0. 1. 2.]
 [3. 4. 5.]
 [6. 7. 8.]]

numpy.linalg.norm() 関数は、与えられたベクトル(1次元配列)もしくは行列(2次元配列)のノルムを返します。

[53]:
np.linalg.norm(np.ones(3)) # ユークリッドノルムを計算するのでsqrt(3)と等しい
[53]:
np.float64(1.7320508075688772)

NumPyでは、行列の分解、転置、行列式などの計算を含む線形代数の演算は、numpy.linalg モジュールで提供されています。 詳しくは、線形代数関連関数を参照してください。

練習の解答

[54]:
def arange_square_matrix(n):
    return np.array([np.arange(i, n+i) for i in range(n)])
================================================ FILE: docs/6/6-1.html ================================================ 6-1. 内包表記 — Pythonプログラミング入門 documentation

6-1. 内包表記

内包表記について説明します。

参考:

リスト内包表記

Pythonでは各種の内包表記 (comprehension) が利用できます。

以下のような整数の自乗を要素に持つリストを作るプログラムでは、

[1]:
squares1 = []
for x in range(6):
    squares1.append(x**2)
squares1
[1]:
[0, 1, 4, 9, 16, 25]

squares1 として [0, 1, 4, 9, 16, 25] が得られます。 これを内包表記を用いて書き換えると、以下のように一行で書け、プログラムが読みやすくなります。

[2]:
squares2 = [x**2 for x in range(6)]
squares2
[2]:
[0, 1, 4, 9, 16, 25]

関数 sum は与えられた数のリストの総和を求めます。 (2-2の練習にあった sum_list と同じ機能を持つ組み込みの関数です。) 内包表記に対して sum を適用すると以下のようになります。

[3]:
sum([x**2 for x in range(6)])
[3]:
55

以下の内包表記は3-2で用いられていました。

[4]:
[chr(i + ord('a')) for i in range(26)]
[4]:
['a',
 'b',
 'c',
 'd',
 'e',
 'f',
 'g',
 'h',
 'i',
 'j',
 'k',
 'l',
 'm',
 'n',
 'o',
 'p',
 'q',
 'r',
 's',
 't',
 'u',
 'v',
 'w',
 'x',
 'y',
 'z']

練習

文字列のリストが変数 strings に与えられたとき、 それぞれの文字列の長さからなるリストを返す内包表記を記述してください。

strings = ['The', 'quick', 'brown'] のとき、結果は [3, 5, 5] となります。

[5]:
strings = ['The', 'quick', 'brown']
[ここに内包表記を書く]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[5], line 2
      1 strings = ['The', 'quick', 'brown']
----> 2 [ここに内包表記を書く]

NameError: name 'ここに内包表記を書く' is not defined

練習

コンマで区切られた10進数からなる文字列が変数 str1 に与えられたとき、 それぞれの10進数を数に変換して得られるリストを返す内包表記を記述してください。

str1 = '123,45,-3' のとき、結果は [123, 45, -3] となります。

なお、コンマで区切られた10進数からなる文字列を、10進数の文字列のリストに変換するには、メソッド split を用いることができます。 また、10進数の文字列を数に変換するには、int を関数として用いることができます。

[6]:
str1 = '123,45,-3'
[ここに内包表記を書く]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[6], line 2
      1 str1 = '123,45,-3'
----> 2 [ここに内包表記を書く]

NameError: name 'ここに内包表記を書く' is not defined

練習

数のリストが与えらえたとき、リストの要素の分散を求める関数 var を 内包表記と関数 sum を用いて定義してください。 以下のセルの ... のところを書き換えて var を作成してください。

[7]:
def var(lst):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[8]:
print(var([3,4,1,2]) == 1.25)
False

内包表記の入れ子

また内包表記を入れ子ネスト)にすることも可能です:

[9]:
[[x*y for y in range(x+1)] for x in range(4)]
[9]:
[[0], [0, 1], [0, 2, 4], [0, 3, 6, 9]]

ネストした内包表記は、外側から読むとわかりやすいです。 x0 から 3 まで動かしてリストが作られます。 そのリストの要素1つ1つは内包表記によるリストになっていて、 それぞれのリストは y を 0 から x まで動かして得られます。

以下のリストは、上の2重のリストをフラットにしたものです。 この内包表記では、for が2重になっていますが、自然に左から読んでください。 x0 から 3 まで動かし、そのそれぞれに対して y0 から x まで動かします。 その各ステップで得られた x*y の値をリストにします。

[10]:
[x*y for x in range(4) for y in range(x+1)]
[10]:
[0, 0, 1, 0, 2, 4, 0, 3, 6, 9]

以下の関数は、与えられた文字列の全ての空でない部分文字列からなるリストを返します。

[11]:
def allsubstrings(s):
    return [s[i:j] for i in range(len(s)) for j in range(i+1,len(s)+1)]

allsubstrings('abc')
[11]:
['a', 'ab', 'abc', 'b', 'bc', 'c']

練習

次のような関数 sum_lists を作成してください。

  • sum_lists はリスト list1 を引数とします。

  • list1 の各要素はリストであり、そのリストの要素は数です。

  • sum_lists は、list1 の各要素であるリストの総和を求め、それらの総和を足し合せて返します。

ここでは、内包表記と関数 sum を用いて sum_lists を定義してください。 以下のセルの ... のところを書き換えて sum_lists を作成してください。

[12]:
def sum_lists(list1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[13]:
print(sum_lists([[20, 5], [6, 16, 14, 5], [16, 8, 16, 17, 14], [1], [5, 3, 5, 7]]) == 158)
False

練習

リスト list1list2 が引数として与えられたとき、次のようなリスト list3 を返す関数 sum_matrix を作成してください。

  • list1, list2, list3 は、3つの要素を持ちます。

  • 各要素は大きさ 3 のリストになっており、そのリストの要素は全て数です。

  • list3[i][j] (ただし、ij は共に、0 以上 2 以下の整数)は list1[i][j]list2[i][j] の値の和になっています。

ここでは、内包表記を用いてsum_matrix を定義してください。以下のセルの ... のところを書き換えて sum_matrix を作成してください。

[14]:
def sum_matrix(list1, list2):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[15]:
print(sum_matrix([[1,5,3],[4,5,6],[7,8,9]], [[1,4,7],[2,5,8],[3,6,9]])==[[2, 9, 10], [6, 10, 14], [10, 14, 18]])
False

条件付き内包表記

内包表記は for に加えて if を使うこともできます:

[16]:
words = ['cat', 'dog', 'elephant', None, 'giraffe']
length = [len(w) for w in words if w != None]
print(length)
[3, 3, 8, 7]

この場合、length として要素が None の場合を除いた [3, 3, 8, 7] が得られます。

セット内包表記

内包表記はセット(集合)に対しても使うことができます:

[17]:
words = ['cat', 'dog', 'elephant', 'giraffe']
length_set = {len(w) for w in words}
print(length_set)
{8, 3, 7}

length_set として {3, 7, 8} が得られます。 セット型なので、リストと異なり重複する要素は除かれます。

辞書内包表記

さらに、内包表記は辞書型でも使うことができます。

[18]:
words = ['cat', 'dog', 'elephant', 'giraffe']
length_dic = {w:len(w) for w in words}
print(length_dic)
{'cat': 3, 'dog': 3, 'elephant': 8, 'giraffe': 7}

length_dic として {'cat': 3, 'dog': 3, 'elephant': 8, 'giraffe': 7} が得られます。

長さと文字列を逆にするとどうなるでしょうか。

[19]:
length_rdic = {len(w): w for w in words}
print(length_rdic)
{3: 'dog', 8: 'elephant', 7: 'giraffe'}

ジェネレータ式

内包表記と似たものとして、ジェネレータ式というものがあります。 リスト内包表記の []() に置き換えれば、ジェネレータ式になります。 ジェネレータ式は、4-2で説明したイテレータを構築します。 4-2で説明したように、イテレータは、for文で走査(全要素を訪問)できます。

[20]:
it = (x * 3 for x in 'abc')
for x in it:
    print(x)
aaa
bbb
ccc

イテレータを組み込み関数 list()tuple() に渡すと、対応するリストやタプルが構築されます。 なお、ジェネレータ式を直接引数とするときには、ジェネレータ式の外側の () は省略可能です。

[21]:
list(x ** 2 for x in range(5))
[21]:
[0, 1, 4, 9, 16]
[22]:
tuple(x ** 2 for x in range(5))
[22]:
(0, 1, 4, 9, 16)

総和を計算する組み込み関数 sum() など、リストやタプルを引数に取れる大抵の関数には、イテレータも渡せます。

[23]:
sum(x ** 2 for x in range(5))
[23]:
30

上の例において、ジェネレータ式の代わりにリスト内包表記を用いても同じ結果を得ますが、 計算の途中で実際にリストを構築するので、メモリ消費が大きいです。 ジェネレータ式では、リストのように走査できるイテレータを構築するだけなので、リスト内包表記よりメモリ効率がよいです。 したがって、関数に渡すだけの一時オブジェクトには、リスト内包表記ではなくジェネレータ式を用いるのが有効です。

練習の解答

[24]:
strings = ['The', 'quick', 'brown']
[len(x) for x in strings]
[24]:
[3, 5, 5]
[25]:
str1 = '123,45,-3'
[int(x) for x in str1.split(',')]
[25]:
[123, 45, -3]
[26]:
def var(lst):
    n = len(lst)
    av = sum(lst)/n
    return sum([(x - av)*(x - av) for x in lst])/n
[27]:
def var(lst):
    n = len(lst)
    av = sum(lst)/n
    return sum([x*x for x in lst])/n - av*av
[28]:
def sum_lists(list1):
    return sum([sum(lst) for lst in list1])
[29]:
def sum_matrix(list1,list2):
    return [[list1[i][j] + list2[i][j] for j in range(3)] for i in range(3)]
[ ]:

================================================ FILE: docs/6/6-2.html ================================================ 6-2. 高階関数 — Pythonプログラミング入門 documentation

6-2. 高階関数

Pythonにおける高階関数について説明します。

参考

max

例として、関数 max について考察します。max は与えられたリストの要素のうち、最大のものを返します。

[1]:
ls = [3,-8,1,0,7,-5]
max(ls)
[1]:
7

maxkey というキーワード引数として、たとえば関数 abs を与えることができます。 (キーワード引数について詳しくは、3-3を参照してください。)

[2]:
max(ls, key=abs)
[2]:
-8

この場合、各要素に関数 abs が適用されて、その結果が最も大きい要素が返ります。 (各要素に abs 適用した結果の中の最大値が返るわけではないことに注意してください。) なお、abs(x)x の絶対値を返します。

この場合、max という関数は、関数を引数として受け取っています。

一般に、関数を引数として受け取ったり返値として返したりする関数を高階関数といいます。

sorted

sorted も高階関数で、max と同様に key というキーワード引数を取ります。

[3]:
sorted(ls, key=abs)
[3]:
[0, 1, 3, -5, 7, -8]

このように、各要素に関数 abs を適用した結果によって、各要素をソートします。

リストを降順にソートするには、次のような関数を用いればよいです。

[4]:
def invert(x):
    return -x
[5]:
sorted(ls, key=invert)
[5]:
[7, 3, 1, 0, -5, -8]

なお、リストを降順にソートするには、reverse というキーワード引数に True を指定するという方法もあります。

[6]:
sorted(ls, reverse=True)
[6]:
[7, 3, 1, 0, -5, -8]

ラムダ式

上の invert のような簡単な関数の場合、 いちいち def で定義するのは面倒と思いませんか。

そのようなときは、lambda を使ったラムダ式(または無名関数)を用いることができます。 上の例は、以下のように書くことができます。

[7]:
sorted(ls, key=lambda x: -x)
[7]:
[7, 3, 1, 0, -5, -8]

lambda x: -x という式は、x をもらって -x を返す関数を表します。 return は書かないことに注意してください。

さて、ここまで関数と呼んでいたものは、Pythonでは、オブジェクトの一種に他なりません。 実際に、abslambda x: -x という式の値を調べてみてください。

[8]:
abs
[8]:
<function abs(x, /)>
[9]:
lambda x: -x
[9]:
<function __main__.<lambda>(x)>

したがって、Pythonでは、関数を他の種類のデータ(数やリストや文字列など)と同様に、 関数の引数にしたり、リストの要素にしたり、することができます。

リストからイテラブルへ

以上の例では、maxsorted はリストを受け取っていましたが、 リストではなく、タプルでもいいですし、文字列でも構いません。

[10]:
max((3,-8,1,0,7,-5))
[10]:
7
[11]:
sorted((3,-8,1,0,7,-5))
[11]:
[-8, -5, 0, 1, 3, 7]
[12]:
max('hello world')
[12]:
'w'
[13]:
sorted('hello world')
[13]:
[' ', 'd', 'e', 'h', 'l', 'l', 'l', 'o', 'o', 'r', 'w']

すなわち、maxsorted は、一般にイテラブルを引数に取ることができます。

イテラブルについては4-2に説明がありましたが、 簡単に言うと、イテラブルとはfor文の in の後に来ることができるものです。 maxsorted は、イテラブルの各要素を次々と求めて、 その中の最大値を求めたり、整列した結果をリストとして返したりします。

以下の例では、max にファイルオブジェクトが渡されます。 ファイルオブジェクトはイテレータですので、イテラブルでもあります。 ファイルオブジェクトをfor文の in の後に指定すると、 ファイルの各行が文字列として得られます。 以下の例では、key として関数 len が指定されていますので、 ファイルの中で最も長い行が表示されます。

[14]:
with open('jugemu.txt', 'r', encoding='utf-8') as f:
    print(max(f, key=len))
グーリンダイのポンポコピーのポンポコナーの、

辞書もイテラブルです。max に辞書与えると、最大のキーが返ります。

[15]:
max({3:10, 5:2, 9:1})
[15]:
9

練習

辞書 d が与えられたとき、 最大の値を持つキー(複数個ならばそのいずれか)を返す関数 max_value_key(d) を、 max を使って定義してください。

ヒント:辞書 d のキー k に対して、k に対応する値を返す関数は lambda k: d[k] という式で表すことができます。

[16]:
def max_value_key(d):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[17]:
print(max_value_key({3:10, 5:2, 9:1}) == 3)
False

map

以下は内包表記の例です。

[18]:
[abs(x) for x in [3,-8,1,0,7,-5]]
[18]:
[3, 8, 1, 0, 7, 5]

リストの各要素に関数 abs が適用された結果がリストになります。

同様のことを、高階関数 map を用いて行うことができます。 関数 map は、2番目の引数としてイテラブルを取ります。1番目の引数は関数です。 例を見ましょう。

[19]:
map(abs, [3,-8,1,0,7,-5])
[19]:
<map at 0x11288c2b0>

何が返ったか、よくわからないと思います。 以下のように、map の結果をfor文の in の後に指定してみましょう。

[20]:
for x in map(abs, [3,-8,1,0,7,-5]):
    print(x)
3
8
1
0
7
5

すなわち、map が返すものはイテレータです。 このイテレータは、2番目の引数のイテラブル(この例ではリスト)の各要素に 関数 abs を適用したものを、次々と返すようなイテレータです。

内包表記を使えば、以下のようにリストにまとめることができます。

[21]:
[x for x in map(abs, [3,-8,1,0,7,-5])]
[21]:
[3, 8, 1, 0, 7, 5]

関数 list をイテレータに適用してもよいです。

[22]:
list(map(abs, [3,-8,1,0,7,-5]))
[22]:
[3, 8, 1, 0, 7, 5]

しかし、これでは、イテレータがどのように動くのか、よくわからないと思います。

以下では、呼ばれるたびにメッセージを出力する関数 abs1 を用います。

[23]:
def abs1(x):
    print('abs called on', x)
    return abs(x)
[24]:
it = map(abs1, [3,-8,1,0,7,-5])

このように、map がイテレータを返した時点では、各要素に対する計算は何も行われません。

このイテレータに next を適用するとどうなるか、見てください。

[25]:
next(it)
abs called on 3
[25]:
3
[26]:
next(it)
abs called on -8
[26]:
8

関数 next が呼ばれるたびに、次の要素を求める計算が行われていることがわかります。

イテレータはイテラブルですから、map の結果にさらに map を適用することができます。

[27]:
list(map(lambda x: x+1, map(abs, [3,-8,1,0,7,-5])))
[27]:
[4, 9, 2, 1, 8, 6]

lambda x: x+1 は、x をもらって x+1 を返す関数です。 すなわち、引数に 1 を足した結果を返します。

関数 sum は、max と同様に、イテラブルを受け取って、その要素の総和を返します。 したがって、map が返したイテレータに対しても適用できます。 (イテレータをリストに変換する必要はありません。)

[28]:
sum(map(lambda x: x+1, map(abs, [3,-8,1,0,7,-5])))
[28]:
30

練習

数のリストが与えられたとき、その要素の絶対値の最大値を返す関数 max_abs を、 mapmax を使って定義してください。

[29]:
def max_abs(ln):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[30]:
print(max_abs([3,-8,1,0,7,-5]) == 8)
False

filter

関数 filter もイテラブルをもらってイテレータを返します。 最初の引数としては、真理値を返す関数を指定します。

[31]:
def pos(x):
    if x>0:
        return True
    else:
        return False

この関数 pos は、引数が正ならば True、そうでなければ False を返します。

すると、以下のように、filterpos を適用すると True が返る要素のみからなるイテレータを返します。

[32]:
list(filter(pos, [3,-8,1,0,7,-5]))
[32]:
[3, 1, 7]

filter は、条件付き内包表記に対応しています。 同じ計算を以下のようにして行うことができます。

[33]:
[x for x in [3,-8,1,0,7,-5] if pos(x)]
[33]:
[3, 1, 7]

練習

数のリスト ln と数 n を受け取って、ln の要素のうち、n より大きい個数を返す関数 number_of_big_numbers(ln, n) を、for文やwhile文を用いずに、filter を用いて定義してください。

[34]:
def number_of_big_numbers(ln, n):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[35]:
print(number_of_big_numbers([10, 0, 7, 1, 5, 2, 9], 5) == 3)
False

練習

ファイル名 file と整数 n を受け取って、そのファイルをオープンし、 (改行文字も含めて)長さが n より長い行の数を返す関数 number_of_long_lines(file,n) を定義してください。 (ファイルは encoding='utf-8' でオープンしてください。)

[36]:
def number_of_long_lines(file, n):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[37]:
print(number_of_long_lines('jugemu.txt', 10) == 6)
False

練習の解答

[38]:
def max_value_key(d):
    return max(d, key=lambda k: d[k])
[39]:
def max_abs(ln):
    return max(map(abs, ln))
[40]:
def number_of_big_numbers(ln, n):
    return sum(map(lambda x: 1, filter(lambda x: x>n, ln)))
[41]:
def number_of_long_lines(file, n):
    with open(file, 'r', encoding='utf-8') as f:
        return sum(map(lambda x: 1, filter(lambda x: len(x)>n, f)))
[ ]:

================================================ FILE: docs/6/6-3.html ================================================ 6-3. クラス — Pythonプログラミング入門 documentation

6-3. クラス

Pythonにおけるオブジェクト指向プログラミングのうち、クラスを定義する方法について簡単に説明します。

参考

クラス定義

Pythonでは全てのデータはオブジェクトなのですが、 以下では特に、クラス定義によって作成されたクラスを型とするデータを扱います。 このようなデータは、オブジェクト指向プログラミングにおける典型的なオブジェクトです。 そこで以下では、オブジェクトという用語をもっぱら使います。

4-1で見たように、ファイルオブジェクトに対して readline() というメソッドを呼び出すと、 ファイルの行が文字列として次々と返されます。 ここでは、ファイルオブジェクトのようなオブジェクトで、 readline() というメソッドが呼び出されると、常に 'Hello.\n' という文字列を返すようなものを作ってみましょう。

そのためには、新しいクラスを定義します。 クラスとは、オブジェクトの種類を意味します。 新しいクラスを定義すると、そのクラスに属するオブジェクトを作ることができるようになります。 それらのオブジェクトの型は、その新しいクラスになります。

ここでは、ずっと 'Hello.\n' を返し続けるので、 HelloForEver という名前を持つクラスを定義しましょう。 そして、HelloForEver というクラスを型とするオブジェクトを作ります。

[1]:
class HelloForEver:
    def readline(self):
        return 'Hello.\n'

一般にクラス定義は、以下のような形をしています。

class クラス名:
    def メソッド名(self, 引数, ...):
        実行文
    def メソッド名(self, 引数, ...):
        実行文
    ...

メソッド定義は関数定義と同じ形をしていますが、 クラス定義の中に入っています。 メソッド定義において、その最初の引数には慣例として self という名前を付けます。 この引数には、メソッドが呼び出されたオブジェクト自身が渡されます。

上の例では、readline というメソッドが1つ定義されています。

以下のようにして、このクラスのオブジェクトを作ることができます。

[2]:
f = HelloForEver()

HelloForEver を型とする新しいオブジェクトが作られて変数 f の値となります。

一般に、オブジェクトの生成は、

クラス名(式, ...)

という式で行います。このようにオブジェクトを生成する式はコンストラクタと呼ばれます。 なお、上の例では、括弧の中に式は1つもありません。

このようにして作ったオブジェクトの型を確認してください。

[3]:
type(f)
[3]:
__main__.HelloForEver

__main__.HelloForEver と表示されたでしょう。 __main__ は、ノートブックの式が評価されているモジュールを指すので、 このオブジェクトの型が、上で定義した HelloForEver クラスであることがわかります。 クラスのコンストラクタによって生成されたオブジェクトを、そのクラスのインスタンスと言います。 上のオブジェクトは HelloForEver クラスのインスタンスです。

オブジェクトそのものは以下のように表示されます。

[4]:
f
[4]:
<__main__.HelloForEver at 0x10f459820>

このオブジェクトに対して、readline というメソッドを呼び出すことができます。

[5]:
f.readline()
[5]:
'Hello.\n'

この例では、f という変数に入っているオブジェクトが self という引数に渡されて、 readline の本体である以下の文が実行されました。

return 'Hello.\n'

(この例では self は参照されていません。)

何回やっても同じです。

[6]:
f.readline()
[6]:
'Hello.\n'
[7]:
f.readline()
[7]:
'Hello.\n'

初期化と属性

以下の例では、初期化のメソッドが定義され、オブジェクトに属性が与えられます。

初期化のメソッドは __init__ という名前を持ち、 オブジェクトが作られたときに自動的に呼び出されます。 __init__ の引数は、オブジェクト自身と、クラス名の後に与えられる式の値です。

[8]:
class HelloFile:
    def __init__(self, n):
        self.n = n
    def readline(self):
        if self.n == 0:
            return ''
        self.n = self.n - 1
        return 'Hello.\n'

この例では、以下のようにしてオブジェクトが作られます。

[9]:
f = HelloFile(3)

すると、HelloFile を型とする新しいオブジェクトが作られて、 そのオブジェクト自身が self に、3n に渡されて、 self.n = n という文が実行されます。

self.n という式は、このオブジェクトの n という名前の属性を表します。

一般に、class の構文によって定義されたクラスを型とするオブジェクトは、 属性を持つことができます。 属性とは、個々のオブジェクトごとに記録される値であり、 オブジェクト内の変数と考えられます。 オブジェクトの属性は、オブジェクトに対してその属性名を指定して、参照したり設定したりできます。 オブジェクトの属性は、self.属性名 という式で参照されます。 self.属性名 を代入文の左辺に書けば、属性を設定することができます。

self.n = n のうち、self. の次の n は属性を表し、 右辺の n は、__init__ メソッドの引数を表していますので、 混同しないようにしてください。

この例では、新しく作られたオブジェクトの n という属性が、引数 n の値である 3 に設定されます。

readline メソッドは以下のように定義されています。

def readline(self):
    if self.n == 0:
        return ''
    self.n = self.n - 1
    return 'Hello.\n'

オブジェクトの属性 n を参照して、それが 0 ならば空文字列を返します。 そうでなければ、属性 n1 減らしてから文字列 'Hello.\n' を返します。

[10]:
f.readline()
[10]:
'Hello.\n'
[11]:
f.readline()
[11]:
'Hello.\n'
[12]:
f.readline()
[12]:
'Hello.\n'
[13]:
f.readline()
[13]:
''

変数 f の値であるオブジェクトの属性 n は、f.n という式によって参照できます。

[14]:
f.n
[14]:
0

ここでは詳しく説明しませんが、オブジェクトのメソッドも属性の一種です。

継承

継承は、既存のクラスをもとにして、変更部分だけを与えることにより、 新たなクラスを定義する機能です。

以下の例では、HelloForEver をもとにして HelloFile を定義しています。 一般に、新しく定義されるクラスを子クラス、そのもとになるクラスを親クラスと言います。

[15]:
class HelloFile(HelloForEver):
    def __init__(self, n):
        self.n = n
    def readline(self):
        if self.n == 0:
            return ''
        self.n = self.n - 1
        return super().readline()

ここでは、__init__readline を新たに定義しています。

HelloForEver にも readline があります。 こちらの readline は、super().readline() という式で呼び出すことができます。 super() は、子クラスのオブジェクトに対して親クラスのメソッドを呼び出すための構文です。 実際に、HelloFilereadline の中で、 HelloForEverreadline を呼び出しています。

[16]:
f = HelloFile(3)
[17]:
f.readline()
[17]:
'Hello.\n'

特殊メソッド

Pythonでは、特殊メソッドと呼ばれるメソッドが多数あります。 これらのメソッドの名前は __ で始まり __ で終わります。

クラス定義の中で特殊メソッドを定義すると、そのクラスのオブジェクトに対して、 その特殊メソッドに対応する機能が付与されます。 初期化メソッド __init__ も特殊メソッドですが、 以下のクラス HelloFileIterator では、__iter____next__ という特殊メソッドが定義されています。 このクラスは、HelloFile を継承して定義されています。

__iter__ メソッドは、オブジェクトに対して関数 iter が適用されたときに呼び出されます。 __iter__ メソッドの値が関数 iter の値となります。 以下の例では、__iter__ はオブジェクト自身を返しています。 したがって、オブジェクトに iter が適用されると、オブジェクト自身が返ります。

[18]:
class HelloFileIterator(HelloFile):
    def __iter__(self):
        return self
    def __next__(self):
        line = self.readline()
        if line == '':
            raise StopIteration
        return line
[19]:
f = HelloFileIterator(3)
[20]:
print(f is iter(f))
True

上の例で、iter(f) として関数 iter を呼び出すと、 f.__iter__() としてメソッド __iter__f に対して呼び出され、 その結果が iter(f) の値となります。 したがって、iter(f)f と同じ値を返します。

__next__ メソッドも、オブジェクトに対して関数 next が適用されたときに呼び出されます。 __next__ メソッドの値が next の値となります。

上の例では、self.readline() として、オブジェクト自身に対してメソッド readline を呼び出しています。 その値が空文字列ならば、

raise StopIteration

という文を実行して、StopIteration というエラーを投げます。 実は、このエラーは、for文が捕まえて繰り返しを止める効果を持ちます。 なお、raise は強制的にエラーを発生させる構文です。

[21]:
for line in f:
    print(line)
Hello.

Hello.

Hello.

4-2で説明したように、上のfor文では、 まず f のオブジェクトに対して関数 iter が適用されます。 すると f のオブジェクト自身が返ります。 そして、このオブジェクトに対して関数 next が繰り返し適用されて、 その結果が変数 line の値となります。 StopIteration のエラーが検知されると、for文が終了します。

継承による振舞いの改変

上で示された、HelloFileIterator__next__ メソッドでは、self.readline() というメソッド呼び出しがありました。 上の例の振舞いから、そのメソッド呼び出しは、HelloFileIterator には readline メソッドが定義されていないので、親の HelloFile を見に行って、そこで定義された readline メソッドが使われたように見えます。 しかし、それは正確ではありません。

self.readline() では、その呼び出し場所がどこであるかに関わらず、常にオブジェクト self の中のメソッドを探索します。 そして、継承があるために、__next__(self) における self が、HelloFileIterator のインスタンスであるとも限りません。 次を見てみましょう。

[22]:
class EmptyFile(HelloFileIterator):
    def readline(self):
        return ''

f = EmptyFile(3)
next(f)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In[22], line 6
      3         return ''
      5 f = EmptyFile(3)
----> 6 next(f)

Cell In[18], line 7, in HelloFileIterator.__next__(self)
      5 line = self.readline()
      6 if line == '':
----> 7     raise StopIteration
      8 return line

StopIteration:

コンストラクタに 3 を与えているので、HelloFileIterator と同様に next を3回適用できてもよさそうですが、即座に StopIteration が生じました。 これは、__next__(self) における self が、EmptyFile のインスタンスであり、self.readline() が常に '' を返すからです。

このように、継承は、メソッドの部分的な再定義を通じて、再定義されたメソッドを呼び出しているメソッドの振舞いを、間接的に改変することを可能にします。

練習

'Hello.\n' ではなくて、初期時に指定された文字列を繰り返し返すように、 新たなクラス StringFileIterator を定義してください。

StringFileIteratorHelloFileIterator を継承し、 初期化メソッドには、文字列と回数を指定します。

[23]:
class StringFileIterator(HelloFileIterator):
    def __init__(self, s, n):
        ...
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[24]:
f = StringFileIterator('abc', 3)
print(list(f) == ['abc','abc','abc'])
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[24], line 2
      1 f = StringFileIterator('abc', 3)
----> 2 print(list(f) == ['abc','abc','abc'])

Cell In[18], line 5, in HelloFileIterator.__next__(self)
      4 def __next__(self):
----> 5     line = self.readline()
      6     if line == '':
      7         raise StopIteration

Cell In[15], line 5, in HelloFile.readline(self)
      4 def readline(self):
----> 5     if self.n == 0:
      6         return ''
      7     self.n = self.n - 1

AttributeError: 'StringFileIterator' object has no attribute 'n'

▲with文への対応

ここでは詳しく説明しませんが、さらに特殊メソッドである __enter____exit__ を定義すると、 with文にも対応できます。

[25]:
class HelloFileIterator(HelloFile):
    def __enter__(self):
        return self
    def __exit__(self,exception_type,exception_value,traceback):
        pass
    def __next__(self):
        line = self.readline()
        if line == '':
            raise StopIteration
        return line
    def __iter__(self):
        return self
[26]:
with HelloFileIterator(3) as f:
    for line in f:
        print(line)
Hello.

Hello.

Hello.

練習の解答

[27]:
class StringFileIterator(HelloFileIterator):
    def __init__(self, s, n):
        self.s = s
        self.n = n
    def readline(self):
        if self.n == 0:
            return ''
        self.n = self.n - 1
        return self.s
[ ]:

================================================ FILE: docs/7/7-1.html ================================================ 7-1. pandasライブラリ — Pythonプログラミング入門 documentation

7-1. pandasライブラリ

pandasライブラリについて説明します。

参考

pandasライブラリにはデータ分析作業を支援するためのモジュールが含まれています。以下では、pandasライブラリのモジュールの基本的な使い方について説明します。

pandasライブラリを使用するには、まず pandas モジュールをインポートします。慣例として、同モジュールを pd と別名をつけてコードの中で使用します。データの生成に用いるため、ここでは numpy モジュールも併せてインポートします。

[1]:
import pandas as pd
import numpy as np

シリーズとデータフレーム

pandas モジュールは、リスト、配列や辞書などのデータをシリーズ (Series) あるいはデータフレーム (DataFrame) のオブジェクトとして保持します。シリーズは列、データフレームは複数の列で構成されます。シリーズやデータフレームの行はインデックス index で管理され、インデックスには 0 から始まる番号、または任意のラベルが付けられています。インデックスが番号の場合は、シリーズやデータフレームはそれぞれNumPyの配列、2次元配列とみなすことができます。また、インデックスがラベルの場合は、ラベルをキー、各行を値とした辞書としてシリーズやデータフレームをみなすことができます。

シリーズ (Series) の作成

シリーズのオブジェクトは、以下のように、リスト、配列や辞書から作成することができます。

[2]:
# リストからシリーズの作成
s1 = pd.Series([0,1,2])
print(s1)

# 配列からシリーズの作成
s2 = pd.Series(np.random.rand(3))
print(s2)

# 辞書からシリーズの作成
s3 = pd.Series({0:'boo',1:'foo',2:'woo'})
print(s3)
0    0
1    1
2    2
dtype: int64
0    0.296747
1    0.845386
2    0.680552
dtype: float64
0    boo
1    foo
2    woo
dtype: object

以下では、シリーズ(列)より一般的なデータフレームの操作と機能について説明していきますが、データフレームオブジェクトの多くの操作や機能はシリーズオブジェクトにも適用できます。

データフレーム (DataFrame) の作成

データフレームのオブジェクトは、以下のように、リスト、配列や辞書から作成することができます。行のラベルは、DataFrameindex 引数で指定できますが、以下のデータフレーム作成の例、d2, d3、 では同インデックスを省略しているため、0 から始まるインデックス番号がラベルとして行に自動的に付けられます。列のラベルは columns 引数で指定します。辞書からデータフレームを作成する際は、columns 引数で列の順番を指定することになります。

[3]:
# 多次元リストからデータフレームの作成
d1 = pd.DataFrame([[0,1,2],[3,4,5],[6,7,8],[9,10,11]], index=[10,11,12,13], columns=['c1','c2','c3'])
print(d1)

# 多次元配列からデータフレームの作成
d2 = pd.DataFrame(np.random.rand(12).reshape(4,3), columns=['c1','c2','c3'])
print(d2)

# 辞書からデータフレームの作成
d3 = pd.DataFrame({'Initial':['B','F','W'], 'Name':['boo', 'foo', 'woo']}, columns=['Name','Initial'])
print(d3)
    c1  c2  c3
10   0   1   2
11   3   4   5
12   6   7   8
13   9  10  11
         c1        c2        c3
0  0.373992  0.912874  0.326649
1  0.044701  0.395272  0.990805
2  0.914061  0.759766  0.118296
3  0.712000  0.992865  0.260287
  Name Initial
0  boo       B
1  foo       F
2  woo       W

CSVファイルからのデータフレームの作成

pandas モジュールの read_csv() 関数を用いて、以下のようにCSVファイルを読み込んで、データフレームのオブジェクトを作成することができます。read_csv() 関数の encoding 引数にはファイルの文字コードを指定します。CSVファイル iris.csv には、以下のようにアヤメの種類 (species) と花弁 (petal)・がく片 (sepal) の長さ (length) と幅 (width) のデータが含まれています。

sepal_length, sepal_width, petal_length, petal_width, species
5.1, 3.5, 1.4, 0.2, setosa
4.9, 3.0, 1.4, 0.2, setosa
4.7, 3.2, 1.3, 0.2, setosa
...

head() メソッドを使うとデータフレームの先頭の複数行を表示させることができます。引数には表示させたい行数を指定し、行数を指定しない場合は、5行分のデータが表示されます。

[4]:
# CSVファイルの読み込み
iris_d = pd.read_csv('iris.csv')

# 先頭10行のデータを表示
iris_d.head(10)
[4]:
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
5 5.4 3.9 1.7 0.4 setosa
6 4.6 3.4 1.4 0.3 setosa
7 5.0 3.4 1.5 0.2 setosa
8 4.4 2.9 1.4 0.2 setosa
9 4.9 3.1 1.5 0.1 setosa

データフレームオブジェクトの index 属性により、データフレームのインデックスの情報が確認できます。len() 関数を用いると、データフレームの行数が取得できます。

[5]:
print(iris_d.index) #インデックスの情報
len(iris_d.index) #インデックスの長さ
RangeIndex(start=0, stop=150, step=1)
[5]:
150

データの参照

シリーズやデータフレームでは、行の位置(行は 0 から始まります)をスライスとして指定することで任意の行を抽出することができます。

[6]:
# データフレームの先頭5行のデータ
iris_d[:5]
[6]:
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
[7]:
# データフレームの終端5行のデータ
iris_d[-5:]
[7]:
sepal_length sepal_width petal_length petal_width species
145 6.7 3.0 5.2 2.3 virginica
146 6.3 2.5 5.0 1.9 virginica
147 6.5 3.0 5.2 2.0 virginica
148 6.2 3.4 5.4 2.3 virginica
149 5.9 3.0 5.1 1.8 virginica

データフレームから任意の列を抽出するには、DataFrame.列名 のように、データフレームオブジェクトに . で列名をつなげることで、その列を指定してシリーズオブジェクトとして抽出することができます。なお、列名を文字列として、DataFrame['列名'] のように添字指定しても同様です。

[8]:
# データフレームの'species'の列の先頭10行のデータ
iris_d['species'].head(10)
[8]:
0    setosa
1    setosa
2    setosa
3    setosa
4    setosa
5    setosa
6    setosa
7    setosa
8    setosa
9    setosa
Name: species, dtype: object

データフレームの添字として、列名のリストを指定すると複数の列をデータフレームオブジェクトとして抽出することができます。

[9]:
# データフレームの'sepal_length'とspecies'の列の先頭10行のデータ
iris_d[['sepal_length','species']].head(10)
[9]:
sepal_length species
0 5.1 setosa
1 4.9 setosa
2 4.7 setosa
3 4.6 setosa
4 5.0 setosa
5 5.4 setosa
6 4.6 setosa
7 5.0 setosa
8 4.4 setosa
9 4.9 setosa

ilocloc

データフレームオブジェクトの iloc 属性を用いると、NumPyの多次元配列のスライスと同様に、行と列の位置を指定して任意の行と列を抽出することができます。

[10]:
# データフレームの2行のデータ
iris_d.iloc[1]
[10]:
sepal_length       4.9
sepal_width        3.0
petal_length       1.4
petal_width        0.2
species         setosa
Name: 1, dtype: object
[11]:
# データフレームの2行,2列目のデータ
iris_d.iloc[1, 1]
[11]:
np.float64(3.0)
[12]:
# データフレームの1から5行目と1から2列目のデータ
iris_d.iloc[0:5, 0:2]
[12]:
sepal_length sepal_width
0 5.1 3.5
1 4.9 3.0
2 4.7 3.2
3 4.6 3.1
4 5.0 3.6

データフレームオブジェクトの loc 属性を用いると、抽出したい行のインデックス・ラベルや列のラベルを指定して任意の行と列を抽出することができます。複数のラベルはリストで指定します。行のインデックスは各行に割り当てられた番号で、iloc で指定する行の位置とは必ずしも一致しないことに注意してください。

[13]:
# データフレームの行インデックス5のデータ
iris_d.loc[5]
[13]:
sepal_length       5.4
sepal_width        3.9
petal_length       1.7
petal_width        0.4
species         setosa
Name: 5, dtype: object
[14]:
# データフレームの行インデックス5と'sepal_length'と列のデータ
iris_d.loc[5, 'sepal_length']
[14]:
np.float64(5.4)
[15]:
# データフレームの行インデックス1から5と'sepal_length'とspecies'の列のデータ
iris_d.loc[1:5, ['sepal_length','species']]
[15]:
sepal_length species
1 4.9 setosa
2 4.7 setosa
3 4.6 setosa
4 5.0 setosa
5 5.4 setosa

データの条件取り出し

データフレームの列の指定と併せて条件を指定することで、条件にあった行からなるデータフレームを抽出することができます。NumPyの多次元配列の真理値配列によるインデックスアクセスと同様に、条件式のブール演算では、and, or, not の代わりに &, |, ~ を用います。

[16]:
# データフレームの'sepal_length'列の値が7より大きく、'species'列の値が3より小さいデータ
iris_d[(iris_d['sepal_length'] > 7.0) & (iris_d['sepal_width'] < 3.0)]
[16]:
sepal_length sepal_width petal_length petal_width species
107 7.3 2.9 6.3 1.8 virginica
118 7.7 2.6 6.9 2.3 virginica
122 7.7 2.8 6.7 2.0 virginica
130 7.4 2.8 6.1 1.9 virginica

列の追加と削除

データフレームに列を追加する場合は、以下のように、追加したい新たな列名を指定し、値を代入すると新たな列を追加できます。

[17]:
# データフレームに'mycolumn'という列を追加
iris_d['mycolumn']=np.random.rand(len(iris_d.index))
iris_d.head(10)
[17]:
sepal_length sepal_width petal_length petal_width species mycolumn
0 5.1 3.5 1.4 0.2 setosa 0.909687
1 4.9 3.0 1.4 0.2 setosa 0.574082
2 4.7 3.2 1.3 0.2 setosa 0.716383
3 4.6 3.1 1.5 0.2 setosa 0.217071
4 5.0 3.6 1.4 0.2 setosa 0.240634
5 5.4 3.9 1.7 0.4 setosa 0.903485
6 4.6 3.4 1.4 0.3 setosa 0.217574
7 5.0 3.4 1.5 0.2 setosa 0.175367
8 4.4 2.9 1.4 0.2 setosa 0.316945
9 4.9 3.1 1.5 0.1 setosa 0.227793

del 文を用いると、以下のようにデータフレームから任意の列を削除できます。

[18]:
# データフレームから'mycolumn'という列を削除
del iris_d['mycolumn']
iris_d.head(10)
[18]:
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
5 5.4 3.9 1.7 0.4 setosa
6 4.6 3.4 1.4 0.3 setosa
7 5.0 3.4 1.5 0.2 setosa
8 4.4 2.9 1.4 0.2 setosa
9 4.9 3.1 1.5 0.1 setosa

assign() メソッドを用いると、追加したい列名とその値を指定することで、以下のように新たな列を追加したデータフレームを新たに作成することができます。この際、元のデータフレームは変更されないことに注意してください。

[19]:
# データフレームに'mycolumn'という列を追加し新しいデータフレームを作成
myiris1 = iris_d.assign(mycolumn=np.random.rand(len(iris_d.index)))
myiris1.head(5)
[19]:
sepal_length sepal_width petal_length petal_width species mycolumn
0 5.1 3.5 1.4 0.2 setosa 0.975114
1 4.9 3.0 1.4 0.2 setosa 0.874244
2 4.7 3.2 1.3 0.2 setosa 0.479607
3 4.6 3.1 1.5 0.2 setosa 0.553219
4 5.0 3.6 1.4 0.2 setosa 0.682090

drop() メソッドを用いると、削除したい列名を指定することで、以下のように任意の列を削除したデータフレームを新たに作成することができます。列を削除する場合は、axis 引数に 1 を指定します。この際、元のデータフレームは変更されないことに注意してください。

[20]:
# データフレームから'mycolumn'という列を削除し、新しいデータフレームを作成
myiris2 = myiris1.drop('mycolumn',axis=1)
myiris2.head(5)
[20]:
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa

行の追加と削除

pandas モジュールの concat() 関数を用いると、データフレームに新たな行を追加することができます。以下では、iris_d データフレームの最終行に新たな行を追加しています。ignore_index 引数を True にすると追加した行に新たなインデックス番号がつけられます。

[21]:
# 追加する行のデータフレーム
row = pd.DataFrame([[1,1,1,1, 'setosa']], columns=iris_d.columns)

# データフレームに行を追加し新しいデータフレームを作成
myiris4 = pd.concat([iris_d, row], ignore_index=True)
myiris4[-2:]
[21]:
sepal_length sepal_width petal_length petal_width species
149 5.9 3.0 5.1 1.8 virginica
150 1.0 1.0 1.0 1.0 setosa

drop() メソッドを用いると、行のインデックスまたはラベルを指定することで行を削除することもできます。このときに、axis 引数は省略することができます。

[22]:
# データフレームから行インデックス150の行を削除し、新しいデータフレームを作成
myiris4 = myiris4.drop(150)
myiris4[-2:]
[22]:
sepal_length sepal_width petal_length petal_width species
148 6.2 3.4 5.4 2.3 virginica
149 5.9 3.0 5.1 1.8 virginica

データの並び替え

データフレームオブジェクトの sort_index() メソッドで、データフレームのインデックスに基づくソートができます。また、sort_values() メソッドで、任意の列の値によるソートができます。列は複数指定することもできます。いずれのメソッドでも、inplace 引数により、ソートにより新しいデータフレームを作成する (False) か、元のデータフレームを更新する (True) を指定できます。デフォルトは inplaceFalse になっており、これらのメソッドは新しいデータフレームを作成します。

[23]:
# iris_dデータフレームの4つ列の値に基づいて昇順にソート
sorted_iris = iris_d.sort_values(['sepal_length', 'sepal_width', 'petal_length', 'petal_width'])
sorted_iris.head(10)
[23]:
sepal_length sepal_width petal_length petal_width species
13 4.3 3.0 1.1 0.1 setosa
8 4.4 2.9 1.4 0.2 setosa
38 4.4 3.0 1.3 0.2 setosa
42 4.4 3.2 1.3 0.2 setosa
41 4.5 2.3 1.3 0.3 setosa
3 4.6 3.1 1.5 0.2 setosa
47 4.6 3.2 1.4 0.2 setosa
6 4.6 3.4 1.4 0.3 setosa
22 4.6 3.6 1.0 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa

列の値で降順にソートする場合は、sort_values() メソッドの ascending 引数を False にしてください。

[24]:
# iris_dデータフレームの4つ列の値に基づいて降順にソート
sorted_iris = iris_d.sort_values(['sepal_length', 'sepal_width', 'petal_length', 'petal_width'],ascending=False)
sorted_iris.head(10)
[24]:
sepal_length sepal_width petal_length petal_width species
131 7.9 3.8 6.4 2.0 virginica
117 7.7 3.8 6.7 2.2 virginica
135 7.7 3.0 6.1 2.3 virginica
122 7.7 2.8 6.7 2.0 virginica
118 7.7 2.6 6.9 2.3 virginica
105 7.6 3.0 6.6 2.1 virginica
130 7.4 2.8 6.1 1.9 virginica
107 7.3 2.9 6.3 1.8 virginica
109 7.2 3.6 6.1 2.5 virginica
125 7.2 3.2 6.0 1.8 virginica

データの統計量

データフレームオブジェクトの describe() メソッドで、データフレームの各列の要約統計量を求めることができます。要約統計量には平均、標準偏差、最大値、最小値などが含まれます。その他の統計量を求める pandas モジュールのメソッドは以下を参照してください。

pandasでの統計量計算

[25]:
# iris_dデータフレームの各数値列の要約統計量を表示
iris_d.describe()
[25]:
sepal_length sepal_width petal_length petal_width
count 150.000000 150.000000 150.000000 150.000000
mean 5.843333 3.054000 3.758667 1.198667
std 0.828066 0.433594 1.764420 0.763161
min 4.300000 2.000000 1.000000 0.100000
25% 5.100000 2.800000 1.600000 0.300000
50% 5.800000 3.000000 4.350000 1.300000
75% 6.400000 3.300000 5.100000 1.800000
max 7.900000 4.400000 6.900000 2.500000

▲データの連結

pandas モジュールの concat() 関数を用いると、データフレームを連結して新たなデータフレームを作成することができます。以下では、iris_d データフレームの先頭5行と最終5行を連結して、新しいデータフレームを作成しています。

[26]:
# iris_dデータフレームの先頭5行と最終5行を連結
concat_iris = pd.concat([iris_d[:5],iris_d[-5:]])
concat_iris
[26]:
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
145 6.7 3.0 5.2 2.3 virginica
146 6.3 2.5 5.0 1.9 virginica
147 6.5 3.0 5.2 2.0 virginica
148 6.2 3.4 5.4 2.3 virginica
149 5.9 3.0 5.1 1.8 virginica

concat() 関数の axis 引数に 1 を指定すると、以下のように、データフレームを列方向に連結することができます。

[27]:
# iris_dデータフレームの'sepal_length'列と'species'列を連結
sepal_len = pd.concat([iris_d.loc[:, ['sepal_length']],iris_d.loc[:, ['species']]], axis=1)
sepal_len.head(10)
[27]:
sepal_length species
0 5.1 setosa
1 4.9 setosa
2 4.7 setosa
3 4.6 setosa
4 5.0 setosa
5 5.4 setosa
6 4.6 setosa
7 5.0 setosa
8 4.4 setosa
9 4.9 setosa

▲データの結合

pandas モジュールの merge() 関数を用いると、任意の列の値をキーとして異なるデータフレームを結合することができます。結合のキーとする列名は on 引数で指定します。以下では、species の列の値をキーに、2つのデータフレーム、sepal_len, sepal_wid、を結合して新しいデータフレーム sepal を作成しています。

[28]:
# 'sepal_length'と'species'列からなる3行のデータ
sepal_len = pd.concat([iris_d.loc[[0,51,101],['sepal_length']],iris_d.loc[[0,51,101], ['species']]], axis=1)
# 'sepal_width'と'species'列からなる3行のデータ
sepal_wid = pd.concat([iris_d.loc[[0,51,101],['sepal_width']],iris_d.loc[[0,51,101], ['species']]], axis=1)

# sepal_lenとsepal_widを'species'をキーにして結合
sepal = pd.merge(sepal_len, sepal_wid, on='species')
sepal
[28]:
sepal_length species sepal_width
0 5.1 setosa 3.5
1 6.4 versicolor 3.2
2 5.8 virginica 2.7

▲データのグループ化

データフレームオブジェクトの groupby() メソッドを使うと、データフレームの任意の列の値に基づいて、同じ値を持つ行をグループにまとめることができます。列は複数指定することもできます。groupby() メソッドを適用するとグループ化オブジェクト (DataFrameGroupBy) が作成されますが、データフレームと同様の操作を多く適用することができます。

[29]:
# iris_dデータフレームの'species'の値で行をグループ化
iris_d.groupby('species')
[29]:
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x1127a6030>
[30]:
# グループごとの先頭5行を表示
iris_d.groupby('species').head(5)
[30]:
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
50 7.0 3.2 4.7 1.4 versicolor
51 6.4 3.2 4.5 1.5 versicolor
52 6.9 3.1 4.9 1.5 versicolor
53 5.5 2.3 4.0 1.3 versicolor
54 6.5 2.8 4.6 1.5 versicolor
100 6.3 3.3 6.0 2.5 virginica
101 5.8 2.7 5.1 1.9 virginica
102 7.1 3.0 5.9 2.1 virginica
103 6.3 2.9 5.6 1.8 virginica
104 6.5 3.0 5.8 2.2 virginica
[31]:
# グループごとの'sepal_length'列,'sepal_width'列の値の平均を表示
iris_d.groupby('species')[['sepal_length','sepal_width']].mean()
[31]:
sepal_length sepal_width
species
setosa 5.006 3.418
versicolor 5.936 2.770
virginica 6.588 2.974

▲欠損値、時系列データの処理

pandasでは、データ分析における欠損値、時系列データの処理を支援するための便利な機能が提供されています。詳細は以下を参照してください。

欠損値の処理

時系列データの処理

================================================ FILE: docs/7/7-2.html ================================================ 7-2. scikit-learnライブラリ — Pythonプログラミング入門 documentation

7-2. scikit-learnライブラリ

scikit-learnライブラリについて説明します。

参考

機械学習の各手法の詳細については以下を参考にしてください

scikit-learnライブラリには分類、回帰、クラスタリング、次元削減、前処理、モデル選択などの機械学習の処理を行うためのモジュールが含まれています。以下では、scikit-learnライブラリのモジュールの基本的な使い方について説明します。

機械学習について

機械学習では、観察されたデータをよく表すようにモデルのパラメータの調整を行います。パラメータを調整することでモデルをデータに適合させるので、「学習」と呼ばれます。学習されたモデルを使って、新たに観測されたデータに対して予測を行うことが可能になります。

教師あり学習

機械学習において、観測されたデータの特徴(特徴量)に対して、そのデータに関するラベルが存在する時、教師あり学習と呼びます。教師あり学習では、ラベルを教師として、データからそのラベルを予測するようなモデルを学習することになります。この時、ラベルが連続値であれば回帰、ラベルが離散値であれば分類の問題となります。

教師なし学習

ラベルが存在せず、観測されたデータの特徴のみからそのデータセットの構造やパターンをよく表すようなモデルを学習することを教師なし学習と呼びます。クラスタリングや次元削減は教師なし学習です。クラスタリングでは、観測されたデータをクラスタと呼ばれる集合にグループ分けします。次元削減では、データの特徴をより簡潔に(低い次元で)表現します。

データ

機械学習に用いるデータセットは、データフレームあるいは2次元の配列として表すことができます。行はデータセットの個々のデータを表し、列はデータが持つ特徴を表します。以下では、例として pandas モジュールの説明で用いたアイリスデータセットを表示しています。

[1]:
import pandas as pd
iris = pd.read_csv('iris.csv')
iris.head(5)
[1]:
sepal_length sepal_width petal_length petal_width species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa

データセットの各行は1つの花のデータに対応しており、行数はデータセットの花データの総数を表します。また、1列目から4列目までの各列は花の特徴(特徴量)に対応しています。scikit-learnでは、このデータと特徴量からなる2次元配列(行列)をNumPy配列または pandas のデータフレームに格納し、入力データとして処理します。5列目は、教師あり学習におけるデータのラベルに対応しており、ここでは各花データの花の種類(全部で3種類)を表しています。ラベルは通常1次元でデータの数だけの長さを持ち、NumPy配列または pandas のシリーズに格納します。先に述べた通り、ラベルが連続値であれば回帰、ラベルが離散値であれば分類の問題となります。機械学習では、特徴量からこのラベルを予測することになります。

アイリスデータセットはscikit-learnが持つデータセットにも含まれており、load_iris 関数によりアイリスデータセットの特徴量データとラベルデータを以下のようにNumPyの配列として取得することもできます。この時、ラベルは数値 (0, 1, 2) に置き換えられています。

[2]:
from sklearn.datasets import load_iris
iris = load_iris()
X_iris = iris.data
y_iris = iris.target

モデル学習の基礎

scikit-learnでは、以下の手順でデータからモデルの学習を行います。

  • 使用するモデルのクラスの選択

  • モデルのハイパーパラメータの選択とインスタンス化

  • データの準備

    • 教師あり学習では、特徴量データとラベルデータを準備

    • 教師あり学習では、特徴量・ラベルデータをモデル学習用の訓練データとモデル評価用のテストデータに分ける

    • 教師なし学習では、特徴量データを準備

  • モデルをデータに適合(fit() メソッド)

  • モデルの評価

    • 教師あり学習では、predict() メソッドを用いてテストデータの特徴量データからラベルデータを予測しその精度の評価を行う

    • 教師なし学習では、transform() または predict() メソッドを用いて特徴量データのクラスタリングや次元削減などを行う

教師あり学習・分類の例

以下では、アイリスデータセットを用いて花の4つの特徴から3つの花の種類を分類する手続きを示しています。scikit-learnでは、全てのモデルはPythonクラスとして実装されており、ここでは分類を行うモデルの1つであるロジスティック回帰 (LogisticRegression) クラスをインポートしています。

LogisticRegressionクラス

train_test_split() はデータセットを訓練データとテストデータに分割するための関数、accuracy_score() はモデルの予測精度を評価するための関数です。

特徴量データ (X_irist) とラベルデータ (y_iris) からなるデータセットを訓練データ (X_train, y_train) とテストデータ (X_test, y_test) に分割しています。ここでは、train_test_split() 関数の test_size 引数にデータセットの30%をテストデータとすることを指定しています。また、stratify 引数にラベルデータを指定することで、訓練データとテストデータ、それぞれでラベルの分布が同じになるようにしています。

ロジスティック回帰クラスのインスタンスを作成し、fit() メソッドによりモデルを訓練データに適合させています。そして、predict() メソッドを用いてテストデータの特徴量データ (X_test) のラベルを予測し、accuracy_score() 関数で実際のラベルデータ (y_test) と比較して予測精度の評価を行なっています。97%の精度で花の4つの特徴から3つの花の種類を分類できていることがわかります。

[3]:
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris

iris = load_iris()
X_iris = iris.data # 特徴量データ
y_iris = iris.target # ラベルデータ

# 訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X_iris, y_iris, test_size=0.3, random_state=1, stratify=y_iris)

# ロジスティック回帰モデル:solver引数には最適化手法を指定
model=LogisticRegression(solver='lbfgs')

model.fit(X_train, y_train) # モデルを訓練データに適合
y_predicted=model.predict(X_test) # テストデータでラベルを予測
accuracy_score(y_test, y_predicted) # 予測精度(accuracy)の評価
[3]:
0.9777777777777777

練習

アイリスデータセットの2つの特徴量、petal_lengthpetal_width、から2つの花の種類、versicolorvirginica、を予測するモデルをロジスティック回帰を用いて学習し、その予測精度を評価してください。以下では pandas データフレームの values 属性を用いてNumPy配列を取得しています。

[4]:
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

iris = pd.read_csv('iris.csv')
iris2=iris[(iris['species']=='versicolor')|(iris['species']=='virginica')]
X_iris=iris2[['petal_length','petal_width']].values
y_iris=iris2['species'].values

###  your code here

上記のコードが完成したら、以下のコードを実行して、2つの特徴量、petal_lengthpetal_width、から2つの花の種類、versicolorvirginica、を分類するための決定境界を可視化してみてください。model は上記の練習で学習されたモデルとします。決定境界は、学習の結果得られた、特徴量の空間においてラベル(クラス)間を分離する境界を表しています。

[5]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

w2 = model.coef_[0,1]
w1 = model.coef_[0,0]
w0 = model.intercept_[0]

line=np.linspace(3,7)
plt.plot(line, -(w1*line+w0)/w2)
y_c = (y_iris=='versicolor').astype(int)
plt.scatter(iris2['petal_length'],iris2['petal_width'],c=y_c);
../_images/7_7-2_14_0.png

教師あり学習・回帰の例

以下では、アイリスデータセットを用いて花の特徴の1つ、petal_length、からもう1つの特徴、petal_width、を回帰する手続きを示しています。この時、petal_length は特徴量、petal_width は連続値のラベルとなっています。まず、matplotlib の散布図を用いて petal_lengthpetal_width の関係を可視化してみましょう。関係があるといえそうでしょうか。

[6]:
iris = pd.read_csv('iris.csv')
X=iris[['petal_length']].values
y=iris['petal_width'].values
plt.scatter(X,y);
../_images/7_7-2_16_0.png

次に、回帰を行うモデルの1つである線形回帰 (LinearRegression) クラスをインポートしています。

LinearRegressionクラス

mean_squared_error() は平均二乗誤差によりモデルの予測精度を評価するための関数です。

データセットを訓練データ (X_train, y_train) とテストデータ (X_test, y_test) に分割し、線形回帰クラスのインスタンスの fit() メソッドによりモデルを訓練データに適合させています。そして、predict() メソッドを用いてテストデータの petal_length の値から petal_width の値を予測し、mean_squared_error() 関数で実際の petal_widthの値 (y_test) と比較して予測精度の評価を行なっています。

[7]:
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

# 訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1)

model=LinearRegression() # 線形回帰モデル
model.fit(X_train,y_train) # モデルを訓練データに適合
y_predicted=model.predict(X_test) # テストデータで予測
mean_squared_error(y_test,y_predicted) # 予測精度(平均二乗誤差)の評価
[7]:
np.float64(0.03974445760904273)

以下では、線形回帰モデルにより学習された petal_lengthpetal_width の関係を表す回帰式を可視化しています。学習された回帰式が実際のデータに適合していることがわかります。

[8]:
x_plot=np.linspace(1,7)
X_plot=x_plot[:,np.newaxis]
y_plot=model.predict(X_plot)
plt.scatter(X,y)
plt.plot(x_plot,y_plot);
../_images/7_7-2_20_0.png

教師なし学習・クラスタリングの例

以下では、アイリスデータセットを用いて花の2つの特徴量、petal_lenghとpetal_width、を元に花のデータをクラスタリングする手続きを示しています。ここではクラスタリングを行うモデルの1つである KMeans クラスをインポートしています。

KMeansクラス

特徴量データ (X_irist) を用意し、引数 n_clusters にハイパーパラメータとしてクラスタ数、ここでは 3、を指定して KMeans クラスのインスタンスを作成しています。そして、fit() メソッドによりモデルをデータに適合させ、predict() メソッドを用いて各データが所属するクラスタの情報 (y_km) を取得しています。

学習された各花データのクラスタ情報を元のデータセットのデータフレームに列として追加し、クラスタごとに異なる色でデータセットを可視化しています。2つの特徴量、petal_lenghpetal_width、に基づき、3つのクラスタが得られていることがわかります。

[9]:
from sklearn.cluster import KMeans

iris = pd.read_csv('iris.csv')
X_iris=iris[['petal_length', 'petal_width']].values

model = KMeans(n_clusters=3) # k-meansモデル
model.fit(X_iris) # モデルをデータに適合
y_km=model.predict(X_iris) # クラスタを予測

iris['cluster']=y_km
iris.plot.scatter(x='petal_length', y='petal_width', c='cluster', colormap='viridis');
../_images/7_7-2_22_0.png

3つのクラスタと3つの花の種類の分布を2つの特徴量、petal_lenghpetal_width、の空間で比較してみると、クラスタと花の種類には対応があり、2つの特徴量から花の種類をクラスタとしてグループ分けできていることがわかります。以下では可視化に seaborn モジュールを用いています。

[10]:
import seaborn as sns
sns.lmplot(x='petal_length',y='petal_width',hue='cluster',data=iris,fit_reg=False);
sns.lmplot(x='petal_length',y='petal_width',hue='species',data=iris,fit_reg=False);
../_images/7_7-2_24_0.png
../_images/7_7-2_24_1.png

練習

アイリスデータセットの2つの特徴量、sepal_lengthsepal_width、を元に、KMeans モデルを用いて花のデータをクラスタリングしてください。クラスタの数は任意に設定してください。

[11]:
from sklearn.cluster import KMeans
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

iris = pd.read_csv('iris.csv')
X_iris=iris[['sepal_length', 'sepal_width']].values

### your code here

教師なし学習・次元削減の例

以下では、アイリスデータセットを用いて花の4つの特徴量を元に花のデータを次元削減する手続きを示しています。ここでは次元削減を行うモデルの1つである PCA クラスをインポートしています。

PCAクラス

特徴量データ (X_irist) を用意し、引数 n_components にハイパーパラメータとして削減後の次元数、ここでは 2、を指定して PCA クラスのインスタンスを作成しています。そして、fit() メソッドによりモデルをデータに適合させ、transform() メソッドを用いて4つの特徴量を2次元に削減した特徴量データ (X_2d) を取得しています。

学習された各次元の値を元のデータセットのデータフレームに列として追加し、データセットを削減して得られた次元の空間において、データセットを花の種類ごとに異なる色で可視化しています。削減された次元の空間において、花の種類をグループ分けできていることがわかります。

[12]:
from sklearn.decomposition import PCA

iris = pd.read_csv('iris.csv')
X_iris=iris[['sepal_length', 'sepal_width', 'petal_length', 'petal_width']].values

model = PCA(n_components=2) # PCAモデル
model.fit(X_iris) # モデルをデータに適合
X_2d=model.transform(X_iris) # 次元削減
[13]:
import seaborn as sns
iris['pca1']=X_2d[:,0]
iris['pca2']=X_2d[:,1]
sns.lmplot(x='pca1',y='pca2',hue='species',data=iris,fit_reg=False);
../_images/7_7-2_29_0.png

練習の解答例

[14]:
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

iris = pd.read_csv('iris.csv')
iris2=iris[(iris['species']=='versicolor')|(iris['species']=='virginica')]
X_iris=iris2[['petal_length','petal_width']].values
y_iris=iris2['species'].values

X_train, X_test, y_train, y_test = train_test_split(X_iris, y_iris, test_size=0.3, random_state=1, stratify=y_iris)

model=LogisticRegression(solver='lbfgs')
model.fit(X_train, y_train)
y_model=model.predict(X_test)
accuracy_score(y_test, y_model)
[14]:
0.9666666666666667
[15]:
from sklearn.cluster import KMeans
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

iris = pd.read_csv('iris.csv')
X_iris=iris[['sepal_length', 'sepal_width']].values

model = KMeans(n_clusters=3)
model.fit(X_iris)
y_km=model.predict(X_iris)

iris['cluster']=y_km
iris.plot.scatter(x='sepal_length', y='sepal_width', c='cluster', colormap='viridis');
../_images/7_7-2_32_0.png
================================================ FILE: docs/_static/alabaster.css ================================================ /* -- page layout ----------------------------------------------------------- */ body { font-family: Georgia, serif; font-size: 17px; background-color: #fff; color: #000; margin: 0; padding: 0; } div.document { width: 940px; margin: 30px auto 0 auto; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 220px; } div.sphinxsidebar { width: 220px; font-size: 14px; line-height: 1.5; } hr { border: 1px solid #B1B4B6; } div.body { background-color: #fff; color: #3E4349; padding: 0 30px 0 30px; } div.body > .section { text-align: left; } div.footer { width: 940px; margin: 20px auto 30px auto; font-size: 14px; color: #888; text-align: right; } div.footer a { color: #888; } p.caption { font-family: inherit; font-size: inherit; } div.relations { display: none; } div.sphinxsidebar { max-height: 100%; overflow-y: auto; } div.sphinxsidebar a { color: #444; text-decoration: none; border-bottom: 1px dotted #999; } div.sphinxsidebar a:hover { border-bottom: 1px solid #999; } div.sphinxsidebarwrapper { padding: 18px 10px; } div.sphinxsidebarwrapper p.logo { padding: 0; margin: -10px 0 0 0px; text-align: center; } div.sphinxsidebarwrapper h1.logo { margin-top: -10px; text-align: center; margin-bottom: 5px; text-align: left; } div.sphinxsidebarwrapper h1.logo-name { margin-top: 0px; } div.sphinxsidebarwrapper p.blurb { margin-top: 0; font-style: normal; } div.sphinxsidebar h3, div.sphinxsidebar h4 { font-family: Georgia, serif; color: #444; font-size: 24px; font-weight: normal; margin: 0 0 5px 0; padding: 0; } div.sphinxsidebar h4 { font-size: 20px; } div.sphinxsidebar h3 a { color: #444; } div.sphinxsidebar p.logo a, div.sphinxsidebar h3 a, div.sphinxsidebar p.logo a:hover, div.sphinxsidebar h3 a:hover { border: none; } div.sphinxsidebar p { color: #555; margin: 10px 0; } div.sphinxsidebar ul { margin: 10px 0; padding: 0; color: #000; } div.sphinxsidebar ul li.toctree-l1 > a { font-size: 120%; } div.sphinxsidebar ul li.toctree-l2 > a { font-size: 110%; } div.sphinxsidebar input { border: 1px solid #CCC; font-family: Georgia, serif; font-size: 1em; } div.sphinxsidebar #searchbox { margin: 1em 0; } div.sphinxsidebar .search > div { display: table-cell; } div.sphinxsidebar hr { border: none; height: 1px; color: #AAA; background: #AAA; text-align: left; margin-left: 0; width: 50%; } div.sphinxsidebar .badge { border-bottom: none; } div.sphinxsidebar .badge:hover { border-bottom: none; } /* To address an issue with donation coming after search */ div.sphinxsidebar h3.donation { margin-top: 10px; } /* -- body styles ----------------------------------------------------------- */ a { color: #004B6B; text-decoration: underline; } a:hover { color: #6D4100; text-decoration: underline; } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: Georgia, serif; font-weight: normal; margin: 30px 0px 10px 0px; padding: 0; } div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } div.body h2 { font-size: 180%; } div.body h3 { font-size: 150%; } div.body h4 { font-size: 130%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 100%; } a.headerlink { color: #DDD; padding: 0 4px; text-decoration: none; } a.headerlink:hover { color: #444; background: #EAEAEA; } div.body p, div.body dd, div.body li { line-height: 1.4em; } div.admonition { margin: 20px 0px; padding: 10px 30px; background-color: #EEE; border: 1px solid #CCC; } div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { background-color: #FBFBFB; border-bottom: 1px solid #fafafa; } div.admonition p.admonition-title { font-family: Georgia, serif; font-weight: normal; font-size: 24px; margin: 0 0 10px 0; padding: 0; line-height: 1; } div.admonition p.last { margin-bottom: 0; } dt:target, .highlight { background: #FAF3E8; } div.warning { background-color: #FCC; border: 1px solid #FAA; } div.danger { background-color: #FCC; border: 1px solid #FAA; -moz-box-shadow: 2px 2px 4px #D52C2C; -webkit-box-shadow: 2px 2px 4px #D52C2C; box-shadow: 2px 2px 4px #D52C2C; } div.error { background-color: #FCC; border: 1px solid #FAA; -moz-box-shadow: 2px 2px 4px #D52C2C; -webkit-box-shadow: 2px 2px 4px #D52C2C; box-shadow: 2px 2px 4px #D52C2C; } div.caution { background-color: #FCC; border: 1px solid #FAA; } div.attention { background-color: #FCC; border: 1px solid #FAA; } div.important { background-color: #EEE; border: 1px solid #CCC; } div.note { background-color: #EEE; border: 1px solid #CCC; } div.tip { background-color: #EEE; border: 1px solid #CCC; } div.hint { background-color: #EEE; border: 1px solid #CCC; } div.seealso { background-color: #EEE; border: 1px solid #CCC; } div.topic { background-color: #EEE; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre, tt, code { font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 0.9em; } .hll { background-color: #FFC; margin: 0 -12px; padding: 0 12px; display: block; } img.screenshot { } tt.descname, tt.descclassname, code.descname, code.descclassname { font-size: 0.95em; } tt.descname, code.descname { padding-right: 0.08em; } img.screenshot { -moz-box-shadow: 2px 2px 4px #EEE; -webkit-box-shadow: 2px 2px 4px #EEE; box-shadow: 2px 2px 4px #EEE; } table.docutils { border: 1px solid #888; -moz-box-shadow: 2px 2px 4px #EEE; -webkit-box-shadow: 2px 2px 4px #EEE; box-shadow: 2px 2px 4px #EEE; } table.docutils td, table.docutils th { border: 1px solid #888; padding: 0.25em 0.7em; } table.field-list, table.footnote { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } table.footnote { margin: 15px 0; width: 100%; border: 1px solid #EEE; background: #FDFDFD; font-size: 0.9em; } table.footnote + table.footnote { margin-top: -15px; border-top: none; } table.field-list th { padding: 0 0.8em 0 0; } table.field-list td { padding: 0; } table.field-list p { margin-bottom: 0.8em; } /* Cloned from * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 */ .field-name { -moz-hyphens: manual; -ms-hyphens: manual; -webkit-hyphens: manual; hyphens: manual; } table.footnote td.label { width: .1px; padding: 0.3em 0 0.3em 0.5em; } table.footnote td { padding: 0.3em 0.5em; } dl { margin-left: 0; margin-right: 0; margin-top: 0; padding: 0; } dl dd { margin-left: 30px; } blockquote { margin: 0 0 0 30px; padding: 0; } ul, ol { /* Matches the 30px from the narrow-screen "li > ul" selector below */ margin: 10px 0 10px 30px; padding: 0; } pre { background: unset; padding: 7px 30px; margin: 15px 0px; line-height: 1.3em; } div.viewcode-block:target { background: #ffd; } dl pre, blockquote pre, li pre { margin-left: 0; padding-left: 30px; } tt, code { background-color: #ecf0f3; color: #222; /* padding: 1px 2px; */ } tt.xref, code.xref, a tt { background-color: #FBFBFB; border-bottom: 1px solid #fff; } a.reference { text-decoration: none; border-bottom: 1px dotted #004B6B; } a.reference:hover { border-bottom: 1px solid #6D4100; } /* Don't put an underline on images */ a.image-reference, a.image-reference:hover { border-bottom: none; } a.footnote-reference { text-decoration: none; font-size: 0.7em; vertical-align: top; border-bottom: 1px dotted #004B6B; } a.footnote-reference:hover { border-bottom: 1px solid #6D4100; } a:hover tt, a:hover code { background: #EEE; } @media screen and (max-width: 940px) { body { margin: 0; padding: 20px 30px; } div.documentwrapper { float: none; background: #fff; margin-left: 0; margin-top: 0; margin-right: 0; margin-bottom: 0; } div.sphinxsidebar { display: block; float: none; width: unset; margin: 50px -30px -20px -30px; padding: 10px 20px; background: #333; color: #FFF; } div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, div.sphinxsidebar h3 a { color: #fff; } div.sphinxsidebar a { color: #AAA; } div.sphinxsidebar p.logo { display: none; } div.document { width: 100%; margin: 0; } div.footer { display: none; } div.bodywrapper { margin: 0; } div.body { min-height: 0; min-width: auto; /* fixes width on small screens, breaks .hll */ padding: 0; } .hll { /* "fixes" the breakage */ width: max-content; } .rtd_doc_footer { display: none; } .document { width: auto; } .footer { width: auto; } .github { display: none; } ul { margin-left: 0; } li > ul { /* Matches the 30px from the "ul, ol" selector above */ margin-left: 30px; } } /* misc. */ .revsys-inline { display: none!important; } /* Hide ugly table cell borders in ..bibliography:: directive output */ table.docutils.citation, table.docutils.citation td, table.docutils.citation th { border: none; /* Below needed in some edge cases; if not applied, bottom shadows appear */ -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } /* relbar */ .related { line-height: 30px; width: 100%; font-size: 0.9rem; } .related.top { border-bottom: 1px solid #EEE; margin-bottom: 20px; } .related.bottom { border-top: 1px solid #EEE; } .related ul { padding: 0; margin: 0; list-style: none; } .related li { display: inline; } nav#rellinks { float: right; } nav#rellinks li+li:before { content: "|"; } nav#breadcrumbs li+li:before { content: "\00BB"; } /* Hide certain items when printing */ @media print { div.related { display: none; } } img.github { position: absolute; top: 0; border: 0; right: 0; } ================================================ FILE: docs/_static/basic.css ================================================ /* * basic.css * ~~~~~~~~~ * * Sphinx stylesheet -- basic theme. * * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ /* -- main layout ----------------------------------------------------------- */ div.clearer { clear: both; } div.section::after { display: block; content: ''; clear: left; } /* -- relbar ---------------------------------------------------------------- */ div.related { width: 100%; font-size: 90%; } div.related h3 { display: none; } div.related ul { margin: 0; padding: 0 0 0 10px; list-style: none; } div.related li { display: inline; } div.related li.right { float: right; margin-right: 5px; } /* -- sidebar --------------------------------------------------------------- */ div.sphinxsidebarwrapper { padding: 10px 5px 0 10px; } div.sphinxsidebar { float: left; width: 230px; margin-left: -100%; font-size: 90%; word-wrap: break-word; overflow-wrap : break-word; } div.sphinxsidebar ul { list-style: none; } div.sphinxsidebar ul ul, div.sphinxsidebar ul.want-points { margin-left: 20px; list-style: square; } div.sphinxsidebar ul ul { margin-top: 0; margin-bottom: 0; } div.sphinxsidebar form { margin-top: 10px; } div.sphinxsidebar input { border: 1px solid #98dbcc; font-family: sans-serif; font-size: 1em; } div.sphinxsidebar #searchbox form.search { overflow: hidden; } div.sphinxsidebar #searchbox input[type="text"] { float: left; width: 80%; padding: 0.25em; box-sizing: border-box; } div.sphinxsidebar #searchbox input[type="submit"] { float: left; width: 20%; border-left: none; padding: 0.25em; box-sizing: border-box; } img { border: 0; max-width: 100%; } /* -- search page ----------------------------------------------------------- */ ul.search { margin: 10px 0 0 20px; padding: 0; } ul.search li { padding: 5px 0 5px 20px; background-image: url(file.png); background-repeat: no-repeat; background-position: 0 7px; } ul.search li a { font-weight: bold; } ul.search li p.context { color: #888; margin: 2px 0 0 30px; text-align: left; } ul.keywordmatches li.goodmatch a { font-weight: bold; } /* -- index page ------------------------------------------------------------ */ table.contentstable { width: 90%; margin-left: auto; margin-right: auto; } table.contentstable p.biglink { line-height: 150%; } a.biglink { font-size: 1.3em; } span.linkdescr { font-style: italic; padding-top: 5px; font-size: 90%; } /* -- general index --------------------------------------------------------- */ table.indextable { width: 100%; } table.indextable td { text-align: left; vertical-align: top; } table.indextable ul { margin-top: 0; margin-bottom: 0; list-style-type: none; } table.indextable > tbody > tr > td > ul { padding-left: 0em; } table.indextable tr.pcap { height: 10px; } table.indextable tr.cap { margin-top: 10px; background-color: #f2f2f2; } img.toggler { margin-right: 3px; margin-top: 3px; cursor: pointer; } div.modindex-jumpbox { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; margin: 1em 0 1em 0; padding: 0.4em; } div.genindex-jumpbox { border-top: 1px solid #ddd; border-bottom: 1px solid #ddd; margin: 1em 0 1em 0; padding: 0.4em; } /* -- domain module index --------------------------------------------------- */ table.modindextable td { padding: 2px; border-collapse: collapse; } /* -- general body styles --------------------------------------------------- */ div.body { min-width: inherit; max-width: 800px; } div.body p, div.body dd, div.body li, div.body blockquote { -moz-hyphens: auto; -ms-hyphens: auto; -webkit-hyphens: auto; hyphens: auto; } a.headerlink { visibility: hidden; } a:visited { color: #551A8B; } h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink, h4:hover > a.headerlink, h5:hover > a.headerlink, h6:hover > a.headerlink, dt:hover > a.headerlink, caption:hover > a.headerlink, p.caption:hover > a.headerlink, div.code-block-caption:hover > a.headerlink { visibility: visible; } div.body p.caption { text-align: inherit; } div.body td { text-align: left; } .first { margin-top: 0 !important; } p.rubric { margin-top: 30px; font-weight: bold; } img.align-left, figure.align-left, .figure.align-left, object.align-left { clear: left; float: left; margin-right: 1em; } img.align-right, figure.align-right, .figure.align-right, object.align-right { clear: right; float: right; margin-left: 1em; } img.align-center, figure.align-center, .figure.align-center, object.align-center { display: block; margin-left: auto; margin-right: auto; } img.align-default, figure.align-default, .figure.align-default { display: block; margin-left: auto; margin-right: auto; } .align-left { text-align: left; } .align-center { text-align: center; } .align-default { text-align: center; } .align-right { text-align: right; } /* -- sidebars -------------------------------------------------------------- */ div.sidebar, aside.sidebar { margin: 0 0 0.5em 1em; border: 1px solid #ddb; padding: 7px; background-color: #ffe; width: 40%; float: right; clear: right; overflow-x: auto; } p.sidebar-title { font-weight: bold; } nav.contents, aside.topic, div.admonition, div.topic, blockquote { clear: left; } /* -- topics ---------------------------------------------------------------- */ nav.contents, aside.topic, div.topic { border: 1px solid #ccc; padding: 7px; margin: 10px 0 10px 0; } p.topic-title { font-size: 1.1em; font-weight: bold; margin-top: 10px; } /* -- admonitions ----------------------------------------------------------- */ div.admonition { margin-top: 10px; margin-bottom: 10px; padding: 7px; } div.admonition dt { font-weight: bold; } p.admonition-title { margin: 0px 10px 5px 0px; font-weight: bold; } div.body p.centered { text-align: center; margin-top: 25px; } /* -- content of sidebars/topics/admonitions -------------------------------- */ div.sidebar > :last-child, aside.sidebar > :last-child, nav.contents > :last-child, aside.topic > :last-child, div.topic > :last-child, div.admonition > :last-child { margin-bottom: 0; } div.sidebar::after, aside.sidebar::after, nav.contents::after, aside.topic::after, div.topic::after, div.admonition::after, blockquote::after { display: block; content: ''; clear: both; } /* -- tables ---------------------------------------------------------------- */ table.docutils { margin-top: 10px; margin-bottom: 10px; border: 0; border-collapse: collapse; } table.align-center { margin-left: auto; margin-right: auto; } table.align-default { margin-left: auto; margin-right: auto; } table caption span.caption-number { font-style: italic; } table caption span.caption-text { } table.docutils td, table.docutils th { padding: 1px 8px 1px 5px; border-top: 0; border-left: 0; border-right: 0; border-bottom: 1px solid #aaa; } th { text-align: left; padding-right: 5px; } table.citation { border-left: solid 1px gray; margin-left: 1px; } table.citation td { border-bottom: none; } th > :first-child, td > :first-child { margin-top: 0px; } th > :last-child, td > :last-child { margin-bottom: 0px; } /* -- figures --------------------------------------------------------------- */ div.figure, figure { margin: 0.5em; padding: 0.5em; } div.figure p.caption, figcaption { padding: 0.3em; } div.figure p.caption span.caption-number, figcaption span.caption-number { font-style: italic; } div.figure p.caption span.caption-text, figcaption span.caption-text { } /* -- field list styles ----------------------------------------------------- */ table.field-list td, table.field-list th { border: 0 !important; } .field-list ul { margin: 0; padding-left: 1em; } .field-list p { margin: 0; } .field-name { -moz-hyphens: manual; -ms-hyphens: manual; -webkit-hyphens: manual; hyphens: manual; } /* -- hlist styles ---------------------------------------------------------- */ table.hlist { margin: 1em 0; } table.hlist td { vertical-align: top; } /* -- object description styles --------------------------------------------- */ .sig { font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; } .sig-name, code.descname { background-color: transparent; font-weight: bold; } .sig-name { font-size: 1.1em; } code.descname { font-size: 1.2em; } .sig-prename, code.descclassname { background-color: transparent; } .optional { font-size: 1.3em; } .sig-paren { font-size: larger; } .sig-param.n { font-style: italic; } /* C++ specific styling */ .sig-inline.c-texpr, .sig-inline.cpp-texpr { font-family: unset; } .sig.c .k, .sig.c .kt, .sig.cpp .k, .sig.cpp .kt { color: #0033B3; } .sig.c .m, .sig.cpp .m { color: #1750EB; } .sig.c .s, .sig.c .sc, .sig.cpp .s, .sig.cpp .sc { color: #067D17; } /* -- other body styles ----------------------------------------------------- */ ol.arabic { list-style: decimal; } ol.loweralpha { list-style: lower-alpha; } ol.upperalpha { list-style: upper-alpha; } ol.lowerroman { list-style: lower-roman; } ol.upperroman { list-style: upper-roman; } :not(li) > ol > li:first-child > :first-child, :not(li) > ul > li:first-child > :first-child { margin-top: 0px; } :not(li) > ol > li:last-child > :last-child, :not(li) > ul > li:last-child > :last-child { margin-bottom: 0px; } ol.simple ol p, ol.simple ul p, ul.simple ol p, ul.simple ul p { margin-top: 0; } ol.simple > li:not(:first-child) > p, ul.simple > li:not(:first-child) > p { margin-top: 0; } ol.simple p, ul.simple p { margin-bottom: 0; } aside.footnote > span, div.citation > span { float: left; } aside.footnote > span:last-of-type, div.citation > span:last-of-type { padding-right: 0.5em; } aside.footnote > p { margin-left: 2em; } div.citation > p { margin-left: 4em; } aside.footnote > p:last-of-type, div.citation > p:last-of-type { margin-bottom: 0em; } aside.footnote > p:last-of-type:after, div.citation > p:last-of-type:after { content: ""; clear: both; } dl.field-list { display: grid; grid-template-columns: fit-content(30%) auto; } dl.field-list > dt { font-weight: bold; word-break: break-word; padding-left: 0.5em; padding-right: 5px; } dl.field-list > dd { padding-left: 0.5em; margin-top: 0em; margin-left: 0em; margin-bottom: 0em; } dl { margin-bottom: 15px; } dd > :first-child { margin-top: 0px; } dd ul, dd table { margin-bottom: 10px; } dd { margin-top: 3px; margin-bottom: 10px; margin-left: 30px; } .sig dd { margin-top: 0px; margin-bottom: 0px; } .sig dl { margin-top: 0px; margin-bottom: 0px; } dl > dd:last-child, dl > dd:last-child > :last-child { margin-bottom: 0; } dt:target, span.highlighted { background-color: #fbe54e; } rect.highlighted { fill: #fbe54e; } dl.glossary dt { font-weight: bold; font-size: 1.1em; } .versionmodified { font-style: italic; } .system-message { background-color: #fda; padding: 5px; border: 3px solid red; } .footnote:target { background-color: #ffa; } .line-block { display: block; margin-top: 1em; margin-bottom: 1em; } .line-block .line-block { margin-top: 0; margin-bottom: 0; margin-left: 1.5em; } .guilabel, .menuselection { font-family: sans-serif; } .accelerator { text-decoration: underline; } .classifier { font-style: oblique; } .classifier:before { font-style: normal; margin: 0 0.5em; content: ":"; display: inline-block; } abbr, acronym { border-bottom: dotted 1px; cursor: help; } .translated { background-color: rgba(207, 255, 207, 0.2) } .untranslated { background-color: rgba(255, 207, 207, 0.2) } /* -- code displays --------------------------------------------------------- */ pre { overflow: auto; overflow-y: hidden; /* fixes display issues on Chrome browsers */ } pre, div[class*="highlight-"] { clear: both; } span.pre { -moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none; white-space: nowrap; } div[class*="highlight-"] { margin: 1em 0; } td.linenos pre { border: 0; background-color: transparent; color: #aaa; } table.highlighttable { display: block; } table.highlighttable tbody { display: block; } table.highlighttable tr { display: flex; } table.highlighttable td { margin: 0; padding: 0; } table.highlighttable td.linenos { padding-right: 0.5em; } table.highlighttable td.code { flex: 1; overflow: hidden; } .highlight .hll { display: block; } div.highlight pre, table.highlighttable pre { margin: 0; } div.code-block-caption + div { margin-top: 0; } div.code-block-caption { margin-top: 1em; padding: 2px 5px; font-size: small; } div.code-block-caption code { background-color: transparent; } table.highlighttable td.linenos, span.linenos, div.highlight span.gp { /* gp: Generic.Prompt */ user-select: none; -webkit-user-select: text; /* Safari fallback only */ -webkit-user-select: none; /* Chrome/Safari */ -moz-user-select: none; /* Firefox */ -ms-user-select: none; /* IE10+ */ } div.code-block-caption span.caption-number { padding: 0.1em 0.3em; font-style: italic; } div.code-block-caption span.caption-text { } div.literal-block-wrapper { margin: 1em 0; } code.xref, a code { background-color: transparent; font-weight: bold; } h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { background-color: transparent; } .viewcode-link { float: right; } .viewcode-back { float: right; font-family: sans-serif; } div.viewcode-block:target { margin: -1px -10px; padding: 0 10px; } /* -- math display ---------------------------------------------------------- */ img.math { vertical-align: middle; } div.body div.math p { text-align: center; } span.eqno { float: right; } span.eqno a.headerlink { position: absolute; z-index: 1; } div.math:hover a.headerlink { visibility: visible; } /* -- printout stylesheet --------------------------------------------------- */ @media print { div.document, div.documentwrapper, div.bodywrapper { margin: 0 !important; width: 100%; } div.sphinxsidebar, div.related, div.footer, #top-link { display: none; } } ================================================ FILE: docs/_static/custom.css ================================================ @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap'); body,h1,h2,h3,h4,h5,h6,p,a,li { font-family: 'Noto Sans JP', sans-serif !important; } ================================================ FILE: docs/_static/custom.css~ ================================================ @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap'); body,h1,h2,h3,h4,h5,h6,p,a,li { font-family: 'Noto Sans JP', sans-serif; } ================================================ FILE: docs/_static/doctools.js ================================================ /* * doctools.js * ~~~~~~~~~~~ * * Base JavaScript utilities for all Sphinx HTML documentation. * * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ "use strict"; const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ "TEXTAREA", "INPUT", "SELECT", "BUTTON", ]); const _ready = (callback) => { if (document.readyState !== "loading") { callback(); } else { document.addEventListener("DOMContentLoaded", callback); } }; /** * Small JavaScript module for the documentation. */ const Documentation = { init: () => { Documentation.initDomainIndexTable(); Documentation.initOnKeyListeners(); }, /** * i18n support */ TRANSLATIONS: {}, PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), LOCALE: "unknown", // gettext and ngettext don't access this so that the functions // can safely bound to a different name (_ = Documentation.gettext) gettext: (string) => { const translated = Documentation.TRANSLATIONS[string]; switch (typeof translated) { case "undefined": return string; // no translation case "string": return translated; // translation exists default: return translated[0]; // (singular, plural) translation tuple exists } }, ngettext: (singular, plural, n) => { const translated = Documentation.TRANSLATIONS[singular]; if (typeof translated !== "undefined") return translated[Documentation.PLURAL_EXPR(n)]; return n === 1 ? singular : plural; }, addTranslations: (catalog) => { Object.assign(Documentation.TRANSLATIONS, catalog.messages); Documentation.PLURAL_EXPR = new Function( "n", `return (${catalog.plural_expr})` ); Documentation.LOCALE = catalog.locale; }, /** * helper function to focus on search bar */ focusSearchBar: () => { document.querySelectorAll("input[name=q]")[0]?.focus(); }, /** * Initialise the domain index toggle buttons */ initDomainIndexTable: () => { const toggler = (el) => { const idNumber = el.id.substr(7); const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); if (el.src.substr(-9) === "minus.png") { el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; toggledRows.forEach((el) => (el.style.display = "none")); } else { el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; toggledRows.forEach((el) => (el.style.display = "")); } }; const togglerElements = document.querySelectorAll("img.toggler"); togglerElements.forEach((el) => el.addEventListener("click", (event) => toggler(event.currentTarget)) ); togglerElements.forEach((el) => (el.style.display = "")); if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); }, initOnKeyListeners: () => { // only install a listener if it is really needed if ( !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS ) return; document.addEventListener("keydown", (event) => { // bail for input elements if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; // bail with special keys if (event.altKey || event.ctrlKey || event.metaKey) return; if (!event.shiftKey) { switch (event.key) { case "ArrowLeft": if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; const prevLink = document.querySelector('link[rel="prev"]'); if (prevLink && prevLink.href) { window.location.href = prevLink.href; event.preventDefault(); } break; case "ArrowRight": if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; const nextLink = document.querySelector('link[rel="next"]'); if (nextLink && nextLink.href) { window.location.href = nextLink.href; event.preventDefault(); } break; } } // some keyboard layouts may need Shift to get / switch (event.key) { case "/": if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; Documentation.focusSearchBar(); event.preventDefault(); } }); }, }; // quick alias for translations const _ = Documentation.gettext; _ready(Documentation.init); ================================================ FILE: docs/_static/documentation_options.js ================================================ const DOCUMENTATION_OPTIONS = { VERSION: '', LANGUAGE: 'jp', COLLAPSE_INDEX: false, BUILDER: 'html', FILE_SUFFIX: '.html', LINK_SUFFIX: '.html', HAS_SOURCE: true, SOURCELINK_SUFFIX: '.txt', NAVIGATION_WITH_KEYS: false, SHOW_SEARCH_SUMMARY: true, ENABLE_SEARCH_SHORTCUTS: true, }; ================================================ FILE: docs/_static/language_data.js ================================================ /* * language_data.js * ~~~~~~~~~~~~~~~~ * * This script contains the language-specific data used by searchtools.js, * namely the list of stopwords, stemmer, scorer and splitter. * * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ var stopwords = []; /* Non-minified version is copied as a separate JS file, if available */ /** * Dummy stemmer for languages without stemming rules. */ var Stemmer = function() { this.stemWord = function(w) { return w; } } ================================================ FILE: docs/_static/nbsphinx-code-cells.css ================================================ /* remove conflicting styling from Sphinx themes */ div.nbinput.container div.prompt *, div.nboutput.container div.prompt *, div.nbinput.container div.input_area pre, div.nboutput.container div.output_area pre, div.nbinput.container div.input_area .highlight, div.nboutput.container div.output_area .highlight { border: none; padding: 0; margin: 0; box-shadow: none; } div.nbinput.container > div[class*=highlight], div.nboutput.container > div[class*=highlight] { margin: 0; } div.nbinput.container div.prompt *, div.nboutput.container div.prompt * { background: none; } div.nboutput.container div.output_area .highlight, div.nboutput.container div.output_area pre { background: unset; } div.nboutput.container div.output_area div.highlight { color: unset; /* override Pygments text color */ } /* avoid gaps between output lines */ div.nboutput.container div[class*=highlight] pre { line-height: normal; } /* input/output containers */ div.nbinput.container, div.nboutput.container { display: -webkit-flex; display: flex; align-items: flex-start; margin: 0; width: 100%; } @media (max-width: 540px) { div.nbinput.container, div.nboutput.container { flex-direction: column; } } /* input container */ div.nbinput.container { padding-top: 5px; } /* last container */ div.nblast.container { padding-bottom: 5px; } /* input prompt */ div.nbinput.container div.prompt pre, /* for sphinx_immaterial theme: */ div.nbinput.container div.prompt pre > code { color: #307FC1; } /* output prompt */ div.nboutput.container div.prompt pre, /* for sphinx_immaterial theme: */ div.nboutput.container div.prompt pre > code { color: #BF5B3D; } /* all prompts */ div.nbinput.container div.prompt, div.nboutput.container div.prompt { width: 4.5ex; padding-top: 5px; position: relative; user-select: none; } div.nbinput.container div.prompt > div, div.nboutput.container div.prompt > div { position: absolute; right: 0; margin-right: 0.3ex; } @media (max-width: 540px) { div.nbinput.container div.prompt, div.nboutput.container div.prompt { width: unset; text-align: left; padding: 0.4em; } div.nboutput.container div.prompt.empty { padding: 0; } div.nbinput.container div.prompt > div, div.nboutput.container div.prompt > div { position: unset; } } /* disable scrollbars and line breaks on prompts */ div.nbinput.container div.prompt pre, div.nboutput.container div.prompt pre { overflow: hidden; white-space: pre; } /* input/output area */ div.nbinput.container div.input_area, div.nboutput.container div.output_area { -webkit-flex: 1; flex: 1; overflow: auto; } @media (max-width: 540px) { div.nbinput.container div.input_area, div.nboutput.container div.output_area { width: 100%; } } /* input area */ div.nbinput.container div.input_area { border: 1px solid #e0e0e0; border-radius: 2px; /*background: #f5f5f5;*/ } /* override MathJax center alignment in output cells */ div.nboutput.container div[class*=MathJax] { text-align: left !important; } /* override sphinx.ext.imgmath center alignment in output cells */ div.nboutput.container div.math p { text-align: left; } /* standard error */ div.nboutput.container div.output_area.stderr { background: #fdd; } /* ANSI colors */ .ansi-black-fg { color: #3E424D; } .ansi-black-bg { background-color: #3E424D; } .ansi-black-intense-fg { color: #282C36; } .ansi-black-intense-bg { background-color: #282C36; } .ansi-red-fg { color: #E75C58; } .ansi-red-bg { background-color: #E75C58; } .ansi-red-intense-fg { color: #B22B31; } .ansi-red-intense-bg { background-color: #B22B31; } .ansi-green-fg { color: #00A250; } .ansi-green-bg { background-color: #00A250; } .ansi-green-intense-fg { color: #007427; } .ansi-green-intense-bg { background-color: #007427; } .ansi-yellow-fg { color: #DDB62B; } .ansi-yellow-bg { background-color: #DDB62B; } .ansi-yellow-intense-fg { color: #B27D12; } .ansi-yellow-intense-bg { background-color: #B27D12; } .ansi-blue-fg { color: #208FFB; } .ansi-blue-bg { background-color: #208FFB; } .ansi-blue-intense-fg { color: #0065CA; } .ansi-blue-intense-bg { background-color: #0065CA; } .ansi-magenta-fg { color: #D160C4; } .ansi-magenta-bg { background-color: #D160C4; } .ansi-magenta-intense-fg { color: #A03196; } .ansi-magenta-intense-bg { background-color: #A03196; } .ansi-cyan-fg { color: #60C6C8; } .ansi-cyan-bg { background-color: #60C6C8; } .ansi-cyan-intense-fg { color: #258F8F; } .ansi-cyan-intense-bg { background-color: #258F8F; } .ansi-white-fg { color: #C5C1B4; } .ansi-white-bg { background-color: #C5C1B4; } .ansi-white-intense-fg { color: #A1A6B2; } .ansi-white-intense-bg { background-color: #A1A6B2; } .ansi-default-inverse-fg { color: #FFFFFF; } .ansi-default-inverse-bg { background-color: #000000; } .ansi-bold { font-weight: bold; } .ansi-underline { text-decoration: underline; } div.nbinput.container div.input_area div[class*=highlight] > pre, div.nboutput.container div.output_area div[class*=highlight] > pre, div.nboutput.container div.output_area div[class*=highlight].math, div.nboutput.container div.output_area.rendered_html, div.nboutput.container div.output_area > div.output_javascript, div.nboutput.container div.output_area:not(.rendered_html) > img{ padding: 5px; margin: 0; } /* fix copybtn overflow problem in chromium (needed for 'sphinx_copybutton') */ div.nbinput.container div.input_area > div[class^='highlight'], div.nboutput.container div.output_area > div[class^='highlight']{ overflow-y: hidden; } /* hide copy button on prompts for 'sphinx_copybutton' extension ... */ .prompt .copybtn, /* ... and 'sphinx_immaterial' theme */ .prompt .md-clipboard.md-icon { display: none; } /* Some additional styling taken form the Jupyter notebook CSS */ .jp-RenderedHTMLCommon table, div.rendered_html table { border: none; border-collapse: collapse; border-spacing: 0; color: black; font-size: 12px; table-layout: fixed; } .jp-RenderedHTMLCommon thead, div.rendered_html thead { border-bottom: 1px solid black; vertical-align: bottom; } .jp-RenderedHTMLCommon tr, .jp-RenderedHTMLCommon th, .jp-RenderedHTMLCommon td, div.rendered_html tr, div.rendered_html th, div.rendered_html td { text-align: right; vertical-align: middle; padding: 0.5em 0.5em; line-height: normal; white-space: normal; max-width: none; border: none; } .jp-RenderedHTMLCommon th, div.rendered_html th { font-weight: bold; } .jp-RenderedHTMLCommon tbody tr:nth-child(odd), div.rendered_html tbody tr:nth-child(odd) { background: #f5f5f5; } .jp-RenderedHTMLCommon tbody tr:hover, div.rendered_html tbody tr:hover { background: rgba(66, 165, 245, 0.2); } ================================================ FILE: docs/_static/nbsphinx-gallery.css ================================================ .nbsphinx-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 5px; margin-top: 1em; margin-bottom: 1em; } .nbsphinx-gallery > a { padding: 5px; border: 1px dotted currentColor; border-radius: 2px; text-align: center; } .nbsphinx-gallery > a:hover { border-style: solid; } .nbsphinx-gallery img { max-width: 100%; max-height: 100%; } .nbsphinx-gallery > a > div:first-child { display: flex; align-items: start; justify-content: center; height: 120px; margin-bottom: 5px; } ================================================ FILE: docs/_static/pygments.css ================================================ pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #f8f8f8; } .highlight .c { color: #8f5902; font-style: italic } /* Comment */ .highlight .err { color: #a40000; border: 1px solid #ef2929 } /* Error */ .highlight .g { color: #000000 } /* Generic */ .highlight .k { color: #004461; font-weight: bold } /* Keyword */ .highlight .l { color: #000000 } /* Literal */ .highlight .n { color: #000000 } /* Name */ .highlight .o { color: #582800 } /* Operator */ .highlight .x { color: #000000 } /* Other */ .highlight .p { color: #000000; font-weight: bold } /* Punctuation */ .highlight .ch { color: #8f5902; font-style: italic } /* Comment.Hashbang */ .highlight .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */ .highlight .cp { color: #8f5902 } /* Comment.Preproc */ .highlight .cpf { color: #8f5902; font-style: italic } /* Comment.PreprocFile */ .highlight .c1 { color: #8f5902; font-style: italic } /* Comment.Single */ .highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */ .highlight .gd { color: #a40000 } /* Generic.Deleted */ .highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */ .highlight .ges { color: #000000 } /* Generic.EmphStrong */ .highlight .gr { color: #ef2929 } /* Generic.Error */ .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ .highlight .gi { color: #00A000 } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #745334 } /* Generic.Prompt */ .highlight .gs { color: #000000; font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ .highlight .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */ .highlight .kc { color: #004461; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #004461; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #004461; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #004461; font-weight: bold } /* Keyword.Pseudo */ .highlight .kr { color: #004461; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #004461; font-weight: bold } /* Keyword.Type */ .highlight .ld { color: #000000 } /* Literal.Date */ .highlight .m { color: #990000 } /* Literal.Number */ .highlight .s { color: #4e9a06 } /* Literal.String */ .highlight .na { color: #c4a000 } /* Name.Attribute */ .highlight .nb { color: #004461 } /* Name.Builtin */ .highlight .nc { color: #000000 } /* Name.Class */ .highlight .no { color: #000000 } /* Name.Constant */ .highlight .nd { color: #888888 } /* Name.Decorator */ .highlight .ni { color: #ce5c00 } /* Name.Entity */ .highlight .ne { color: #cc0000; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #000000 } /* Name.Function */ .highlight .nl { color: #f57900 } /* Name.Label */ .highlight .nn { color: #000000 } /* Name.Namespace */ .highlight .nx { color: #000000 } /* Name.Other */ .highlight .py { color: #000000 } /* Name.Property */ .highlight .nt { color: #004461; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #000000 } /* Name.Variable */ .highlight .ow { color: #004461; font-weight: bold } /* Operator.Word */ .highlight .pm { color: #000000; font-weight: bold } /* Punctuation.Marker */ .highlight .w { color: #f8f8f8 } /* Text.Whitespace */ .highlight .mb { color: #990000 } /* Literal.Number.Bin */ .highlight .mf { color: #990000 } /* Literal.Number.Float */ .highlight .mh { color: #990000 } /* Literal.Number.Hex */ .highlight .mi { color: #990000 } /* Literal.Number.Integer */ .highlight .mo { color: #990000 } /* Literal.Number.Oct */ .highlight .sa { color: #4e9a06 } /* Literal.String.Affix */ .highlight .sb { color: #4e9a06 } /* Literal.String.Backtick */ .highlight .sc { color: #4e9a06 } /* Literal.String.Char */ .highlight .dl { color: #4e9a06 } /* Literal.String.Delimiter */ .highlight .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */ .highlight .s2 { color: #4e9a06 } /* Literal.String.Double */ .highlight .se { color: #4e9a06 } /* Literal.String.Escape */ .highlight .sh { color: #4e9a06 } /* Literal.String.Heredoc */ .highlight .si { color: #4e9a06 } /* Literal.String.Interpol */ .highlight .sx { color: #4e9a06 } /* Literal.String.Other */ .highlight .sr { color: #4e9a06 } /* Literal.String.Regex */ .highlight .s1 { color: #4e9a06 } /* Literal.String.Single */ .highlight .ss { color: #4e9a06 } /* Literal.String.Symbol */ .highlight .bp { color: #3465a4 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #000000 } /* Name.Function.Magic */ .highlight .vc { color: #000000 } /* Name.Variable.Class */ .highlight .vg { color: #000000 } /* Name.Variable.Global */ .highlight .vi { color: #000000 } /* Name.Variable.Instance */ .highlight .vm { color: #000000 } /* Name.Variable.Magic */ .highlight .il { color: #990000 } /* Literal.Number.Integer.Long */ ================================================ FILE: docs/_static/searchtools.js ================================================ /* * searchtools.js * ~~~~~~~~~~~~~~~~ * * Sphinx JavaScript utilities for the full-text search. * * :copyright: Copyright 2007-2024 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ "use strict"; /** * Simple result scoring code. */ if (typeof Scorer === "undefined") { var Scorer = { // Implement the following function to further tweak the score for each result // The function takes a result array [docname, title, anchor, descr, score, filename] // and returns the new score. /* score: result => { const [docname, title, anchor, descr, score, filename] = result return score }, */ // query matches the full name of an object objNameMatch: 11, // or matches in the last dotted part of the object name objPartialMatch: 6, // Additive scores depending on the priority of the object objPrio: { 0: 15, // used to be importantResults 1: 5, // used to be objectResults 2: -5, // used to be unimportantResults }, // Used when the priority is not in the mapping. objPrioDefault: 0, // query found in title title: 15, partialTitle: 7, // query found in terms term: 5, partialTerm: 2, }; } const _removeChildren = (element) => { while (element && element.lastChild) element.removeChild(element.lastChild); }; /** * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping */ const _escapeRegExp = (string) => string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string const _displayItem = (item, searchTerms, highlightTerms) => { const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; const contentRoot = document.documentElement.dataset.content_root; const [docName, title, anchor, descr, score, _filename] = item; let listItem = document.createElement("li"); let requestUrl; let linkUrl; if (docBuilder === "dirhtml") { // dirhtml builder let dirname = docName + "/"; if (dirname.match(/\/index\/$/)) dirname = dirname.substring(0, dirname.length - 6); else if (dirname === "index/") dirname = ""; requestUrl = contentRoot + dirname; linkUrl = requestUrl; } else { // normal html builders requestUrl = contentRoot + docName + docFileSuffix; linkUrl = docName + docLinkSuffix; } let linkEl = listItem.appendChild(document.createElement("a")); linkEl.href = linkUrl + anchor; linkEl.dataset.score = score; linkEl.innerHTML = title; if (descr) { listItem.appendChild(document.createElement("span")).innerHTML = " (" + descr + ")"; // highlight search terms in the description if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); } else if (showSearchSummary) fetch(requestUrl) .then((responseData) => responseData.text()) .then((data) => { if (data) listItem.appendChild( Search.makeSearchSummary(data, searchTerms, anchor) ); // highlight search terms in the summary if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); }); Search.output.appendChild(listItem); }; const _finishSearch = (resultCount) => { Search.stopPulse(); Search.title.innerText = _("Search Results"); if (!resultCount) Search.status.innerText = Documentation.gettext( "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." ); else Search.status.innerText = _( "Search finished, found ${resultCount} page(s) matching the search query." ).replace('${resultCount}', resultCount); }; const _displayNextItem = ( results, resultCount, searchTerms, highlightTerms, ) => { // results left, load the summary and display it // this is intended to be dynamic (don't sub resultsCount) if (results.length) { _displayItem(results.pop(), searchTerms, highlightTerms); setTimeout( () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), 5 ); } // search finished, update title and status message else _finishSearch(resultCount); }; // Helper function used by query() to order search results. // Each input is an array of [docname, title, anchor, descr, score, filename]. // Order the results by score (in opposite order of appearance, since the // `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. const _orderResultsByScoreThenName = (a, b) => { const leftScore = a[4]; const rightScore = b[4]; if (leftScore === rightScore) { // same score: sort alphabetically const leftTitle = a[1].toLowerCase(); const rightTitle = b[1].toLowerCase(); if (leftTitle === rightTitle) return 0; return leftTitle > rightTitle ? -1 : 1; // inverted is intentional } return leftScore > rightScore ? 1 : -1; }; /** * Default splitQuery function. Can be overridden in ``sphinx.search`` with a * custom function per language. * * The regular expression works by splitting the string on consecutive characters * that are not Unicode letters, numbers, underscores, or emoji characters. * This is the same as ``\W+`` in Python, preserving the surrogate pair area. */ if (typeof splitQuery === "undefined") { var splitQuery = (query) => query .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) .filter(term => term) // remove remaining empty strings } /** * Search Module */ const Search = { _index: null, _queued_query: null, _pulse_status: -1, htmlToText: (htmlString, anchor) => { const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); for (const removalQuery of [".headerlink", "script", "style"]) { htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); } if (anchor) { const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); if (anchorContent) return anchorContent.textContent; console.warn( `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` ); } // if anchor not specified or not found, fall back to main content const docContent = htmlElement.querySelector('[role="main"]'); if (docContent) return docContent.textContent; console.warn( "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." ); return ""; }, init: () => { const query = new URLSearchParams(window.location.search).get("q"); document .querySelectorAll('input[name="q"]') .forEach((el) => (el.value = query)); if (query) Search.performSearch(query); }, loadIndex: (url) => (document.body.appendChild(document.createElement("script")).src = url), setIndex: (index) => { Search._index = index; if (Search._queued_query !== null) { const query = Search._queued_query; Search._queued_query = null; Search.query(query); } }, hasIndex: () => Search._index !== null, deferQuery: (query) => (Search._queued_query = query), stopPulse: () => (Search._pulse_status = -1), startPulse: () => { if (Search._pulse_status >= 0) return; const pulse = () => { Search._pulse_status = (Search._pulse_status + 1) % 4; Search.dots.innerText = ".".repeat(Search._pulse_status); if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); }; pulse(); }, /** * perform a search for something (or wait until index is loaded) */ performSearch: (query) => { // create the required interface elements const searchText = document.createElement("h2"); searchText.textContent = _("Searching"); const searchSummary = document.createElement("p"); searchSummary.classList.add("search-summary"); searchSummary.innerText = ""; const searchList = document.createElement("ul"); searchList.classList.add("search"); const out = document.getElementById("search-results"); Search.title = out.appendChild(searchText); Search.dots = Search.title.appendChild(document.createElement("span")); Search.status = out.appendChild(searchSummary); Search.output = out.appendChild(searchList); const searchProgress = document.getElementById("search-progress"); // Some themes don't use the search progress node if (searchProgress) { searchProgress.innerText = _("Preparing search..."); } Search.startPulse(); // index already loaded, the browser was quick! if (Search.hasIndex()) Search.query(query); else Search.deferQuery(query); }, _parseQuery: (query) => { // stem the search terms and add them to the correct list const stemmer = new Stemmer(); const searchTerms = new Set(); const excludedTerms = new Set(); const highlightTerms = new Set(); const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); splitQuery(query.trim()).forEach((queryTerm) => { const queryTermLower = queryTerm.toLowerCase(); // maybe skip this "word" // stopwords array is from language_data.js if ( stopwords.indexOf(queryTermLower) !== -1 || queryTerm.match(/^\d+$/) ) return; // stem the word let word = stemmer.stemWord(queryTermLower); // select the correct list if (word[0] === "-") excludedTerms.add(word.substr(1)); else { searchTerms.add(word); highlightTerms.add(queryTermLower); } }); if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) } // console.debug("SEARCH: searching for:"); // console.info("required: ", [...searchTerms]); // console.info("excluded: ", [...excludedTerms]); return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; }, /** * execute search (requires search index to be loaded) */ _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { const filenames = Search._index.filenames; const docNames = Search._index.docnames; const titles = Search._index.titles; const allTitles = Search._index.alltitles; const indexEntries = Search._index.indexentries; // Collect multiple result groups to be sorted separately and then ordered. // Each is an array of [docname, title, anchor, descr, score, filename]. const normalResults = []; const nonMainIndexResults = []; _removeChildren(document.getElementById("search-progress")); const queryLower = query.toLowerCase().trim(); for (const [title, foundTitles] of Object.entries(allTitles)) { if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { for (const [file, id] of foundTitles) { const score = Math.round(Scorer.title * queryLower.length / title.length); const boost = titles[file] === title ? 1 : 0; // add a boost for document titles normalResults.push([ docNames[file], titles[file] !== title ? `${titles[file]} > ${title}` : title, id !== null ? "#" + id : "", null, score + boost, filenames[file], ]); } } } // search for explicit entries in index directives for (const [entry, foundEntries] of Object.entries(indexEntries)) { if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { for (const [file, id, isMain] of foundEntries) { const score = Math.round(100 * queryLower.length / entry.length); const result = [ docNames[file], titles[file], id ? "#" + id : "", null, score, filenames[file], ]; if (isMain) { normalResults.push(result); } else { nonMainIndexResults.push(result); } } } } // lookup as object objectTerms.forEach((term) => normalResults.push(...Search.performObjectSearch(term, objectTerms)) ); // lookup as search terms in fulltext normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); // let the scorer override scores with a custom scoring function if (Scorer.score) { normalResults.forEach((item) => (item[4] = Scorer.score(item))); nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); } // Sort each group of results by score and then alphabetically by name. normalResults.sort(_orderResultsByScoreThenName); nonMainIndexResults.sort(_orderResultsByScoreThenName); // Combine the result groups in (reverse) order. // Non-main index entries are typically arbitrary cross-references, // so display them after other results. let results = [...nonMainIndexResults, ...normalResults]; // remove duplicate search results // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept let seen = new Set(); results = results.reverse().reduce((acc, result) => { let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); if (!seen.has(resultStr)) { acc.push(result); seen.add(resultStr); } return acc; }, []); return results.reverse(); }, query: (query) => { const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); // for debugging //Search.lastresults = results.slice(); // a copy // console.info("search results:", Search.lastresults); // print the results _displayNextItem(results, results.length, searchTerms, highlightTerms); }, /** * search for object names */ performObjectSearch: (object, objectTerms) => { const filenames = Search._index.filenames; const docNames = Search._index.docnames; const objects = Search._index.objects; const objNames = Search._index.objnames; const titles = Search._index.titles; const results = []; const objectSearchCallback = (prefix, match) => { const name = match[4] const fullname = (prefix ? prefix + "." : "") + name; const fullnameLower = fullname.toLowerCase(); if (fullnameLower.indexOf(object) < 0) return; let score = 0; const parts = fullnameLower.split("."); // check for different match types: exact matches of full name or // "last name" (i.e. last dotted part) if (fullnameLower === object || parts.slice(-1)[0] === object) score += Scorer.objNameMatch; else if (parts.slice(-1)[0].indexOf(object) > -1) score += Scorer.objPartialMatch; // matches in last name const objName = objNames[match[1]][2]; const title = titles[match[0]]; // If more than one term searched for, we require other words to be // found in the name/title/description const otherTerms = new Set(objectTerms); otherTerms.delete(object); if (otherTerms.size > 0) { const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); if ( [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) ) return; } let anchor = match[3]; if (anchor === "") anchor = fullname; else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; const descr = objName + _(", in ") + title; // add custom score for some objects according to scorer if (Scorer.objPrio.hasOwnProperty(match[2])) score += Scorer.objPrio[match[2]]; else score += Scorer.objPrioDefault; results.push([ docNames[match[0]], fullname, "#" + anchor, descr, score, filenames[match[0]], ]); }; Object.keys(objects).forEach((prefix) => objects[prefix].forEach((array) => objectSearchCallback(prefix, array) ) ); return results; }, /** * search for full-text terms in the index */ performTermsSearch: (searchTerms, excludedTerms) => { // prepare search const terms = Search._index.terms; const titleTerms = Search._index.titleterms; const filenames = Search._index.filenames; const docNames = Search._index.docnames; const titles = Search._index.titles; const scoreMap = new Map(); const fileMap = new Map(); // perform the search on the required terms searchTerms.forEach((word) => { const files = []; const arr = [ { files: terms[word], score: Scorer.term }, { files: titleTerms[word], score: Scorer.title }, ]; // add support for partial matches if (word.length > 2) { const escapedWord = _escapeRegExp(word); if (!terms.hasOwnProperty(word)) { Object.keys(terms).forEach((term) => { if (term.match(escapedWord)) arr.push({ files: terms[term], score: Scorer.partialTerm }); }); } if (!titleTerms.hasOwnProperty(word)) { Object.keys(titleTerms).forEach((term) => { if (term.match(escapedWord)) arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); }); } } // no match but word was a required one if (arr.every((record) => record.files === undefined)) return; // found search word in contents arr.forEach((record) => { if (record.files === undefined) return; let recordFiles = record.files; if (recordFiles.length === undefined) recordFiles = [recordFiles]; files.push(...recordFiles); // set score for the word in each file recordFiles.forEach((file) => { if (!scoreMap.has(file)) scoreMap.set(file, {}); scoreMap.get(file)[word] = record.score; }); }); // create the mapping files.forEach((file) => { if (!fileMap.has(file)) fileMap.set(file, [word]); else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); }); }); // now check if the files don't contain excluded terms const results = []; for (const [file, wordList] of fileMap) { // check if all requirements are matched // as search terms with length < 3 are discarded const filteredTermCount = [...searchTerms].filter( (term) => term.length > 2 ).length; if ( wordList.length !== searchTerms.size && wordList.length !== filteredTermCount ) continue; // ensure that none of the excluded terms is in the search result if ( [...excludedTerms].some( (term) => terms[term] === file || titleTerms[term] === file || (terms[term] || []).includes(file) || (titleTerms[term] || []).includes(file) ) ) break; // select one (max) score for the file. const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); // add result to the result list results.push([ docNames[file], titles[file], "", null, score, filenames[file], ]); } return results; }, /** * helper function to return a node containing the * search summary for a given text. keywords is a list * of stemmed words. */ makeSearchSummary: (htmlText, keywords, anchor) => { const text = Search.htmlToText(htmlText, anchor); if (text === "") return null; const textLower = text.toLowerCase(); const actualStartPosition = [...keywords] .map((k) => textLower.indexOf(k.toLowerCase())) .filter((i) => i > -1) .slice(-1)[0]; const startWithContext = Math.max(actualStartPosition - 120, 0); const top = startWithContext === 0 ? "" : "..."; const tail = startWithContext + 240 < text.length ? "..." : ""; let summary = document.createElement("p"); summary.classList.add("context"); summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; return summary; }, }; _ready(Search.init); ================================================ FILE: docs/_static/sphinx_highlight.js ================================================ /* Highlighting utilities for Sphinx HTML documentation. */ "use strict"; const SPHINX_HIGHLIGHT_ENABLED = true /** * highlight a given string on a node by wrapping it in * span elements with the given class name. */ const _highlight = (node, addItems, text, className) => { if (node.nodeType === Node.TEXT_NODE) { const val = node.nodeValue; const parent = node.parentNode; const pos = val.toLowerCase().indexOf(text); if ( pos >= 0 && !parent.classList.contains(className) && !parent.classList.contains("nohighlight") ) { let span; const closestNode = parent.closest("body, svg, foreignObject"); const isInSVG = closestNode && closestNode.matches("svg"); if (isInSVG) { span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); } else { span = document.createElement("span"); span.classList.add(className); } span.appendChild(document.createTextNode(val.substr(pos, text.length))); const rest = document.createTextNode(val.substr(pos + text.length)); parent.insertBefore( span, parent.insertBefore( rest, node.nextSibling ) ); node.nodeValue = val.substr(0, pos); /* There may be more occurrences of search term in this node. So call this * function recursively on the remaining fragment. */ _highlight(rest, addItems, text, className); if (isInSVG) { const rect = document.createElementNS( "http://www.w3.org/2000/svg", "rect" ); const bbox = parent.getBBox(); rect.x.baseVal.value = bbox.x; rect.y.baseVal.value = bbox.y; rect.width.baseVal.value = bbox.width; rect.height.baseVal.value = bbox.height; rect.setAttribute("class", className); addItems.push({ parent: parent, target: rect }); } } } else if (node.matches && !node.matches("button, select, textarea")) { node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); } }; const _highlightText = (thisNode, text, className) => { let addItems = []; _highlight(thisNode, addItems, text, className); addItems.forEach((obj) => obj.parent.insertAdjacentElement("beforebegin", obj.target) ); }; /** * Small JavaScript module for the documentation. */ const SphinxHighlight = { /** * highlight the search words provided in localstorage in the text */ highlightSearchWords: () => { if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight // get and clear terms from localstorage const url = new URL(window.location); const highlight = localStorage.getItem("sphinx_highlight_terms") || url.searchParams.get("highlight") || ""; localStorage.removeItem("sphinx_highlight_terms") url.searchParams.delete("highlight"); window.history.replaceState({}, "", url); // get individual terms from highlight string const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); if (terms.length === 0) return; // nothing to do // There should never be more than one element matching "div.body" const divBody = document.querySelectorAll("div.body"); const body = divBody.length ? divBody[0] : document.querySelector("body"); window.setTimeout(() => { terms.forEach((term) => _highlightText(body, term, "highlighted")); }, 10); const searchBox = document.getElementById("searchbox"); if (searchBox === null) return; searchBox.appendChild( document .createRange() .createContextualFragment( '" ) ); }, /** * helper function to hide the search marks again */ hideSearchWords: () => { document .querySelectorAll("#searchbox .highlight-link") .forEach((el) => el.remove()); document .querySelectorAll("span.highlighted") .forEach((el) => el.classList.remove("highlighted")); localStorage.removeItem("sphinx_highlight_terms") }, initEscapeListener: () => { // only install a listener if it is really needed if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; document.addEventListener("keydown", (event) => { // bail for input elements if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; // bail with special keys if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { SphinxHighlight.hideSearchWords(); event.preventDefault(); } }); }, }; _ready(() => { /* Do not call highlightSearchWords() when we are on the search page. * It will highlight words from the *previous* search query. */ if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); SphinxHighlight.initEscapeListener(); }); ================================================ FILE: docs/appendix/1-jupyter-notebook.html ================================================ ▲Jupyter Notebook の使い方 — Pythonプログラミング入門 documentation

▲Jupyter Notebook の使い方

Jupyter Notebook について説明します。

参考

教材等の既存のノートブックは、 ディレクトリのページで選択することによって開くことができます。 ノートブックには ipynb という拡張子(エクステンション)が付きます。

ノートブックを新たに作成するには、ディレクトリが表示されているページで、 New のメニューで Python3 を選択してください。 Untitled1 などが付くことあり)というノートブックが作られます。 タイトルをクリックして変更することができます。

ノートブックの上方には、FileEdit などのメニュー、 などのアイコンが表示されています。

右上に Python 3 と表示されていることに注意してください。

Ctrl+s(Macの場合は Cmd+s)を入力することによって、 ノートブックをファイルにセーブできます。 オートセーブもされますが、適当なタイミングでセーブしましょう。

ノートブックはセルから成り立っています。

セル

主に次の二種類のセルを使います。

  • Code: Pythonのコードが書かれたセルです。 Codeセルの横には In [ ]: と表示されています。 コードを実行するには、Shift+Enter(または Return)を押します。 このセルの次のセルはCodeセルです。Shift+Enterを押してみてください。

  • Markdown: 説明が書かれたセルです。 このセル自身はMarkdownセルです。

セルの種類はノートブックの上のメニューで変更できます。

[ ]:

コマンドモード

セルを選択するとコマンドモードになります。 ただし、Codeセルを選択したとき、 マウスカーソルが入力フィールドに入っていると、 編集モードになってしまいます。

コマンドモードでは、セルの左の線が青色になります。

コマンドモードで Enter を入力すると、編集モードになります。 Markdownのセルでは、ダブルクリックでも編集モードになります。

コマンドモードでは、一文字コマンドが有効なので注意してください。

  • a: 上にセルを挿入 (above)

  • b: 下にセルを挿入 (below)

  • x: セルを削除(そのセルが削除されてしまいますので注意!)

  • l: セルの行に番号を振るか振らないかをスイッチ

  • s または Ctrl+s: ノートブックをセーブ (checkpoint)

  • Enter: 編集モードに移行

  • Shift+Enter: セルを実行して次のセルに

編集モード

編集モードでは文字カーソルが表示されて、セルの編集が可能です。 Ctrl の付かない文字はそのまま挿入されます。

編集モードでは、セルの左の線が緑色になります。

編集モードでは、以下のような編集コマンドが使えます。

  • Ctrl+c: copy

  • Ctrl+x: cut

  • Ctrl+v: paste

  • Ctrl+z: undo

Codeセルでは、編集モードでも Shift+Enter を入力すると、 セルの中のコードが実行されて、次のセルに移動します。 Markdownセルはフォーマットされて、次のセルに移動します。 次のセルではコマンドモードになっています。

Esc でコマンドモードになります。

Ctrl+s でノートブックをセーブ (checkpoint)。 これはコマンドモードの場合と同じです。

練習

次のセルを編集モードにして 10/3 と入力して実行してください。

[ ]:

(注意)Shift-Enterに反応がなくなったとき

CodeセルでShift-Enterをしても反応がないとき、 特にセルの左の部分が

In [*]:

となったままで、* が数に置き換わらないとき、 のアイコンを押して、 kernel(Pythonのインタープリタ)を停止させてください。

それでも反応がないときは、右回りの矢印のアイコンを押して、 kernel(Pythonのインタープリタ)を起動し直してください。

たとえば、次のような例です。 のアイコンを押してください。

[ ]:
while True:
    pass
[ ]:

================================================ FILE: docs/appendix/2-set.html ================================================ ▲セット (set) — Pythonプログラミング入門 documentation

▲セット (set)

セットについて説明します。

参考

セット集合)は、リストと同様に複数の要素から構成されるデータです。 セットでは、リストと異なり要素の重複がありません、また要素の順番もありません。

セットを作成するには、次のように波括弧で要素を囲みます。 辞書と似ていますが、辞書では : でキーと値を対応させる必要がありました。

[1]:
set1= {2, 1, 2, 3, 2, 3, 1, 3, 3, 1}
set1
[1]:
{1, 2, 3}
[2]:
type(set1)
[2]:
set

セットのデータ型は set であり、set は組み込み関数でもあります。

組み込み関数 set を用いてもセットを作成することができます。

[3]:
set([2, 1, 2, 3, 2, 3, 1, 3, 3, 1])
[3]:
{1, 2, 3}

空のセットを作成する場合、次のようにします。( {} では空の辞書が作成されます。)

[4]:
set2 = set() # 空のセット
set2
[4]:
set()
[5]:
set2 = {} # 空の辞書
set2
[5]:
{}

set を用いて、文字列、リストやタプルなどからセットを作成することができます。

[6]:
set([1,1,2,2,2,3])
[6]:
{1, 2, 3}
[7]:
set((1,1,2,2,2,3))
[7]:
{1, 2, 3}
[8]:
set('aabdceabdae')
[8]:
{'a', 'b', 'c', 'd', 'e'}
[9]:
set({'apple' : 3, 'pen' : 5})
[9]:
{'apple', 'pen'}

セットの組み込み関数

リストなどと同様に、次の関数などはセットにも適用可能です。

[10]:
len(set1) # 集合を構成する要素数
[10]:
3
[11]:
x,y,z = set1 # 多重代入
x
[11]:
1
[12]:
2 in set1 # 指定した要素を集合が含むかどうかの判定
[12]:
True
[13]:
10 in set1 # 指定した要素を集合が含むかどうかの判定
[13]:
False
[14]:
10 not in set1
[14]:
True

セットの要素は、順序付けられていないのでインデックスを指定して取り出すことはできません。

[15]:
set1[0]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[15], line 1
----> 1 set1[0]

TypeError: 'set' object is not subscriptable

練習

文字列 str1 が引数として与えられたとき、str1 に含まれる要素(文字、すなわち長さ1の文字列)の種類を返す関数 check_characters を作成してください(大文字と小文字は区別し、スペースや句読点も1つと数えます)。 たとえば、'aabccc' には 'a''b''c' が含まれるので、 check_characters('aabccc') は 3 を返します。

以下のセルの ... のところを書き換えて check_characters(str1) を作成してください。

[16]:
def check_characters(str1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[17]:
print(check_characters('Onde a terra acaba e o mar começa') == 13)
False

練習

辞書 dic1 が引数として与えられたとき、dic1 に登録されているキーの数を返す関数 check_dicsize を作成してください。

以下のセルの ... のところを書き換えて check_dicsize(dic1) を作成してください。

[18]:
def check_dicsize(dic1):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[19]:
print(check_dicsize({'apple': 0, 'orange': 2, 'pen': 1}) == 3)
False

集合演算

複数のセットから、和集合積集合差集合対称差を求める集合演算が存在します。

[20]:
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
[21]:
set1 | set2 # 和集合
[21]:
{1, 2, 3, 4, 5, 6}
[22]:
set1 & set2 # 積集合
[22]:
{3, 4}
[23]:
set1 - set2 # 差集合
[23]:
{1, 2}
[24]:
set1 ^ set2 # 対称差
[24]:
{1, 2, 5, 6}

比較演算

数値などを比較するのに用いた比較演算子を用いて、2つのセットを比較することもできます。

[25]:
print({1, 2, 3} == {1, 2, 3})
print({1, 2} == {1, 2, 3})
True
False
[26]:
print({1, 2, 3} != {1, 2, 3})
print({1, 2} != {1, 2, 3})
False
True

<=< は、集合の間の包含関係を判定します。

[27]:
print({1, 2, 3} <= {1, 2, 3})
print({1, 2, 3} < {1, 2, 3})
print({1, 2} < {1, 2, 3})
True
False
True
[28]:
print({1, 2} <= {2, 3, 4})
False

セットのメソッド

セットにも様々なメソッドが存在します。なお、以下のメソッドは全て破壊的です。

add

指定した要素を新たにセットに追加します。

[29]:
set1 = {1, 2, 3}
set1.add(4)
set1
[29]:
{1, 2, 3, 4}

remove

指定した要素をセットから削除します。 その要素がセットに含まれていない場合、エラーになります。

[30]:
set1.remove(1)
set1
[30]:
{2, 3, 4}
[31]:
set1.remove(10)
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[31], line 1
----> 1 set1.remove(10)

KeyError: 10

discard

指定した要素をセットから削除します。 その要素がセットに含まれていなくともエラーになりません。

[32]:
set1 = {1, 2, 3, 4}
set1.discard(1)
set1
[32]:
{2, 3, 4}
[33]:
set1.discard(5)

clear

全ての要素を削除して対象のセットを空にします。

[34]:
set1 = {1, 2, 3, 4}
set1.clear()
set1
[34]:
set()

pop

セットからランダムに1つの要素を取り出します。

[35]:
set1 = {1, 2, 3, 4}
print(set1.pop())
print(set1)
1
{2, 3, 4}

union, intersection, difference

和集合積集合差集合対称差を求めるメソッドも存在します。

[36]:
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
set1.union(set2) # 和集合
[36]:
{1, 2, 3, 4, 5, 6}
[37]:
set1.intersection(set2) # 積集合
[37]:
{3, 4}
[38]:
set1.difference(set2) # 差集合
[38]:
{1, 2}
[39]:
set1.symmetric_difference(set2) # 対称差
[39]:
{1, 2, 5, 6}

練習

英語の文章からなる文字列 str_engsentences が引数として与えられたとき、str_engsentences 中に含まれる単語の種類数を返す関数 count_words2 を作成してください。

以下のセルの ... のところを書き換えて count_words2(str_engsentences) を作成してください。

[40]:
def count_words2(str_engsentences):
    ...

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[41]:
print(count_words2('From Stettin in the Baltic to Trieste in the Adriatic an iron curtain has descended across the Continent.') == 15)
False

練習の解答

[42]:
def check_characters(str1):
    set1 = set(str1)
    return len(set1)
#check_characters('Onde a terra acaba e o mar começa')
[43]:
def check_dicsize(dic1):
    return len(set(dic1))
#check_dicsize({'apple': 0, 'orange': 2, 'pen': 1})

実は len は辞書に対してキーの数を返すので、セットを使う必要はありません。

[44]:
def check_dicsize(dic1):
    return len(dic1)
[45]:
def count_words2(str_engsentences):
    str1 = str_engsentences.replace('.', '') # 句読点を削除する
    str1 = str1.replace(',', '')
    str1 = str1.replace(':', '')
    str1 = str1.replace(';', '')
    str1 = str1.replace('!', '')
    str1 = str1.replace('?', '')
    list1 = str1.split(' ') # 句読点を削除した文字列を、単語ごとにリストに格納する
    set1 = set(list1) # リストを集合に変換して同じ要素を1つにまとめる
    return len(set1)
#count_words2('From Stettin in the Baltic to Trieste in the Adriatic an iron curtain has descended across the Continent.')
[ ]:

================================================ FILE: docs/appendix/3-recursion.html ================================================ ▲再帰 — Pythonプログラミング入門 documentation

▲再帰

再帰について説明します。

関数の再帰呼び出しとは、定義しようとしている関数を、その定義の中で呼び出すことです。 定義の中で直接呼び出す場合に限らず、他の関数を経由して間接的に呼び出す場合も、再帰呼び出しに含まれます。 再帰呼び出しを行う関数を、再帰関数といいます。

再帰関数は、分割統治アルゴリズムの記述に適しています。 分割統治とは、問題を容易に解ける小さな粒度まで分割していき、 個々の小さな問題を解いて、その部分解を合成することで問題全体を解くような方法を指します。 分割統治の考え方は、関数型プログラミングにおいてもよく用いられます。 再帰関数による分割統治の典型的な形は、次の通りです。

def recursive_function(...):
    if 問題粒度の判定:
        再帰呼び出しを含まない基本処理
    else:
        再帰呼び出しを含む処理(問題の分割や部分解の合成を行う)

以下で、再帰関数を使った処理の例をいくつか見ていきましょう。

再帰関数の例:接頭辞リストと接尾辞リスト

[1]:
# 入力の文字列の接頭辞リストを返す関数prefixes
def prefixes(s):
    if s == '':
        return []
    else:
        return [s] + prefixes(s[:-1])

prefixes('aabcc')
[1]:
['aabcc', 'aabc', 'aab', 'aa', 'a']
[2]:
# 入力の文字列の接尾辞リストを返す関数suffixes
def suffixes(s):
    if s == '':
        return []
    else:
        return [s] + suffixes(s[1:])

suffixes('aabcc')
[2]:
['aabcc', 'abcc', 'bcc', 'cc', 'c']

再帰関数の例:べき乗の計算

[3]:
# 入力の底baseと冪指数exptからべき乗を計算する関数power
def power(base, expt):
    if expt == 0:
        # exptが0ならば1を返す
        return 1
    else:
        # exptを1つずつ減らしながらpowerに渡し、再帰的にべき乗を計算
        # (2*(2*(2*....*1)))
        return base * power(base, expt - 1)

power(2,10)
[3]:
1024

一般に、再帰処理は、繰り返し処理としても書くことができます。

[4]:
# べき乗の計算を繰り返し処理で行った例
def power(base, expt):
    e = 1
    for i in range(expt):
        e *= base
    return e

power(2,10)
[4]:
1024

単純な処理においては、繰り返しの方が効率的に計算できることが多いですが、 特に複雑な処理になってくると、再帰的に定義した方が読みやすいコードで効率的なアルゴリズムを記述できることもあります。 たとえば、次に示すべき乗計算は、上記よりも高速なアルゴリズムですが、計算の見通しは明快です。

[5]:
# べき乗を計算する高速なアルゴリズム
def power(base, expt):
    if expt == 0:
        return 1
    elif expt % 2 == 0:
        return power(base * base, expt // 2) # x**(2m) == (x*x)**m
    else:
        return base * power(base, expt - 1)

power(2,10)
[5]:
1024

再帰関数の例:マージソート

マージソートは、典型的な分割統治アルゴリズムで、以下のように再帰関数で実装することができます。

[6]:
# マージソートを行い、比較回数 n を返す
def merge_sort_rec(data, l, r, work):
    n = 0
    if r - l <= 1:
        return n
    m = l + (r - l) // 2
    n1 = merge_sort_rec(data, l, m, work)
    n2 = merge_sort_rec(data, m, r, work)
    i1 = l
    i2 = m
    for i in range(l, r):
        from1 = False
        if i2 >= r:
            from1 = True
        elif i1 < m:
            n = n + 1
            if data[i1] <= data[i2]:
                from1 = True
        if from1:
            work[i] = data[i1]
            i1 = i1 + 1
        else:
            work[i] = data[i2]
            i2 = i2 + 1
    for i in range(l, r):
        data[i] = work[i]
    return n1 + n2 + n

def merge_sort(data):
    return merge_sort_rec(data, 0, len(data), [0]*len(data))

merge_sort は、与えられた配列をインプレースでソートするとともに、比較の回数を返します。 merge_sort は、再帰関数 merge_sort_rec を呼び出します。

merge_sort_rec(data, l, r, work) は、配列 data のインデックスが l 以上で r より小さいところをソートします。

  • 要素が1つかないときは何もしません。

  • そうでなければ、l から r までの要素を半分にしてそれぞれを再帰的にソートします。

  • その結果を作業用の配列 work に順序を保ちながらコピーします。この操作はマージ(併合)と呼ばれます。

  • 最後に、work から data に要素を戻します。

merge_sort_rec は自分自身を2回呼び出していますので、繰り返しでは容易には実装できません。

[7]:
import random
a = [random.randint(1,10000) for i in range(100)]
merge_sort(a)
[7]:
538
[8]:
a
[8]:
[46,
 73,
 198,
 227,
 233,
 262,
 430,
 464,
 587,
 679,
 720,
 832,
 839,
 911,
 940,
 1123,
 1458,
 1488,
 1541,
 1562,
 1890,
 2157,
 2311,
 2364,
 2390,
 2509,
 2717,
 2721,
 2801,
 2960,
 3200,
 3209,
 3219,
 3356,
 3602,
 3611,
 3707,
 3720,
 3764,
 3787,
 4137,
 4189,
 4304,
 4334,
 4337,
 4407,
 4424,
 4474,
 4610,
 4892,
 4918,
 5069,
 5156,
 5198,
 5219,
 5231,
 5385,
 5420,
 5560,
 5711,
 6019,
 6027,
 6266,
 6327,
 6477,
 6686,
 6930,
 6962,
 7052,
 7091,
 7136,
 7319,
 7351,
 7385,
 7472,
 7508,
 7532,
 7584,
 7749,
 8014,
 8046,
 8315,
 8361,
 8409,
 8560,
 8563,
 8881,
 8928,
 9084,
 9158,
 9289,
 9419,
 9504,
 9622,
 9648,
 9657,
 9864,
 9880,
 9934,
 9936]
[ ]:

================================================ FILE: docs/appendix/3-visualization.html ================================================ ▲簡単なデータの可視化 — Pythonプログラミング入門 documentation

▲簡単なデータの可視化

第3回までに学んだ各種のデータに対する簡単な可視化について触れます。

参考

matplotlib については、5-matplotlib に詳しい説明があります。

matplotlib

Pythonでは可視化のための様々な仕組みが用意されています。 ここでは最も広く利用され、ノートブック上で容易に動作を確認できる matplotlib について触れます。 matplotlib を利用するには第5回で取り上げるモジュールについても知る必要がありますが、 第2回と第3回でデータについてだけ学ぶのでは、みなさんのモチベーションの維持が難しいと思われますので、 この段階でリスト・辞書だけで2次元グラフを表示させてみます。 したがって、ここではモジュールの使い方については説明しません。

matplotlib の出力をノートブックで表示させるには、以下をCodeセルで1回だけ実行します。 %matplotlib のように % で始まる文をマジックコマンドと呼びます。

[1]:
%matplotlib inline

さらに matplotlib モジュールを読み込む次の処理もプログラムの冒頭で行う必要があります。

import matplotlib.pyplot as plt

折れ線グラフ

ls1 = [1, 4, 9, 16] といった数を要素とするリストを折れ線グラフで表示するには、次のように行います。

[2]:
import matplotlib.pyplot as plt
ls1 = [1, 4, 9, 16]
plt.plot(ls1)
plt.show()
../_images/appendix_3-visualization_6_0.png

折れ線グラフを複数表示させるには、plt.plot を繰り返します。

[3]:
import matplotlib.pyplot as plt
ls1 = [1, 4, 9, 16]
ls2 = [8, 7, 6, 5]
plt.plot(ls1, label='1st plot')
plt.plot(ls2, label='2nd plot')
plt.show()
../_images/appendix_3-visualization_8_0.png

散布図

散布図を表示させるには、plt.scatter にそれぞれの点に対応する水平、垂直座標をリストで与えます。 この2つのリストの要素数は同じでなければなりません。

[4]:
import matplotlib.pyplot as plt
x = [5, 10, 15, 10]
y = [10, 5, 10, 15]
plt.scatter(x,y)
plt.show()
../_images/appendix_3-visualization_10_0.png

棒グラフ

棒グラフを表示させるには、plt.bar に水平座標、高さをリストで与えます。 この2つのリストの要素数は同じでなければなりません。 以下の例では、等間隔でグラフを表示させるため水平軸に整数列を使っています。

[5]:
import matplotlib.pyplot as plt
x = [1, 2, 3, 4]
y = [10, 30, 40, 15]
plt.bar(x,y)
plt.show()
../_images/appendix_3-visualization_12_0.png

第2回と第3回では文字列、辞書について学びました。 文字列をキー、整数を値とする辞書を棒グラフで可視化します。 さらに、水平軸にはキーをラベルとして表示されます。

[6]:
import matplotlib.pyplot as plt
d = {'apple':10, 'banana':30, 'orange': 40, 'kiwi': 15}
x = [1,2,3,4]
plt.bar(x, d.values(), tick_label=list(d.keys()))
plt.show()
../_images/appendix_3-visualization_14_0.png
================================================ FILE: docs/appendix/4-csv.html ================================================ ▲CSVファイルの入出力 — Pythonプログラミング入門 documentation

▲CSVファイルの入出力

CSVファイルの入出力について説明します。

参考

CSV形式とは

CSV形式とは "comma-separated values" の略で、 複数の値をコンマで区切って記録するファイル形式です。

みなさんExcelを使ったことがあると思いますが、 Excelでは1つのセルに1つの値(数値や文字など)が入っていて、 その他のセルの値とは独立に扱えますよね。

それと同じように、CSV形式では、,(コンマ)で区切られた要素はそれぞれ独立の値として扱われます。

たとえばサークルのメンバーデータを作ることを考えましょう。 メンバーは「鈴木一郎」と「山田花子」の2名で、 それぞれ『氏名』『ニックネーム』『出身地』を記録しておきたいと思います。

表で表すとこんなデータです。

ID

氏名

ニックネーム

出身地

user1

鈴木一郎

イチロー

広島

user2

山田花子

はなこ

名古屋

これをCSV形式で表すと次のようになります。

'user1','鈴木一郎','イチロー','広島' 'user2','山田花子','はなこ','名古屋'

CSVファイルの読み込み

CSVファイルを読み書きするには、 ファイルをオープンして、そのファイルオブジェクトから、 CSVリーダを作ります。

CSVリーダとは、CSVファイルからデータを読み込むためのオブジェクトで、 このオブジェクトのメソッドを呼び出すことにより、CSVファイルからデータを読み込むことができます。

CSVリーダを作るには、 csv というモジュールの csv.reader という関数にファイルオブジェクトを渡します。

たとえば、次のような表で表されるCSVファイル small.csv を読み込んでみましょう。

0列目 | 1列目 | 2列目 | 3列目 | 4列目

11 | 12 | 13 | 14 | 15 21 | 22 | 23 | 24 | 25 31 | 32 | 33 | 34 | 35

[1]:
import csv
f = open('small.csv', 'r')
dataReader = csv.reader(f)

このオブジェクトもイテレータで、next という関数を呼び出すことができます。

[2]:
next(dataReader)
[2]:
['11', '12', '13', '14', '15']

このようにして CSVファイルを読むと、 CSVファイルの各行のデータが文字列のリストとなって返されます。

[3]:
next(dataReader)
[3]:
['21', '22', '23', '24', '25']
[4]:
row = next(dataReader)
[5]:
row
[5]:
['31', '32', '33', '34', '35']
[6]:
row[2]
[6]:
'33'

数値が '' で囲われている場合、数値ではなく文字列として扱われているので、そのまま計算に使用することができません。

文字列が整数を表す場合、int 関数によって文字列を整数に変換することができます。 文字列が小数を含む場合は float 関数で浮動小数点数型に変換、文字列が複素数を表す場合は complex 関数で複素数に変換します。

[7]:
int(row[2])
[7]:
33

ファイルの終わりまで達した後に next 関数を実行すると、下のようにエラーが返ってきます。

[8]:
next(dataReader)
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
Cell In[8], line 1
----> 1 next(dataReader)

StopIteration:

ファイルを使い終わったらクローズすることを忘れないようにしましょう。

[9]:
f.close()

CSVファイルに対するfor文

CSVリーダもイテレータですので、for文の in の後に書くことができます。

for row in dataReader:
    ...

繰り返しの各ステップで、next(dataReader) が呼び出されて、 row にその値が設定され、for文の中身が実行されます。

[10]:
f = open('small.csv', 'r')
dataReader = csv.reader(f)
for row in dataReader:
    print(row)
f.close()
['11', '12', '13', '14', '15']
['21', '22', '23', '24', '25']
['31', '32', '33', '34', '35']

CSVファイルに対するwith文

以下はwith文を使った例です。

[11]:
with open('small.csv', 'r') as f:
    dataReader = csv.reader(f)
    for row in dataReader:
        print(row)
['11', '12', '13', '14', '15']
['21', '22', '23', '24', '25']
['31', '32', '33', '34', '35']

CSVファイルの書き込み

CSVファイルを作成して書き込むには、CSVライターを作ります。

CSVライターとは、CSVファイルを作ってデータを書き込むためのオブジェクトで、 このオブジェクトのメソッドを呼び出すことにより、データがCSV形式でファイルに書き込まれます。

CSVライターを作るには、 csv というモジュールの csv.writer という関数にファイルオブジェクトを渡します。 ここで、半角英数文字以外の文字(たとえば日本語文字や全角英数文字)を書き込み・書き出しする際には、 文字コード(たとえば encoding='utf-8')を指定し、 また書き出しの際にはさらに改行コードとして newline='' を指定しないと文字化けが生じる可能性があります。

[12]:
f = open('out.csv', 'w', encoding='utf-8', newline='')
[13]:
dataWriter = csv.writer(f)
[14]:
dir(dataWriter)
[14]:
['__class__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getstate__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'dialect',
 'writerow',
 'writerows']
[15]:
dataWriter.writerow([1,2,3])
[15]:
7
[16]:
dataWriter.writerow([21,22,23])
[16]:
10

書き込みモードの場合も、ファイルを使い終わったらクローズすることを忘れないようにしましょう。

[17]:
f.close()

読み込みのときと同様、with文を使うこともできます。

[18]:
with open('out.csv', 'w', encoding='utf-8', newline='') as f:
    dataWriter = csv.writer(f)
    dataWriter.writerow([1,2,3])
    dataWriter.writerow([21,22,23])

東京の7月の気温

tokyo-temps.csv には、気象庁のオープンデータからダウンロードした、 東京の7月の平均気温のデータが入っています。

http://www.data.jma.go.jp/gmd/risk/obsdl/

48行目の第2列に1875年7月の平均気温が入っており、 以下、2016年まで、12行ごとに7月の平均気温が入っています。

以下は、これを取り出すPythonの簡単なコードです。

[19]:
import csv

with open('tokyo-temps.csv', 'r', encoding='shift_jis') as f:
    dataReader = csv.reader(f) # csvリーダを作成
    n=0
    year = 1875
    years = []
    july_temps = []
    for row in dataReader: # CSVファイルの中身を1行ずつ読み込み
        n = n+1
        if n>=48 and (n-48)%12 == 0: # 48行目からはじめて12か月ごとにif内を実行
            years.append(year)
            july_temps.append(float(row[1]))
            year = year + 1

ファイルをオープンするときに、キーワード引数の encoding が指定されています。 このファイルはShift_JISという文字コードで書かれているため、 この引数で、ファイルの符号(文字コード)を指定します。 'shift_jis' はShift_JISを意味します。この他に、'utf-8'(UTF-8、すなわちビットのUnicode)があります。

変数 years に年の配列、変数 july_temps に対応する年の7月の平均気温の配列が設定されます。

[20]:
years
[20]:
[1875,
 1876,
 1877,
 1878,
 1879,
 1880,
 1881,
 1882,
 1883,
 1884,
 1885,
 1886,
 1887,
 1888,
 1889,
 1890,
 1891,
 1892,
 1893,
 1894,
 1895,
 1896,
 1897,
 1898,
 1899,
 1900,
 1901,
 1902,
 1903,
 1904,
 1905,
 1906,
 1907,
 1908,
 1909,
 1910,
 1911,
 1912,
 1913,
 1914,
 1915,
 1916,
 1917,
 1918,
 1919,
 1920,
 1921,
 1922,
 1923,
 1924,
 1925,
 1926,
 1927,
 1928,
 1929,
 1930,
 1931,
 1932,
 1933,
 1934,
 1935,
 1936,
 1937,
 1938,
 1939,
 1940,
 1941,
 1942,
 1943,
 1944,
 1945,
 1946,
 1947,
 1948,
 1949,
 1950,
 1951,
 1952,
 1953,
 1954,
 1955,
 1956,
 1957,
 1958,
 1959,
 1960,
 1961,
 1962,
 1963,
 1964,
 1965,
 1966,
 1967,
 1968,
 1969,
 1970,
 1971,
 1972,
 1973,
 1974,
 1975,
 1976,
 1977,
 1978,
 1979,
 1980,
 1981,
 1982,
 1983,
 1984,
 1985,
 1986,
 1987,
 1988,
 1989,
 1990,
 1991,
 1992,
 1993,
 1994,
 1995,
 1996,
 1997,
 1998,
 1999,
 2000,
 2001,
 2002,
 2003,
 2004,
 2005,
 2006,
 2007,
 2008,
 2009,
 2010,
 2011,
 2012,
 2013,
 2014,
 2015,
 2016]
[21]:
july_temps
[21]:
[26.0,
 24.3,
 26.5,
 26.0,
 26.1,
 24.2,
 24.0,
 24.2,
 23.7,
 23.4,
 23.1,
 25.0,
 23.6,
 24.5,
 23.4,
 23.5,
 24.9,
 25.7,
 25.3,
 26.8,
 22.1,
 24.1,
 22.9,
 25.9,
 23.2,
 22.8,
 22.1,
 21.8,
 23.2,
 24.8,
 23.3,
 23.5,
 22.7,
 22.1,
 24.3,
 23.0,
 24.5,
 24.3,
 23.3,
 25.5,
 24.2,
 23.9,
 25.7,
 26.0,
 23.6,
 26.1,
 24.3,
 25.0,
 24.0,
 26.1,
 23.2,
 24.6,
 26.0,
 23.4,
 25.9,
 26.3,
 21.8,
 25.7,
 26.6,
 23.9,
 24.3,
 24.9,
 26.3,
 25.0,
 26.5,
 26.9,
 23.7,
 27.5,
 25.1,
 25.6,
 22.0,
 26.2,
 25.7,
 26.0,
 25.3,
 26.5,
 24.3,
 24.3,
 24.7,
 22.3,
 27.6,
 24.2,
 24.4,
 24.9,
 26.1,
 25.8,
 27.4,
 25.1,
 25.7,
 25.5,
 24.2,
 24.4,
 26.3,
 24.7,
 25.0,
 25.4,
 25.8,
 25.2,
 26.1,
 23.4,
 25.6,
 23.9,
 25.8,
 27.8,
 25.2,
 23.8,
 26.3,
 23.1,
 23.8,
 26.2,
 26.3,
 23.9,
 27.0,
 22.4,
 24.1,
 25.7,
 26.7,
 25.5,
 22.5,
 28.3,
 26.4,
 26.2,
 26.6,
 25.3,
 25.9,
 27.7,
 28.5,
 28.0,
 22.8,
 28.5,
 25.6,
 25.6,
 24.4,
 27.0,
 26.3,
 28.0,
 27.3,
 26.4,
 27.3,
 26.8,
 26.2,
 25.4]

ここでは詳しく説明しませんが、線形回帰によるフィッティングを行ってみましょう。

[22]:
import numpy
import matplotlib.pyplot as plt
%matplotlib inline

fitp = numpy.poly1d(numpy.polyfit(years, july_temps, 1))
ma = max(years)
mi = min(years)
xp = numpy.linspace(mi, ma, (ma - mi))
[23]:
plt.plot(years, july_temps, '.', xp, fitp(xp), '-')
plt.show()
../_images/appendix_4-csv_41_0.png

練習

  1. tokyo-temps.csv を読み込んで、各行が西暦年と7月の気温のみからなる 'tokyo-july-temps.csv' という名前のCSVファイルを作成してください。 西暦年は1875から2016までとします。

  2. 作成したCSVファイルをExcelで読み込むとどうなるか確認してください。

[ ]:

以下のセルによってテストしてください。(yearsjuly_temps の値がそのままと仮定しています。)

[24]:
with open('tokyo-july-temps.csv', 'r', encoding='shift_jis') as f:
    i = 0
    dataReader = csv.reader(f)
    for row in dataReader:
        if int(row[0]) != years[i] or abs(float(row[1])-july_temps[i])>0.000001:
            print('error', int(row[0]), float(row[1]))
        i += 1
print(i== 142) # 1875年から2016年まで142年間分のデータがあるはずです
True

練習

整数データのみからなるCSVファイルの名前を受け取ると、そのCSVファイルの各行を読み込んで整数のリストを作り、 ファイル全体の内容を、そのようなリストのリストとして返す関数 csv_matrix(name) を定義してください。

たとえば上で用いた small.csv には次のようなデータが入っています。

0列目 | 1列目 | 2列目 | 3列目 | 4列目

11 | 12 | 13 | 14 | 15 21 | 22 | 23 | 24 | 25 31 | 32 | 33 | 34 | 35

この small.csv の名前が引数として与えられた場合、

[[11, 12, 13, 14, 15], [21, 22, 23, 24, 25], [31, 32, 33, 34, 35]]

というリストを返します。

[25]:
def csv_matrix(name):
    ...

以下のセルによってテストしてください。

[26]:
print(csv_matrix('small.csv') == [[11, 12, 13, 14, 15], [21, 22, 23, 24, 25], [31, 32, 33, 34, 35]])
False

練習の解答

[27]:
with open('tokyo-july-temps.csv', 'w', encoding='utf-8', newline='') as f:
    i = 0
    dataWriter = csv.writer(f)
    for i in range(len(years)):
        dataWriter.writerow([years[i],july_temps[i]])
[28]:
def csv_matrix(name):
    rows = []
    with open(name, 'r') as f:
        dataReader = csv.reader(f)
        for row in dataReader:
            rows.append([int(x) for x in row])
    return rows
[ ]:

================================================ FILE: docs/appendix/5-bokeh.html ================================================ ▲Bokehライブラリ — Pythonプログラミング入門 documentation

▲Bokehライブラリ

Bokehライブラリについて説明します。

参考

Bokehは、データを可視化するためのライブラリです。 bokeh モジュールを使った、基本的なグラフの描画について説明します。

線グラフ

Bokehライブラリ使用してグラフを描画するには、bokeh.plotting のモジュールをインポートします。 基本的なグラフの描画をノートブック上で行うには、図形を生成する bokeh.plotting.figure()、図形を表示する bokeh.plotting.show()、出力先をノートブック上に設定する bokeh.plotting.output_notebook() があれば充分です。 通例、output_notebook() は最初に呼び出されます。

グラフで可視化するデータは配列を用いることが多いため、numpy モジュールも併せてインポートします。

[1]:
import numpy as np
from bokeh.plotting import figure, output_notebook, show
output_notebook()
Loading BokehJS ...

次は、figure() が返す Figure クラスの line() メソッドを使って、リストの要素の数値をy軸の値としてグラフを描画しています。 y軸の値に対応するx軸の値は、リストの各要素のインデックスとしています。

[2]:
# プロットするデータ
d = [0, 1, 4, 9, 16]
p = figure()
p.line(list(range(len(d))), d) # 第1引数がx軸、第2引数がy軸
show(p)

line() メソッド(及び他の描画用メソッド)では、キーワード引数も使えます。

[3]:
p = figure()
p.line(y=d, x=list(range(len(d))))
show(p)

次に示すように、複数のグラフをまとめてプロットして表示することもできます。 プロットするメソッドではグラフの線の色や線の種類を、line_color 引数や line_dash 引数で指定できます。 また、legend_label 引数に値を設定すると、プロットしたグラフが凡例に現れます。 引数の詳細はFigure.lineのページ(英語)を参照してください。

[4]:
data = [0, 1, 4, 9, 16]
x = list(range(len(data)))
p = figure()
p.line(x, x, line_color='blue', legend_label='linear', line_dash='dashed')
p.line(x, data, line_color='green', legend_label='quad', line_dash='dotted')
show(p)

figure() 関数の引数に、軸のラベルや、グラフのタイトルを設定できます。 プロット点を線グラフ上に重ねたいときには、circle() メソッドや cross() メソッドで同色の円や十字を追加で描けばよいです。

[5]:
p = figure(x_axis_label='x', y_axis_label='y', title='Linear vs. Quadratic')
p.line(x, x, line_color='blue', legend_label='linear', line_dash='dashed')
p.circle(x, x, color='blue', line_width=5)
p.line(x, data, line_color='green', legend_label='quad', line_dash='dotted')
p.cross(x, data, color='green', size=16)
show(p)
BokehDeprecationWarning: 'cross() method' was deprecated in Bokeh 3.4.0 and will be removed, use "scatter(marker='cross', ...) instead" instead.

色の使い分けを全て自分で決めるのは面倒です。 良く使われる色のリストがパレットとして、提供されています。 次は、d3Category10 という種類の3色パレットを用いています。 詳細は、paletteのページを参照してください。

[6]:
from bokeh.palettes import d3
c = d3['Category10'][3]
p = figure(x_axis_label='x', y_axis_label='y', title='Linear vs. Quadratic')
p.line(x, x, line_color=c[0], legend_label='linear', line_dash='dashed')
p.circle(x, x, color=c[0], line_width=5)
p.line(x, data, line_color=c[1], legend_label='quad', line_dash='dotted')
p.cross(x, data, color=c[1], size=16)
show(p)
BokehDeprecationWarning: 'cross() method' was deprecated in Bokeh 3.4.0 and will be removed, use "scatter(marker='cross', ...) instead" instead.

グラフを描画するときのプロット数を増やすことで任意の曲線のグラフを作成することもできます。 次の例では、numpy モジュールの arange() 関数を用いて、\(- \pi\) から \(\pi\) の範囲を 0.1 刻みでx軸の値を配列として準備しています。 そのx軸の値に対して、numpy モジュールの cos() 関数と sin() 関数を用いて、y軸の値をそれぞれ準備し、cosカーブとsinカーブを描画しています。

[7]:
# グラフのx軸の値となる配列
x = np.arange(-np.pi, np.pi, 0.1)

# 上記配列をcos, sin関数に渡し, y軸の値として描画
p = figure(title='cos and sin Curves', x_axis_label='x', y_axis_label='y')
p.line(x, np.cos(x), line_color=c[0])
p.line(x, np.sin(x), line_color=c[1])
show(p)

プロットの数を少なくすると、曲線は直線をつなぎ合わせることで描画されていることがわかります。

[8]:
x = np.arange(-np.pi, np.pi, 0.5)
p = figure(title='cos and sin Curves', x_axis_label='x', y_axis_label='y')
p.line(x, np.cos(x), line_color=c[0])
p.line(x, np.sin(x), line_color=c[1])
show(p)

グラフの例:ソートアルゴリズムにおける比較回数

[9]:
import random

def bubble_sort(lst):
    n = 0
    for j in range(len(lst) - 1):
        for i in range(len(lst) - 1 - j):
            n = n + 1
            if lst[i] > lst[i+1]:
                lst[i + 1], lst[i] = lst[i], lst[i+1]
    return n

def merge_sort_rec(data, l, r, work):
    if l+1 >= r:
        return 0
    m = l+(r-l)//2
    n1 = merge_sort_rec(data, l, m, work)
    n2 = merge_sort_rec(data, m, r, work)
    n = 0
    i1 = l
    i2 = m
    for i in range(l, r):
        from1 = False
        if i2 >= r:
            from1 = True
        elif i1 < m:
            n = n + 1
            if data[i1] <= data[i2]:
                from1 = True
        if from1:
            work[i] = data[i1]
            i1 = i1 + 1
        else:
            work[i] = data[i2]
            i2 = i2 + 1
    for i in range(l, r):
        data[i] = work[i]
    return n1+n2+n

def merge_sort(data):
    return merge_sort_rec(data, 0, len(data), [0]*len(data))
[10]:
x = np.arange(100, 1100, 100)
bdata = np.array([bubble_sort([random.randint(1,10000) for i in range(k)]) for k in x])
mdata = np.array([merge_sort([random.randint(1,10000) for i in range(k)]) for k in x])
[11]:
p = figure(title='bubble sort vs. merge sort', x_axis_label='number of items', y_axis_label='number of comparisons')
p.line(x, bdata, line_color=c[0])
p.circle(x, bdata, color=c[0], line_width=5)
p.line(x, mdata, line_color=c[1])
p.circle(x, mdata, color=c[1], line_width=5)
show(p)

散布図

散布図の描画には、点のプロットを marker 引数で指定できる scatter() メソッドが便利です。 以下では、ランダムに生成した20個の要素からなる配列 xy の各要素の値の組みを点としてプロットした散布図を表示します。 プロットする点のマーカは円とし、size 引数で大きさを、alpha 引数で透明度を設定しています。

[12]:
# グラフのx軸の値となる配列
x = np.random.rand(20)
# グラフのy軸の値となる配列
y = np.random.rand(20)

p = figure()
p.scatter(x, y, marker='circle', size=16, alpha=0.5)
show(p)

これと同じグラフは、単に circle() メソッドでプロットをすることでも描画できます。

[13]:
p = figure()
p.circle(x, y, size=16, alpha=0.5)
show(p)
BokehDeprecationWarning: 'circle() method with size value' was deprecated in Bokeh 3.4.0 and will be removed, use 'scatter(size=...) instead' instead.

棒グラフ

棒グラフは、vbar() メソッドを用いて描画できます。 次の例では、ランダムに生成した10個の要素からなる配列 y の各要素の値を縦の棒グラフで表示しています。 x は、x軸上で棒グラフのバーの並ぶ位置を示しています。 ここでは、numpy モジュールの arange() 関数を用いて、1 から 10 の範囲を 1 刻みでx軸上のバーの並ぶ位置として配列を準備しています。

[14]:
# x軸上で棒の並ぶ位置となる配列
x = np.arange(1, 11, 1)
# グラフのy軸の値となる配列
y = np.random.rand(10)

p = figure()
p.vbar(x, 0.5, y) # 第2引数は幅
show(p)

ヒストグラム

ヒストグラムの描画には、quad() メソッドが便利です。 次の例では、numpy.random.randn() 関数を用いて、正規分布に基づく 1000 個の数値の要素からなる配列を用意し、numpy.histogram() 関数を使って20個のビンに分類したヒストグラムを計算しています。 その計算結果を、quad() メソッドを使って、描画しています。 ビンの境界を見やすくするように、line_colorfill_color(デフォルト色)を別の色にしています。

[15]:
# 正規分布に基づく1000個の数値の要素からなる配列
d = np.random.randn(1000)
# numpy.histogramで20のビンに分割
hist, bin_edges = np.histogram(d, 20)
p = figure()
p.quad(top=hist, bottom=0, left=bin_edges[:-1], right=bin_edges[1:], line_color='white', alpha=0.5)
show(p)

ヒートマップ

最後に、複雑な応用例として、ヒートマップの描画方法を示します。 次の例は、10x10 のマスに 0.0 以上 1.0 未満の乱数の温度を割り当て、その値に応じた色で塗ったヒートマップです。 ここでは、これまでと違って、x軸、y軸、温度の3つの値が必要になります。 そこで、bokeh.models.ColumnDataSource 型を用いて、その3つ組を、'x''y''T' の属性を持った表データを構築しています。 この表データの構築には、7-1で説明するpandasも使えます。

ヒートマップでは、温度に応じた階調のある色選択が必要です。 そこで、色階調と値を対応付ける bokeh.models.LinearColorMapper 型の mapper を準備します。 rect() メソッドでは、表データの属性を参照して描画しています。 色は、表データの値を mapper に適用して色に変化させたものを用いることで、温度に応じた色選択を実現しています。 最後に、目盛り付きのカラーバーを生成して、右に配置しています。

[16]:
from bokeh.models import LinearColorMapper, BasicTicker, PrintfTickFormatter, ColorBar, ColumnDataSource
from bokeh.transform import transform

# 10行10列のランダム要素からなる行列
n = 10
data = np.random.rand(n*n)
src = ColumnDataSource({'x': [yx % n for yx in range(n*n)], 'y': [yx // n for yx in range(n*n)], 'T' : data})

colors = ['#75968f', '#a5bab7', '#c9d9d3', '#e2e2e2', '#dfccce', '#ddb7b1', '#cc7878', '#933b41', '#550b1d']
mapper = LinearColorMapper(palette=colors, low=data.min(), high=data.max())
p = figure()
p.rect('x', 'y', 1, 1, source=src, line_color=None, fill_color=transform('T', mapper))
color_bar = ColorBar(color_mapper=mapper, location=(0, 0),
                     ticker=BasicTicker(desired_num_ticks=len(colors)),
                     formatter=PrintfTickFormatter(format='%2.1f'))
p.add_layout(color_bar, 'right')
show(p)

グラフのファイル出力

これまで表示されてきたグラフには画像保存ボタンがあるので、それをクリックすればPNG形式の画像を保存できます。

bokeh.plotting.output_file() を用いると、グラフ単独をHTMLファイルとして保存できるようになります。 ただし、既に output_notebook() を読んでいる場合、bokeh.plotting.reset_output() で状態をリセットする必要があります。

[17]:
from bokeh.plotting import save, output_file, reset_output
x = np.arange(-2*np.pi, 2*np.pi, 0.1)
p = figure(title='sin Curves', x_axis_label='x', y_axis_label='y')
p.line(x, np.sin(x))

reset_output() # output_notebook()の効果を消す
output_file('sin.html') # 出力先の設定
save(p) # グラフを保存するだけ
show(p) # 保存した上でブラウザを開く
0:116: execution error: ファイル“不特定のオブジェクト”が見つかりませんでした。 (-43)

注意output_notebook() を呼んだ状態と output_file() を呼んだ状態が重なると、show() でエラーが起きます。

[ ]:

================================================ FILE: docs/appendix/5-command.html ================================================ ▲Pythonスクリプトとコマンドライン実行 — Pythonプログラミング入門 documentation

▲Pythonスクリプトとコマンドライン実行

Pythonスクリプトとコマンドライン実行について説明します。

参考

実は、第4回で紹介したモジュールファイル(拡張子 .py)は、それ単独で直接実行可能な自己完結したプログラムです。 直接実行されるPythonプログラムコードのことを指して特に、Pythonスクリプトと呼びます。 モジュールかスクリプトかを区別しないときには、Pythonソースファイルや .py ファイル等と呼ばれます。

たとえば、次のコードセルを実行してみてください。

[1]:
a1 = 10
print('a1 contains the value of', a1)
a1 contains the value of 10

この内容と全く同じコードを記述したPythonスクリプトファイル sample.py を教材として用意しました。

オペレーティングシステム(実際にはシェル)から sample.py を実行するには、以下のようにします。

>>> python sample.py

あるいは

>>> python3 sample.py

ここで、>>> は、シェルのプロンプト(コマンド入力を促す記号)を意味します。 後に示す具体例を見るとわかるように、環境によっては > であったり、$ であったりします。

このようにスクリプトをシェルから実行することを、コマンドライン実行と呼びます。

コマンドライン実行の具体例

sample.py をコマンドライン実行する具体例を、実行環境毎に説明します。

Jupyter Notebook での実行方法

ファイルマネージャ画面で、

New ⇒ Terminal

を選択すると、ターミナルのタブが生成されます。

fig/terminal-in-menu.png

Windows 10 の環境(ユーザーアカウント名 sato)では、次のように表示されます。

fig/console-in-browser.png

次の例では、cd コマンドで sample.py が存在するディレクトリ materials/5/ に移動し、その上で sample.py を実行しています。

fig/sample-py-browser.png

Jupyter Notebook 上で開かれるターミナルは、環境によって違います。 デフォルトでは、Windows 10 ではPowerShellが起動し、macOSならばbashが起動するでしょう。

Windowsでの実行方法

以下をクリックすれば、ターミナルが開いて python をコマンドとして実行できます。

Start メニュー ⇒ Anaonda3(64-bit) ⇒ Anaconda Prompt

fig/sample-py-win-1.png

下記のようなウインドウが表示されます。

fig/sample-py-win-2.png

Windowsのユーザーアカウント名のついたフォルダ(画像では、KMK)の中に pythontest というフォルダを作成し、その中に sample.py を格納した場合の実行例を示します。

例では、cd というコマンドで sample.py を格納したフォルダ pythontest に移動し、その上で sample.py を実行しています。

fig/sample-py-win-3.png

macOS での実行方法

Application ⇒ Utilities ⇒ Terminal.app を起動します。

アプリケーション ⇒ ユーティリティ ⇒ ターミナル.app を起動します。(日本語の場合)

fig/sample-py-mac-1.png

下記のようなウインドウが表示されます。

fig/sample-py-mac-2.png

ダウンロードフォルダ (Downloads) に sample.py を格納した場合の実行例を示します。

例では、cd というコマンドで sample.py を格納した Downloads フォルダに移動し、その上で sample.py を実行しています。

fig/sample-py-mac-3.png

コマンドライン引数

コマンドライン実行時には、実行スクリプト名の後に、文字列を書き込むことにより、実行スクリプトへ引数を与えることができます。 この引数のことを、コマンドライン引数と呼びます。

たとえば、argsprint.py というスクリプトファイルをコマンドライン実行することを考えます。

>>> python argsprint.py

ここで、 argsprint.py の後ろに、適当な文字列を付け加えます。たとえば、以下のように3つの文字列 firstvalue secondvalue thirdvalue をスペースで区切って付け加えてみます。

>>> python argsprint.py firstvalue secondvalue thirdvalue

このとき、この3つの文字列が argsprint.py にコマンドライン引数として与えられることになります。

この引数は、sys モジュールの argv という変数 (sys.argv) にリストとして格納されます。

argsprint.py を次のようなコードからなるファイルとしましょう。

argsprint.py:

import sys
print(sys.argv) # リスト sys.argv の中身を印字

このような argsprint.py を先の例のように実行すると、以下の画像のような結果が得られます。リスト sys.argv に2番目の要素として文字列 firstvalue が、3番目の要素として文字列 secondvalue が、4番目の要素として文字列 thirdvalue が格納されていることを確認してください。また、リストの最初の要素には、実行したスクリプト名(ここでは argsprint.py)が格納されることに注意してください。

fig/argsprint.png

練習

上記に従って argsprint.py ファイルを作成して、引数を変更したり、引数の数を増やしたり減らしたりして、表示がどう変わるか調べてください。

練習

コマンドライン実行時に、コマンドライン引数の1番目を印字 (print) する arg1.py を作成せよ。

練習

コマンドライン実行時に、スクリプト名を印字する scriptname.py を作成してください。

練習

コマンドライン実行時に、コマンドライン引数の数を印字する numargs.py を作成してください。

練習

コマンドライン引数として与えられた任意個の整数の和を印字する sum.py を作成してください。

たとえば、次のように実行すると、

>>> python sum.py 1 2 3

6 と印字されます。

なお、コマンドライン引数は文字列型であることに注意してください。。

[2]:
v1 = '100'
v2 = '200'
int(v1) + int(v2) # 整数加算
[2]:
300
[3]:
v1 + v2 # 文字列結合
[3]:
'100200'

モジュールのコマンドライン実行

さて、モジュールファイルは、それ自体が単独で実行可能であると述べました。 つまり、Pythonソースファイルは、モジュールとしてインポートされる場合と、スクリプトとしてコマンドライン実行される場合の2通りが考えられるわけです。

あるモジュールが、インポートされたのか、スクリプトとしてコマンドライン実行されたのかは、プログラム中の __name__ という組み込み変数を参照することで区別できます。

具体的には、モジュール mod.py がコマンドライン実行されたとき、__name__ の値は '__main__' になります。 一方、import mod されたとき、__name__ の値は 'mod' になります。

これを利用することで、インポートされた場合とコマンドライン実行された場合で、モジュールの振舞いを変えることができます。 たとえば、次に示す factorial.py モジュールを考えます。

factorial.py:

import sys

# 階乗n!を返す
def fact(n):
    prod = 1
    for i in range(1, n + 1):
        prod *= i
    return prod

if __name__ == '__main__':
    n = int(sys.argv[1]) # 整数nが1番目のコマンドライン引数で与えられる
    print(fact(n))       # n!を印字

これに対して、import factorial すると、階乗を計算する関数 factorial.fact() が利用できるようになります。 一方、python factorial.py 6 とコマンドライン実行すると、6の階乗である 720 が印字されます。 つまり、このモジュールは、階乗を計算するライブラリとしても、階乗を計算するスクリプトとしても利用できるわけです。

もし if __name__ == '__main__' の条件分岐が無かったら、モジュールとしてインポートしたときに、インポート元のスクリプトのために与えられたコマンドライン引数を使って、階乗を計算・印字しようとします。 これは一般に、望ましい振舞いではありません。

このように、if __name__ == '__main__' の分岐中には、自己完結したスクリプトとしての振舞いが記述されます。

ライブラリモジュールとして使うことのみが想定されている場合、テストコードが記述されることもあります。 たとえば、次のように記述すると、

factorial.py:

import sys

# 階乗n!を返す
def fact(n):
    prod = 1
    for i in range(1, n + 1):
        prod *= i
    return prod

if __name__ == '__main__':
    print('test n = 6:', fact(6) == 720)
    print('test n = 0:', fact(0) == 1)

コマンドライン実行したときには、fact() が正しく計算されているかテストした結果が印字されます。 このテストコードは、ライブラリモジュールとしてimportして利用するときには実行されません。 このようにすると、1つのPythonソースファイルの中で、ライブラリ実装とテストをひとまとめにできて、保守しやすくなります。

ソースファイル先頭部分にある宣言

文字コード宣言

PythonソースコードはUTF-8で記述することが公式に推奨されています

しかし、特にWindows環境では、歴史的事情からShift_JIS (shift_jis) が使われることがあります。 このとき、Pythonソースファイルの先頭部分には、次のような文字コード宣言が必要です。

# -*- coding: shift_jis -*-

これがないと、Pythonインタプリタがエラーを出して止まります。

なお、UTF-8で記述されている場合には、文字コード宣言を記述しないことが公式に推奨されています

shebang

Unix環境(macOSを含む)では、スクリプトファイルの先頭行には、そのスクリプトを実行するコマンドを指定できるようになっています。 この先頭行のことは、shebangと呼ばれます。

Unix環境でPythonスクリプトに用いられる標準的なshebangは次です。

#!/usr/bin/env python3

#! に続く部分で、コマンドを絶対パスで指定します。 env コマンドは、その引数(ここでは python3)の名前のコマンドを、環境の中から探して実行します。 したがって、上のように記述すると、Pythonインタプリタがインストールされている場所を気にせずに、Unix環境におけるPython3系列の標準コマンド名である python3 を使って実行できるようになります。

shebangと文字コード宣言の両方を含む場合は、たとえば、次のようになります。

#!/usr/bin/env python3
# -*- coding: shift_jis -*-

練習の解答

各セルのコードを保存した .py ファイルが解答です。

[4]:
#arg1.py
import sys
print(sys.argv[1])
-f
[5]:
#scriptname.py
import sys
print(sys.argv[0])
/Users/jmori/Projects/utpython/lib/python3.12/site-packages/ipykernel_launcher.py
[6]:
#numargs.py
import sys
num = len(sys.argv) - 1 # sys.argv[0]はコマンドライン引数ではないので1減らす
print(num)
3
[7]:
#sum.py
import sys
s = 0
for v in sys.argv[1:]:
    s += int(v)
print(s)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[7], line 5
      3 s = 0
      4 for v in sys.argv[1:]:
----> 5     s += int(v)
      6 print(s)

ValueError: invalid literal for int() with base 10: '-f'
================================================ FILE: docs/appendix/5-matplotlib.html ================================================ ▲Matplotlibライブラリ — Pythonプログラミング入門 documentation

▲Matplotlibライブラリ

Matplotlibライブラリについて説明します。

参考

Matplotlibライブラリにはグラフを可視化するためのモジュールが含まれています。以下では、Matplotlibライブラリのモジュールを使った、グラフの基本的な描画について説明します。

Matoplotlibライブラリを使用するには、まず matplotlib のモジュールをインポートします。ここでは、基本的なグラフを描画するための matplotlib.pyplot モジュールをインポートします。慣例として、同モジュールを plt と別名をつけてコードの中で使用します。また、グラフで可視化するデータはリストや配列を用いることが多いため、5-3で使用した numpy モジュールも併せてインポートします。なお、%matplotlib inline はノートブック内でグラフを表示するために必要です。

matplotlib では、通常 show() 関数を呼ぶと描画を行いますが、inline 表示指定の場合、show() 関数を省略できます。

[1]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

線グラフ

pyplot モジュールの plot() 関数を用いて、リストの要素の数値をy軸の値としてグラフを描画します。y軸の値に対応するx軸の値は、リストの各要素のインデックスとなっています。

具体的には、次のようにすることで リストA のインデックス i に対して、(i, リストA[i]) の位置に点を打ち、各点を線でつなぎます。

plt.plot(リストA)

たとえば、次のようになります。

[2]:
# plotするデータ
d =[0, 1, 4, 9, 16]

# plot関数で描画
plt.plot(d);
# セルの最後に評価されたオブジェクトの出力表示を抑制するために、以下ではセルの最後の行にセミコロン (`;`) をつけています。
# 試しにセミコロンを消した場合も試してみてください。
../_images/appendix_5-matplotlib_3_0.png

plot() 関数では、x, y の両方の軸の値を引数に渡すこともできます。

具体的には、次のように リストXリストY を引数として与えると、各 i に対して、 (リストX[i], リストY[i]) の位置に点を打ち、各点を線でつなぎます。

plt.plot(リストX, リストY)
[3]:
# plotするデータ
x =[0, 1, 2, 3, 4]
y =[0, 3, 6, 9, 12]

# plot関数で描画
plt.plot(x,y);
../_images/appendix_5-matplotlib_5_0.png

リストの代わりにNumPyライブラリの配列を与えても同じ結果が得られます。

[4]:
# plotするデータ
x =[0, 1, 2, 3, 4]
aryx = np.array(x) # リストから配列を作成
y =[0, 3, 6, 9, 12]
aryy = np.array(y) # リストから配列を作成

# plot関数で描画
plt.plot(aryx, aryy);
../_images/appendix_5-matplotlib_7_0.png

以下のようにグラフを複数まとめて表示することもできます。複数のグラフを表示すると、線ごとに異なる色が自動で割り当てられます。

[5]:
# plotするデータ
data =[0, 1, 4, 9, 16]
x =[0, 1, 2, 3, 4]
y =[0, 1, 2, 3, 4]
# plot関数で描画。
plt.plot(x, y)
plt.plot(data);
../_images/appendix_5-matplotlib_9_0.png

plot() 関数ではグラフの線の色、形状、データポイントのマーカの種類を、それぞれ以下のように linestyle, color, marker 引数で指定して変更することができます。それぞれの引数で指定可能な値は以下を参照してください。

[6]:
# plotするデータ
data =[0, 1, 4, 9, 16]
x =[0, 1, 2, 3, 4]
y =[0, 1, 2, 3, 4]

# plot関数で描画。線の形状、色、データポイントのマーカ指定
plt.plot(x,y, linestyle='--', color='blue', marker='o')
plt.plot(data, linestyle=':', color='green', marker='*');
../_images/appendix_5-matplotlib_11_0.png

plot() 関数の label 引数にグラフの各線の凡例を文字列として渡し、legend() 関数を呼ぶことで、グラフ内に凡例を表示できます。legend() 関数の loc 引数で凡例を表示する位置を指定することができます。引数で指定可能な値は以下を参照してください。

[7]:
# plotするデータ
data =[0, 1, 4, 9, 16]
x =[0, 1, 2, 3, 4]
y =[0, 1, 2, 3, 4]

# plot関数で描画。線の形状、色、データポイントのマーカ指定
plt.plot(x,y, linestyle='--', color='blue', marker='o', label='linear')
plt.plot(data, linestyle=':', color='green', marker='*', label='quad')
#凡例を表示
plt.legend();
../_images/appendix_5-matplotlib_13_0.png

pyplot モジュールでは、以下のようにグラフのタイトルと各軸のラベルを指定して表示することができます。タイトル、x軸のラベル、y軸のラベル、はそれぞれ title() 関数、xlabel() 関数、ylabel() 関数に文字列を渡して指定します。また、grid() 関数を用いるとグリッドを併せて表示することもできます。グリッドを表示させたい場合は、grid() 関数に True を渡してください。

[8]:
# plotするデータ
data =[0, 1, 4, 9, 16]
x =[0, 1, 2, 3, 4]
y =[0, 1, 2, 3, 4]

# plot関数で描画。線の形状、色、データポイントのマーカ、凡例を指定
plt.plot(x,y, linestyle='--', color='blue', marker='o', label='linear')
plt.plot(data, linestyle=':', color='green', marker='*', label='quad')
plt.legend()

plt.title('My First Graph') # グラフのタイトル
plt.xlabel('x') #x軸のラベル
plt.ylabel('y') #y軸のラベル
plt.grid(True); #グリッドの表示
../_images/appendix_5-matplotlib_15_0.png

グラフを描画するときのプロット数を増やすことで任意の曲線のグラフを作成することもできます。以下では、numpy モジュールの arange() 関数を用いて、\(- \pi\) から \(\pi\) の範囲を 0.1 刻みでx軸の値を配列として準備しています。そのx軸の値に対して、numpy モジュールの cos() 関数と sin() 関数を用いて、y軸の値をそれぞれ準備し、cosカーブとsinカーブを描画しています。

[9]:
# グラフのx軸の値となる配列
x = np.arange(-np.pi, np.pi, 0.1)

# 上記配列をcos, sin関数に渡し, y軸の値として描画
plt.plot(x,np.cos(x))
plt.plot(x,np.sin(x))

plt.title('cos ans sin Curves')  # グラフのタイトル
plt.xlabel('x') #x軸のラベル
plt.ylabel('y') #y軸のラベル
plt.grid(True); #グリッドの表示
../_images/appendix_5-matplotlib_17_0.png

プロットの数を少なくすると、曲線は直線をつなぎ合わせることで描画されていることがわかります。

[10]:
x = np.arange(-np.pi, np.pi, 0.5)
plt.plot(x,np.cos(x), marker='o')
plt.plot(x,np.sin(x), marker='o')
plt.title('cos ans sin Curves')
plt.xlabel('x')
plt.ylabel('y')
plt.grid(True);
../_images/appendix_5-matplotlib_19_0.png

グラフの例:ソートアルゴリズムにおける比較回数

[11]:
import random

def bubble_sort(lst):
    n = 0
    for j in range(len(lst) - 1):
        for i in range(len(lst) - 1 - j):
            n = n + 1
            if lst[i] > lst[i+1]:
                lst[i + 1], lst[i] = lst[i], lst[i+1]
    return n

def merge_sort_rec(data, l, r, work):
    if l+1 >= r:
        return 0
    m = l+(r-l)//2
    n1 = merge_sort_rec(data, l, m, work)
    n2 = merge_sort_rec(data, m, r, work)
    n = 0
    i1 = l
    i2 = m
    for i in range(l, r):
        from1 = False
        if i2 >= r:
            from1 = True
        elif i1 < m:
            n = n + 1
            if data[i1] <= data[i2]:
                from1 = True
        if from1:
            work[i] = data[i1]
            i1 = i1 + 1
        else:
            work[i] = data[i2]
            i2 = i2 + 1
    for i in range(l, r):
        data[i] = work[i]
    return n1+n2+n

def merge_sort(data):
    return merge_sort_rec(data, 0, len(data), [0]*len(data))
[12]:
x = np.arange(100, 1100, 100)
bdata = np.array([bubble_sort([random.randint(1,10000) for i in range(k)]) for k in x])
mdata = np.array([merge_sort([random.randint(1,10000) for i in range(k)]) for k in x])
[13]:
plt.plot(x, bdata, marker='o')
plt.plot(x, mdata, marker='o')
plt.title('bubble sort vs. merge sort')
plt.xlabel('number of items')
plt.ylabel('number of comparisons')
plt.grid(True);
../_images/appendix_5-matplotlib_23_0.png

練習

-2 から 2 の範囲を 0.1 刻みでx軸の値を配列として作成し、そのx軸の値に対して numpy モジュールの exp() 関数を用いてy軸の値を作成し、\(y=e^{x}\) のグラフを描画する関数 plot_exp を作成してください。ただし、そのグラフに任意のタイトル、x軸、y軸の任意のラベル、任意の凡例、グリッドを表示させてください。

[14]:
import ...
...
def plot_exp():
    ...
  Cell In[14], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[15]:
res_x = plot_exp()
print(len(res_x) == 41, int(res_x[0]) == -2, int(res_x[9]) == -1)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[15], line 1
----> 1 res_x = plot_exp()
      2 print(len(res_x) == 41, int(res_x[0]) == -2, int(res_x[9]) == -1)

NameError: name 'plot_exp' is not defined

練習

4-csvで説明したように、tokyo-temps.csv には、気象庁のオープンデータからダウンロードした、東京の平均気温のデータが入っています。具体的には、各行の第2列に気温の値が格納されており、47行目に1875年6月の、48行目に1875年7月の、…、53行目に1875年12月の、54行目に1876年1月の、…という風に2017年1月のデータまでが格納されています。

そこで、2つの整数 yearmonth を引数として取り、 year 年以降の month 月の平均気温の値をy軸に、年をx軸に描画した線グラフを表示するとともに、描画したx軸とy軸の値をタプルに格納して返す関数 plot_tokyotemps を作成してください。

以下のセルの ... のところを書き換えて解答してください。

[16]:
import ...
...
def plot_tokyotemps(year, month):
    ...
  Cell In[16], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[17]:
res_years, res_temps = plot_tokyotemps(1875, 7)
print(len(res_years) == 142, len(res_temps) == 142, res_years[0] == 1875, res_temps[0] == 26.0)
res_years, res_temps = plot_tokyotemps(1875, 6)
print(len(res_years) == 142, len(res_temps) == 142, res_years[0] == 1875, res_temps[0] == 22.3)
res_years, res_temps = plot_tokyotemps(1875, 12)
print(len(res_years) == 142, len(res_temps) == 142, res_years[0] == 1875, res_temps[0] == 4.6)
res_years, res_temps = plot_tokyotemps(1876, 1)
print(len(res_years) == 142, len(res_temps) == 142, res_years[0] == 1876, res_temps[0] == 1.6)
res_years, res_temps = plot_tokyotemps(1876, 6)
print(len(res_years) == 141, len(res_temps) == 141, res_years[0] == 1876, res_temps[0] == 18.5)
res_years, res_temps = plot_tokyotemps(1900, 6)
print(len(res_years) == 117, len(res_temps) == 117, res_years[0] == 1900, res_temps[0] == 19.3)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[17], line 1
----> 1 res_years, res_temps = plot_tokyotemps(1875, 7)
      2 print(len(res_years) == 142, len(res_temps) == 142, res_years[0] == 1875, res_temps[0] == 26.0)
      3 res_years, res_temps = plot_tokyotemps(1875, 6)

NameError: name 'plot_tokyotemps' is not defined

散布図

散布図は、pyplot モジュールの scatter() 関数を用いて描画できます。

具体的には、次のように リストXリストY (もしくは、 配列X配列Y)を引数として与えると、各 i に対して、 (リストX[i], リストY[i]) の位置に点を打ちます。

plt.scatter(リストX, リストY)

以下では、ランダムに生成した20個の要素からなる配列 x, y の各要素の値の組を点としてプロットした散布図を表示しています。プロットする点のマーカの色や形状は、線グラフの時と同様に、 color, marker 引数で指定して変更することができます。加えて、s, alpha 引数で、それぞれマーカの大きさと透明度を指定することができます。

[18]:
# グラフのx軸の値となる配列
x = np.random.rand(20)
# グラフのy軸の値となる配列
y = np.random.rand(20)

# scatter関数で散布図を描画
plt.scatter(x, y, s=100, alpha=0.5);
../_images/appendix_5-matplotlib_33_0.png

以下のように、plot() 関数を用いても同様の散布図を表示することができます。具体的には、3番目の引数にプロットする点のマーカの形状を指定することにより実現します。

[19]:
x = np.random.rand(20)
y = np.random.rand(20)
plt.plot(x, y, '*', color='blue');
../_images/appendix_5-matplotlib_35_0.png

練習

tokyo-temps.csv には、気象庁のオープンデータからダウンロードした、東京の平均気温のデータが入っています。具体的には、各行の第2列に気温の値が格納されており、47行目に1875年6月の、48行目に1875年7月の、…、53行目に1875年12月の、54行目に1876年1月の、…という風に2017年1月のデータまでが格納されています。

そこで、1875年以降の平均気温の値をy軸に、月の値をx軸に描画した散布図を表示するとともに、描画したx軸とy軸の値をタプルに格納して返す関数 scatter_tokyotemps を作成してください。

以下のセルの ... のところを書き換えて解答してください。

[20]:
import ...
...
def scatter_tokyotemps():
    ...
  Cell In[20], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[21]:
res_months, res_temps = scatter_tokyotemps()
print(len(res_months) == 1700, len(res_temps) == 1700, res_months[0] == 6, res_months[1] == 7, res_months[12] == 6, res_months[13] == 7)
print(res_temps[0] == 22.3, res_temps[1] == 26.0, res_temps[12] == 18.5, res_temps[13] == 24.3)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[21], line 1
----> 1 res_months, res_temps = scatter_tokyotemps()
      2 print(len(res_months) == 1700, len(res_temps) == 1700, res_months[0] == 6, res_months[1] == 7, res_months[12] == 6, res_months[13] == 7)
      3 print(res_temps[0] == 22.3, res_temps[1] == 26.0, res_temps[12] == 18.5, res_temps[13] == 24.3)

NameError: name 'scatter_tokyotemps' is not defined

棒グラフ

棒グラフは、pyplot モジュールの bar() 関数を用いて描画できます。以下では、ランダムに生成した10個の要素からなる配列 y の各要素の値を縦の棒グラフで表示しています。x は、x軸上で棒グラフのバーの並ぶ位置を示しています。ここでは、numpy モジュールの arange() 関数を用いて、1 から 10 の範囲を 1 刻みでx軸上のバーの並ぶ位置として配列を準備しています。

[22]:
# x軸上で棒の並ぶ位置となる配列
x = np.arange(1, 11, 1)
# グラフのy軸の値となる配列
y = np.random.rand(10)

# bar関数で棒グラフを描画
#print(x, y)
plt.bar(x,y);
../_images/appendix_5-matplotlib_41_0.png

練習

tokyo-temps.csv には、気象庁のオープンデータからダウンロードした、東京の平均気温のデータが入っています。具体的には、各行の第2列に気温の値が格納されており、47行目に1875年6月の、48行目に1875年7月の、…、53行目に1875年12月の、54行目に1876年1月の、…という風に2017年1月のデータまでが格納されています。

そこで、4つの引数 year1, month1, year2, month2 を引数に取り、 year1month1 月から year2month2 月までの各月の平均気温の値をy軸に、年月の値(tokyo-temps.csv の1列目の値)をx軸に描画した棒グラフを表示するとともに、描画したx軸とy軸の値をタプルに格納して返す関数 bar_tokyotemps を作成してください。

以下のセルの ... のところを書き換えて解答してください。

[23]:
import ...
...
def bar_tokyotemps(year1, month1, year2, month2):
    ...
  Cell In[23], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[24]:
res_months, res_temps = bar_tokyotemps(2000, 6, 2001, 6)
print(len(res_months) == 13, res_months[0] == '2000/6', res_temps[0] == 22.5, res_months[12] == '2001/6', res_temps[12] == 23.1)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[24], line 1
----> 1 res_months, res_temps = bar_tokyotemps(2000, 6, 2001, 6)
      2 print(len(res_months) == 13, res_months[0] == '2000/6', res_temps[0] == 22.5, res_months[12] == '2001/6', res_temps[12] == 23.1)

NameError: name 'bar_tokyotemps' is not defined

ヒストグラム

ヒストグラムは、pyplot モジュールの hist() 関数を用いて描画できます。 以下では、numpy モジュールの random.randn() 関数を用いて、正規分布に基づく1000個の数値の要素からなる配列を用意し、ヒストグラムとして表示しています。 hist() 関数の bins 引数でヒストグラムの箱(ビン)の数を指定します。

[25]:
# 正規分布に基づく1000個の数値の要素からなる配列
d = np.random.randn(1000)

# hist関数でヒストグラムを描画
plt.hist(d, bins=20);
../_images/appendix_5-matplotlib_47_0.png

練習

tokyo-temps.csv には、気象庁のオープンデータからダウンロードした、東京の平均気温のデータが入っています。具体的には、各行の第2列に気温の値が格納されており、47行目に1875年6月の、48行目に1875年7月の、…、53行目に1875年12月の、54行目に1876年1月の、…という風に2017年1月のデータまでが格納されています。

そこで、5つの引数 year1, month1, year2, month2, mybin を引数に取り、 year1month1 月から year2month2 月までの各月の平均気温の値を格納したリスト temps から mybin 個のヒストグラムを表示するとともに、 temps を返す関数 hist_tokyotemps を作成してください。

以下のセルの ... のところを書き換えて解答してください。

[26]:
import ...
...
def hist_tokyotemps(year1, month1, year2, month2, mybin):
    ...
  Cell In[26], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[27]:
res_temps = hist_tokyotemps(1875, 6, 2000, 6, 50)
print(len(res_temps) == 1501, res_temps[0] == 22.3, res_temps[1500] == 22.5)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[27], line 1
----> 1 res_temps = hist_tokyotemps(1875, 6, 2000, 6, 50)
      2 print(len(res_temps) == 1501, res_temps[0] == 22.3, res_temps[1500] == 22.5)

NameError: name 'hist_tokyotemps' is not defined

ヒートマップ

impshow() 関数を用いると、以下のように行列の要素の値に応じて色の濃淡を変えることで、行列をヒートマップとして可視化することができます。colorbar() 関数は行列の値と色の濃淡の対応を表示します。

[28]:
# 10行10列のランダム要素からなる行列
ary1 = np.random.rand(100)
ary2 = ary1.reshape(10,10)
#ary2 = np.random.rand(100).reshape(10,10) #と同じ

# imshow関数でヒートマップを描画
im=plt.imshow(ary2)
plt.colorbar(im);
../_images/appendix_5-matplotlib_53_0.png

練習

tokyo-temps.csv には、気象庁のオープンデータからダウンロードした、東京の平均気温のデータが入っています。具体的には、各行の第2列に気温の値が格納されており、47行目に1875年6月の、48行目に1875年7月の、…、53行目に1875年12月の、54行目に1876年1月の、…という風に2017年1月のデータまでが格納されています。

そこで、30×12のNumPyの配列 ary1 を作成し、各月の平均気温を整数に丸めた値を求めて、月ごとにその値の数を数えて配列 ary1 に格納して、 ary1 からなるヒートマップを表示しつつ、 ary1 を返す関数 heat_tokyotemps を作成してください。 ただし、厳密には x0 以上 11 以下の任意の整数とし、y0 以上 29 以下の整数とするとき、 ary1[y][x] には、 y ℃以上、 y+1 ℃より小さい平均気温を持つ x+1 月の数が格納されているものとします。

以下のセルの ... のところを書き換えて解答してください。

[29]:
import ...
...
def heat_tokyotemps():
    ...
  Cell In[29], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[30]:
ary1 = heat_tokyotemps()
print(ary1[0][0] == 2, ary1[1][1] == 2, ary1[2][0] == 28)
#画像の向きが気になる人は、以下の2行を同時に実行してみてください
#ary1 = np.flip(ary1, axis=0)
#im=plt.imshow(ary1)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[30], line 1
----> 1 ary1 = heat_tokyotemps()
      2 print(ary1[0][0] == 2, ary1[1][1] == 2, ary1[2][0] == 28)
      3 #画像の向きが気になる人は、以下の2行を同時に実行してみてください
      4 #ary1 = np.flip(ary1, axis=0) 
      5 #im=plt.imshow(ary1)

NameError: name 'heat_tokyotemps' is not defined

グラフの画像ファイル出力

savefig() 関数を用いると、以下のように作成したグラフを画像としてファイルに保存することができます。

[31]:
x = np.arange(-np.pi, np.pi, 0.1)
plt.plot(x,np.cos(x), label='cos')
plt.plot(x,np.sin(x), label='sin')
plt.legend()
plt.title('cos ans sin Curves')
plt.xlabel('x')
plt.ylabel('y')
plt.grid(True)

# savefig関数でグラフを画像保存
plt.savefig('cos_sin.png');
../_images/appendix_5-matplotlib_59_0.png

練習の解答

[32]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

def plot_exp():
    x = np.arange(-2, 2.1, 0.1)
    y = np.exp(x)
    plt.plot(x, y, linestyle='--', color='blue', marker='x', label='exp(x)')
    plt.title('y = exp(x)') # タイトル
    plt.xlabel('x') # x軸のラベル
    plt.ylabel('exp(x)') # y軸のラベル
    plt.grid(True); # グリッドを表示
    plt.legend() # 盆例を表示
    return x
[33]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import csv

def plot_tokyotemps(year, month):
    with open('tokyo-temps.csv', 'r', encoding='sjis') as f:
        dataReader = csv.reader(f) # csvリーダを作成
        n=0
        # 1875年6月が47行目なので、指定されたyear年6月のデータの行番号をまず求める
        init_row = (year - 1875) * 12 + 47
        # その上で、year年month月のデータの行番号を求める
        init_row = init_row + month - 6
        years = [] # 年
        temps = [] # 平均気温
        for row in dataReader: # CSVファイルの中身を1行ずつ読み込み
            n = n+1
            if n >= init_row and (n - init_row) % 12 == 0: # init_row行目からはじめて12か月ごとにif内を実行
                years.append(year)
                temp = float(row[1]) # float関数で実数のデータ型に変換する
                temps.append(temp)
                year = year + 1
    #print(years)
    #print(temps)
    plt.plot(years, temps)
    return years, temps
[34]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import csv

def scatter_tokyotemps():
    with open('tokyo-temps.csv', 'r', encoding='sjis') as f:
        dataReader = csv.reader(f) # csvリーダを作成
        n=0
        months = [] # 月
        temps = [] # 平均気温
        month = 6 # 47行目は6月
        for row in dataReader: # CSVファイルの中身を1行ずつ読み込み
            n = n+1
            if n >= 47: # 47行目からif内を実行
                months.append(month)
                temp = float(row[1]) # float関数で実数のデータ型に変換する
                temps.append(temp)
                month = month + 1
                if month > 12:
                    month = 1
    #print(months)
    #print(temps)
    plt.scatter(months, temps, alpha=0.5)
    return months, temps
[35]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import csv

def bar_tokyotemps(year1, month1, year2, month2):
    with open('tokyo-temps.csv', 'r', encoding='sjis') as f:
        dataReader = csv.reader(f) # csvリーダを作成
        n=0
        months = [] #
        temps = [] # 平均気温
        init_row = (year1 - 1875) * 12 - 6 + month1 + 47
        end_row = (year2 - 1875) * 12 - 6 + month2 + 47
        for row in dataReader: # CSVファイルの中身を1行ずつ読み込み
            n = n+1
            if n >= init_row and n <= end_row: # init_row行目から、end_row行までif内を実行
                months.append(row[0])
                temp = float(row[1]) # float関数で実数のデータ型に変換する
                temps.append(temp)
    #print(months)
    #print(temps)
    plt.bar(months, temps)
    return months, temps
[36]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import csv

def hist_tokyotemps(year1, month1, year2, month2, mybin):
    with open('tokyo-temps.csv', 'r', encoding='sjis') as f:
        dataReader = csv.reader(f) # csvリーダを作成
        n=0
        months = [] #
        temps = [] # 平均気温
        init_row = (year1 - 1875) * 12 - 6 + month1 + 47
        end_row = (year2 - 1875) * 12 - 6 + month2 + 47
        for row in dataReader: # CSVファイルの中身を1行ずつ読み込み
            n = n+1
            if n >= init_row and n <= end_row: # init_row行目から、end_row行までif内を実行
                temp = float(row[1]) # float関数で実数のデータ型に変換する
                temps.append(temp)
    #print(months)
    #print(temps)
    plt.hist(temps, bins=mybin)
    return temps
[37]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
import csv

def heat_tokyotemps():
    ary1 = np.zeros(30*12, dtype=int) # 30×12の配列を作成
    ary1 = ary1.reshape(30, 12)
    with open('tokyo-temps.csv', 'r', encoding='sjis') as f:
        dataReader = csv.reader(f) # csvリーダを作成
        n=0
        month = 6 # 一番最初の月(47行目)は6月
        for row in dataReader: # CSVファイルの中身を1行ずつ読み込み
            n = n+1
            if n >= 47: # 47行目からif内を実行
                temp = int(float(row[1])) # まずfloat関数で実数型に変換してから、int関数で整数のデータ型に変換する
                ary1[temp][month-1] += 1 # month月の値はmonth-1行目に格納する
                month += 1
                if month == 13:
                    month = 1
    im=plt.imshow(ary1)
    plt.colorbar(im);
    #print(ary1)
    return ary1
================================================ FILE: docs/appendix/5-re.html ================================================ ▲正規表現 — Pythonプログラミング入門 documentation

▲正規表現

正規表現について説明します。

参考

正規表現 (regular expression) を扱う場合、re というモジュールをインポートする必要があります。

[1]:
import re

正規表現の基本

正規表現とは、文字列のパターンを表す式です。 文字列が正規表現にマッチするとは、文字列が正規表現の表すパターンに適合していることを意味します。 また、正規表現が文字列にマッチするという言い方もします。

たとえば、正規表現 abc は文字列 abcde (の部分文字列 abc)にマッチします。

正規表現に文字列がマッチしているかどうかを調べることのできる関数に match があります。

match は、指定した 正規表現A文字列B(の先頭部分)にマッチするかどうか調べます。

re.match(正規表現A, 文字列B)
[2]:
match1 = re.match('abc', 'abcde') #マッチする
print(match1)
match1 = re.match('abc', 'ababc') #マッチしない
print(match1)
<re.Match object; span=(0, 3), match='abc'>
None

match では、マッチが成立している場合、matchオブジェクトと呼ばれる特殊なデータを返します。マッチが成立しない場合、 None を返します。

つまり、マッチする部分文字列を含む場合、返値は None ではないので、if文などの条件で真とみなされます。 したがって以下のようにして条件分岐することができます。

if re.match(正規表現, 文字列):
    ...
[3]:
if re.match('abc', 'abcde'): #マッチする
    print('正規表現abcが文字列abcdeにマッチする')
else:
    print('正規表現abcが文字列abcdeにマッチしない')
if re.match('abc', 'ababc'): #マッチしない
    print('正規表現abcが文字列ababcにマッチする')
else:
    print('正規表現abcが文字列ababcにマッチしない')
正規表現abcが文字列abcdeにマッチする
正規表現abcが文字列ababcにマッチしない

さて、上で紹介したmatchオブジェクトには、マッチした文字列の情報が格納されています。上のセルの1つ目の実行結果を印字したものを見てください。

<_sre.SRE_Match object; span=(0, 3), match='abc'> と表示されていると思います。このオブジェクト内の match という値は、マッチした文字列を、 span という値はマッチしたパターンが存在する、文字列のインデックスの範囲を表します。

正規表現では大文字と小文字は区別されます。たとえば、正規表現 abc は文字列 ABCdef にはマッチしません。勿論、正規表現 ABC も文字列 abcdef にはマッチしません。

[4]:
match1 = re.match('abc', 'ABCdef')
print(match1)
match1 = re.match('ABC', 'abcdef')
print(match1)
None
None

そこで match の3番目の引数として re.IGNORECASE もしくは re.I を指定すると、大文字と小文字を区別せずにマッチするかどうかを調べることができます。

[5]:
match1 = re.match('abc', 'ABCdef', re.IGNORECASE)
print(match1)
match1 = re.match('ABC', 'abcdef', re.IGNORECASE)
print(match1)
match1 = re.match('ABC', 'ABCdef', re.IGNORECASE)
print(match1)
match1 = re.match('abc', 'ABCdef', re.I)
print(match1)
match1 = re.match('ABC', 'abcdef', re.I)
print(match1)
match1 = re.match('ABC', 'ABCdef', re.I)
print(match1)
match1 = re.match('AbC', 'aBcdef', re.I)
print(match1)
<re.Match object; span=(0, 3), match='ABC'>
<re.Match object; span=(0, 3), match='abc'>
<re.Match object; span=(0, 3), match='ABC'>
<re.Match object; span=(0, 3), match='ABC'>
<re.Match object; span=(0, 3), match='abc'>
<re.Match object; span=(0, 3), match='ABC'>
<re.Match object; span=(0, 3), match='aBc'>

match は文字列の先頭がマッチするかどうか調べますので、次のような場合、matchオブジェクトを返さずに None が返されます。

[6]:
match1 = re.match('def', 'abcdef')
print(match1)
match1 = re.match('xyz', 'abcdef')
print(match1)
None
None

文字列の先頭しか調べられないのでは、いかにも不便です。

そこで、関数 search は、指定した 正規表現A文字列B に(文字列の先頭以外でも)マッチするかどうか調べることができます。

re.search(正規表現A, 文字列B)
[7]:
match1 = re.search('abc', 'abcdef')
print(match1)
match1 = re.search('abc', 'ababcd')
print(match1)
match1 = re.search('def', 'abcdef')
print(match1)
<re.Match object; span=(0, 3), match='abc'>
<re.Match object; span=(2, 5), match='abc'>
<re.Match object; span=(3, 6), match='def'>

search の場合も3番目の引数として re.IGNORECASE、 もしくは re.I を指定することで、大文字と小文字を区別せずにマッチするかどうかを調べることができます。

[8]:
match1 = re.search('abc', 'ABCdef')
print(match1)
match1 = re.search('DEF', 'abcdef')
print(match1)
match1 = re.search('abc', 'ABCdef', re.IGNORECASE)
print(match1)
match1 = re.search('DEF', 'abcdef', re.I)
print(match1)
match1 = re.search('not', 'It is NOT me.', re.I)
print(match1)
match1 = re.search('NOT', 'It is not mine.', re.I)
print(match1)
None
None
<re.Match object; span=(0, 3), match='ABC'>
<re.Match object; span=(3, 6), match='def'>
<re.Match object; span=(6, 9), match='NOT'>
<re.Match object; span=(6, 9), match='not'>

match 関数と同様に、 search 関数においても、if文を使った条件分岐が可能であることは覚えておいてください。

if re.search(正規表現, 文字列):
    ...
[9]:
if re.search('not', 'It is NOT me.'):
    print('正規表現notが文字列It is NOT me.にマッチする')
else:
    print('正規表現notが文字列It is NOT me.にマッチしない')
if re.search('not', 'It is NOT me.', re.I):
    print('正規表現notが文字列It is NOT me.にマッチする')
else:
    print('正規表現notが文字列It is NOT me.にマッチしない')
正規表現notが文字列It is NOT me.にマッチしない
正規表現notが文字列It is NOT me.にマッチする

文字列の先頭からのマッチを調べたいときには、正規表現の先頭にキャレット (^) をつけてください。また、文字列の最後からマッチさせたいときは、正規表現の最後にドル記号 ($) をつけてください。

[10]:
match1 = re.search('abc', 'ababcd')  #キャレットなしだとマッチする
print(match1)
match1 = re.search('^abc', 'ababcd') #キャレットありだとマッチしない
print(match1)
match1 = re.search('def', 'abcdefg') #ドル記号なしだとマッチする
print(match1)
match1 = re.search('def$', 'abcdefg') #ドル記号ありだとマッチしない
print(match1)
match1 = re.search('def$', 'abcdefxyzdef') # 2つあるうちの2番目(最後)の def にマッチする
print(match1)
<re.Match object; span=(2, 5), match='abc'>
None
<re.Match object; span=(3, 6), match='def'>
None
<re.Match object; span=(9, 12), match='def'>

ただ、ここまでの内容だと、正規表現を用いずに文字列のメソッド (find など)によっても実現が可能です。これでは正規表現を使うメリットはほとんどありません。

というのも、ここまで見てきた1つの正規表現によって、1つの文字列を表していたからです。しかし、最初に言った通り、正規表現は文字列の「パターン」を表します。すなわち、1つの正規表現で複数の文字列を表すことが可能なのです。

たとえば、正規表現 ab と正規表現 de という2つの正規表現を | という記号で繋げた ab|de も正規表現を表します。この正規表現では、abde という2つの文字列を表しており、これらのいずれかを含む文字列にマッチします。この | の記号(演算)を、もしくは選択といいます。

[11]:
match1 = re.search('ab|de', 'bcdef')
print(match1)
match1 = re.search('ab|de', 'abcdef')
print(match1)
match1 = re.search('ab|de', 'fgdeab')
print(match1)
match1 = re.search('ab|de', 'acdf')
print(match1)
match1 = re.search('a|an|the', 'I slipped on a piece of the banana.')
print(match1)
match1 = re.search('a|an|the', 'I slipped on the banana.')
print(match1)
match1 = re.search('Good (Morning|Evening)', 'Good Evening, Vietnam.') #正規表現内の()については下で述べます
print(match1)
match1 = re.search('colo(u|)r', 'That color matches your suit.') #正規表現内の()については下で述べます
print(match1)
match1 = re.search('colo(u|)r', 'That colour matches your suit.') #正規表現内の()については下で述べます
print(match1)
<re.Match object; span=(2, 4), match='de'>
<re.Match object; span=(0, 2), match='ab'>
<re.Match object; span=(2, 4), match='de'>
None
<re.Match object; span=(13, 14), match='a'>
<re.Match object; span=(13, 16), match='the'>
<re.Match object; span=(0, 12), match='Good Evening'>
<re.Match object; span=(5, 10), match='color'>
<re.Match object; span=(5, 11), match='colour'>

上記の3番目の例に注意してください。正規表現 ab | de では abde よりも先に記述されていますが、マッチする文字列は文字列上で先に出てきた方(ab ではなく、de)であることに注意してください。

細かい話ですが、正規表現 abc は、正規表現 a と正規表現 b と正規表現 c という3つの正規表現を繋げて構成された正規表現であり、このように正規表現を繋げて新しい正規表現を作る演算を連接といいます。

a* は、正規表現 a を0回以上繰り返した文字列とマッチします。この * の演算を閉包といいます。

[12]:
match1 = re.search('a*', 'abcdef')
print(match1)
match1 = re.search('a*', 'aabbcc')
print(match1)
match1 = re.search('a*', 'cde')
print(match1)
match1 = re.search('bo*', 'boooo!')
print(match1)
<re.Match object; span=(0, 1), match='a'>
<re.Match object; span=(0, 2), match='aa'>
<re.Match object; span=(0, 0), match=''>
<re.Match object; span=(0, 5), match='boooo'>

上記の3番目の例において(文字 a が含まれていないにも関わらず)None が返らずに、マッチしているのを不思議に思うかもしれません。しかし、a*a を0回反復した文字列にもマッチします。この0回反復した文字列とは、長さが0の文字列であり、空列とか空文字列と呼ばれます。文字列 cde の先頭には、空列があると見なせるので、a* が先頭部分にマッチしているのです。

たとえば、正規表現 abb* は、 ab, abb, abbb, … という文字列にマッチします。

[13]:
match1 = re.search('abb*', 'abcdef')
print(match1)
match1 = re.search('abb*', 'aabbcc')
print(match1)
match1 = re.search('abb*', 'cde')
print(match1)
match1 = re.search('hello*', 'Hi, hellooooo!')
print(match1)
match1 = re.search('hello*', 'Hi, good morning!')
print(match1)

<re.Match object; span=(0, 2), match='ab'>
<re.Match object; span=(1, 4), match='abb'>
None
<re.Match object; span=(4, 13), match='hellooooo'>
None

これまでに紹介した連接、和、閉包という3つの演算を組み合わせることで様々な正規表現を記述することができますが、これらの演算には結合の強さが存在します。たとえば、先に見た ab | cd という正規表現は、 ab もしくは cd という文字列にマッチします((ab)|(cd) と同じ意味です)。つまり、連接の方が和よりも強く結合しているのです。そこで、丸括弧を使って a(b|c)d とすると、この正規表現は、abd | acd と同じ意味になります。

[14]:
match1 = re.search('ab|de', 'fgdeab')
print(match1)
match1 = re.search('(ab)|(de)', 'fgdeab')
print(match1)
match1 = re.search('a(b|d)e', 'fgdeab')
print(match1)
match1 = re.search('a(b|d)e', 'fgadeab')
print(match1)
match1 = re.search('abe|ade', 'fgadeab')
print(match1)
match1 = re.search("(I|i)t('s| is| was)", "It was rainy yesterday, but it's fine today.")
print(match1)
match1 = re.search("(I|i)t('s| is| was)", "It rained yesterday, but it's fine today.")
print(match1)
<re.Match object; span=(2, 4), match='de'>
<re.Match object; span=(2, 4), match='de'>
None
<re.Match object; span=(2, 5), match='ade'>
<re.Match object; span=(2, 5), match='ade'>
<re.Match object; span=(0, 6), match='It was'>
<re.Match object; span=(25, 29), match="it's">

演算の結合の強さは、「和 < 連接 < 閉包」という順序になっています。これは数学の、「和(+)< 積(×) < べき」と同じですので、直感的にもわかりやすいと思います。これまでに紹介した連接、和、閉包という3つの演算と結合の順序を明記する丸括弧 () とを組み合わせることで様々な正規表現を記述することができます。

[15]:
match1 = re.search('a(bc|b)*', 'defabcxyz')
print(match1)
match1 = re.search('a(bc|b)*', 'bbacbabbbbc')
print(match1)
match1 = re.search('ca(r|t(egory|tle|))', 'What category is this cat in?')
print(match1)
match1 = re.search('ca(r|t(egory|tle|))', 'No, this is not a carpet.')
print(match1)
match1 = re.search('ca(r|t(egory|tle|))', 'We saw a cattle car almost hit the cat.')
print(match1)
match1 = re.search('ca(r|t(egory|tle|))', 'Please locate him.')
print(match1)
match1 = re.search('ca(r|t(egory|tle|))', "Don't play castanets.")
print(match1)
<re.Match object; span=(3, 6), match='abc'>
<re.Match object; span=(2, 3), match='a'>
<re.Match object; span=(5, 13), match='category'>
<re.Match object; span=(18, 21), match='car'>
<re.Match object; span=(9, 15), match='cattle'>
<re.Match object; span=(9, 12), match='cat'>
None

Pythonでは正規表現は文字列によって表していることに注意してください。たとえば、match 関数の第一引数を文字列の変数で置き換えられるということです。

[16]:
match1 = re.match('abc', 'abcde')
print(match1)
reg1 = 'abc' # 正規表現を文字列で記述する
match2 = re.match(reg1, 'abcde') #match1と同じ結果になる
print(match2)
<re.Match object; span=(0, 3), match='abc'>
<re.Match object; span=(0, 3), match='abc'>

このことを覚えておくと複雑な正規表現を書くときに、少しずつ分解して記述することができて便利です。

[17]:
match1 = re.search("(I|i)t('s| is| was)", "It was rainy yesterday, but it's fine today.")
print(match1)
reg1 = '(I|i)t' # 正規表現の前半部分
reg2 = "('s| is| was)" # 正規表現の後半部分
reg3 = reg1 + reg2 # 正規表現を表す2つの文字列を結合する
print(reg3)
match2 = re.search(reg3, "It was rainy yesterday, but it's fine today.")
print(match2)
<re.Match object; span=(0, 6), match='It was'>
(I|i)t('s| is| was)
<re.Match object; span=(0, 6), match='It was'>

練習

文字列 str1 を引数として取り、 str1 の中に「月を表す文字列」が含まれているかどうか調べて、含まれていればマッチしたときのmatchオブジェクトを、含まれいなければ None を返す関数 check_monthstr を作成してください。 ただし、「月を表す文字列」 は次のような文字列とします。

  1. 長さ2の mm という文字列

  2. mm は、00, 01, …, 12 のいずれかの文字列

以下のセルの ... のところを書き換えて解答してください。

[18]:
import ...
def check_monthstr(str1):
    ...
  Cell In[18], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[19]:
print(check_monthstr('10').group() == '10') # group()については後半に説明があります(オプショナル)
print(check_monthstr('mon1521vb') == None)
print(check_monthstr('00an23') == None)
print(check_monthstr('13302').group() == '02')
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[19], line 1
----> 1 print(check_monthstr('10').group() == '10') # group()については後半に説明があります(オプショナル)
      2 print(check_monthstr('mon1521vb') == None)
      3 print(check_monthstr('00an23') == None)

NameError: name 'check_monthstr' is not defined

練習

文字列 str1 を引数として取り、 str1 を構成する文字列が A, C, G, T の4種類の文字以外の文字を含むかどうか調べて、これら以外を含む場合は False を、そうでない場合は True を返す関数 check_ACGTstr を作成してください。 ただし、大文字と小文字は区別しません。また、空列の場合は False を返してください。

以下のセルの ... のところを書き換えて解答してください。

[20]:
import ...
def check_ACGTstr(str1):
    ...
  Cell In[20], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[21]:
print(check_ACGTstr('AcCGTAGCacATcGgAaaTtGCacT') == True)
print(check_ACGTstr(':ACaacgta24FgtGH') == False)
print(check_ACGTstr('') == False)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[21], line 1
----> 1 print(check_ACGTstr('AcCGTAGCacATcGgAaaTtGCacT') == True)
      2 print(check_ACGTstr(':ACaacgta24FgtGH') == False)
      3 print(check_ACGTstr('') == False)

NameError: name 'check_ACGTstr' is not defined

練習

文字列 str1 を引数として取り、 str1 の中に「時刻を表す文字列」が含まれているかどうか調べて、含まれていればマッチしたときのmatchオブジェクトを、含まれいなければ None を返す関数 check_timestr を作成してください。 ただし、「時刻を表す文字列」 は次のような文字列とします。

  1. 長さ5の hh:mm という文字列であり、12時間表示で時間を表す。

  2. 前半の2文字 hh は、 00, 01, …, 11 のいずれかの文字列

  3. 後半の2文字 mm は、 00, 01, …, 59 のいずれかの文字列

以下のセルの ... のところを書き換えて解答してください。

[22]:
import ...
def check_timestr(str1):
    ...
  Cell In[22], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[23]:
print(check_timestr('10:23').group() == '10:23') # group()については後半に説明があります(オプショナル)
print(check_timestr('time?1023') == None)
print(check_timestr('time?11:23').group() == '11:23')
print(check_timestr('12:3xx1;23ah23:23') == None)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[23], line 1
----> 1 print(check_timestr('10:23').group() == '10:23') # group()については後半に説明があります(オプショナル)
      2 print(check_timestr('time?1023') == None)
      3 print(check_timestr('time?11:23').group() == '11:23')

NameError: name 'check_timestr' is not defined

練習

文字列 str1 を引数として取り、str1 の中に「IPv4を表す文字列」が含まれているかどうか調べて、含まれていればマッチしたときのmatchオブジェクトを、含まれいなければ None を返す関数 check_ipv4str を作成してください。 ただし、「IPv4を表す文字列」 は次のような文字列とします。

  1. aaa:bbb:ccc:ddd という形式の長さ15の文字列

  2. aaa, bbb, ccc, ddd はいずれも、 000, 001, …, 254, 255 のいずれかの文字列

以下のセルの ... のところを書き換えて解答してください。

[24]:
import ...
def check_ipv4str(str1):
    ...
  Cell In[24], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[25]:
print(check_ipv4str('IP=255:255:255:255').group() == '255:255:255:255')
print(check_ipv4str('notIP=2x5:a5b:2c:255:14:444') == None)
print(check_ipv4str('IP?=25:25:55:155') == None)
print(check_ipv4str('IP?=255:255:255') == None)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[25], line 1
----> 1 print(check_ipv4str('IP=255:255:255:255').group() == '255:255:255:255')
      2 print(check_ipv4str('notIP=2x5:a5b:2c:255:14:444') == None)
      3 print(check_ipv4str('IP?=25:25:55:155') == None)

NameError: name 'check_ipv4str' is not defined

練習

文字列 str1 を引数として取り、 str1 の中に「月と日を表す文字列」が含まれているかどうか調べて、含まれていればマッチしたときのmatchオブジェクトを、含まれいなければ None を返す関数 check_monthdaystr を作成してください。 ただし、「月と日を表す文字列」 は次のような文字列とします。

  1. mm/dd という長さ5の文字列

  2. mm は、 01, 02, …, 12 のいずれかの文字列

  3. dd は、mm01, 03, 05, 07, 08, 10, 12 ならば、01, 02, …, 31 のいずれかの文字列

  4. dd は、mm04, 06, 09, 11 ならば、01, 02, …, 30 のいずれかの文字列

  5. dd は、mm02 ならば、01, 02, …, 29 のいずれかの文字列

以下のセルの ... のところを書き換えて解答してください。

[26]:
import ...
def check_monthdaystr(str1):
    ...
  Cell In[26], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[27]:
print(check_monthdaystr('year11/31month11/30day15hour/27minute/sec').group() == '11/30')
print(check_monthdaystr('11/31') == None)
print(check_monthdaystr('x02f/2d5ax') == None)
print(check_monthdaystr('03/24').group() == '03/24')
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[27], line 1
----> 1 print(check_monthdaystr('year11/31month11/30day15hour/27minute/sec').group() == '11/30')
      2 print(check_monthdaystr('11/31') == None)
      3 print(check_monthdaystr('x02f/2d5ax') == None)

NameError: name 'check_monthdaystr' is not defined

文字クラス

[abc]a|b|c と同じ意味の正規表現です。この角括弧を用いた表記は、文字クラスと呼ばれます。

[28]:
match1 = re.search('[abc]', 'defabcxyz')
print(match1)
match1 = re.search('[3456]', '1234567890')
print(match1)
match1 = re.search('ha[sd]', 'He has an apple and they have pineapples.')
print(match1)

<re.Match object; span=(3, 4), match='a'>
<re.Match object; span=(2, 3), match='3'>
<re.Match object; span=(3, 6), match='has'>

勿論、これまでの和や閉包と組み合わせて用いることができます。

[29]:
match1 = re.search('[def][abc]', 'defabcxyz')
print(match1)
match1 = re.search('4[3456][3456]([3456]|[7890])', '1234567890')
print(match1)
match1 = re.search('6[789]*', '1234567890')
print(match1)
match1 = re.search('she ha[sd]|they ha(ve|d)', 'He has an apple and they have pineapples.', re.I)
print(match1)
<re.Match object; span=(2, 4), match='fa'>
<re.Match object; span=(3, 7), match='4567'>
<re.Match object; span=(5, 9), match='6789'>
<re.Match object; span=(20, 29), match='they have'>

ただし、文字クラスの中で連接、和、閉包は無効化されます。たとえば、[a*] という正規表現は、a もしくは、* にマッチします。

[30]:
match1 = re.search('[a*]', 'aaaaaa') # a一文字にマッチ
print(match1)
match1 = re.search('[a*]', '*') # *一文字にマッチ
print(match1)
match1 = re.search('a*', 'aaaaaa')
print(match1)
match1 = re.search('a*', '*') # 文字クラスでない場合、*にはマッチしない
print(match1)
match1 = re.search('[a|b]', 'defabcxyz') # a一文字にマッチ
print(match1)
match1 = re.search('[a|b]', '|') #  |一文字にマッチ
print(match1)
match1 = re.search('a|b', '|') # 文字クラスでない場合、|にはマッチしない
print(match1)
<re.Match object; span=(0, 1), match='a'>
<re.Match object; span=(0, 1), match='*'>
<re.Match object; span=(0, 6), match='aaaaaa'>
<re.Match object; span=(0, 0), match=''>
<re.Match object; span=(3, 4), match='a'>
<re.Match object; span=(0, 1), match='|'>
None

文字クラスでは一文字分の連続する和演算を表すことができますが、長さ2以上の文字列を表すことはできません。すなわち、ab | cd という正規表現を(1つの)文字クラスで表すことはできません。

また、 [abcdefg][gcdbeaf] などは [a-g][1234567][4271635] などは [1-7] などとハイフン (-) を用いることで簡潔に表すことができます。たとえば、全てのアルファベットと数字を表す場合は、[a-zA-Z0-9] で表されます。

[31]:
match1 = re.search('[a-c]', 'defabcxyz')
print(match1)
match1 = re.search('3[4-8]', '1234567890')
print(match1)
match1 = re.search(':[a-zA-Z0-9]*:', 'a1b2c3:d4e5f:6g7A8B:9C0D')
print(match1)
<re.Match object; span=(3, 4), match='a'>
<re.Match object; span=(2, 4), match='34'>
<re.Match object; span=(6, 13), match=':d4e5f:'>

文字クラスの内側をキャレット (^) で始めると、否定文字クラスとなり、キャレットの後ろに指定した文字以外の文字とマッチする正規表現となります。たとえば、[^abc]a, b, c 以外の1文字とマッチする正規表現です。

[32]:
match1 = re.search('[^abc]', 'abcdefxyz')
print(match1)
match1 = re.search('[^def]', 'defabcxyz')
print(match1)
match1 = re.search('[^1-7]', '1234567890')
print(match1)
match1 = re.search('ha[^sd]e', 'He has an apple and they have pineapples.')
print(match1)
<re.Match object; span=(3, 4), match='d'>
<re.Match object; span=(3, 4), match='a'>
<re.Match object; span=(7, 8), match='8'>
<re.Match object; span=(25, 29), match='have'>

キャレットを先頭以外につけた場合は、単なる文字クラスになります。すなわち、キャレットにマッチするかどうかが判定されます。たとえば、[d^ef] は、d, ^, e, f のいずれかにマッチします。

[33]:
match1 = re.search('[d^ef]', 'defabcxyz')
print(match1)
match1 = re.search('[d^ef]', 'a^bcdef') # キャレットにマッチする
print(match1)
<re.Match object; span=(0, 1), match='d'>
<re.Match object; span=(1, 2), match='^'>

正規表現に関する基本的な関数

上で紹介した正規表現を利用してマッチする文字列が存在するかどうかを調べるだけではなく、マッチした文字列に対して色々な処理を加えることができます。以下では2つの基本的な関数を紹介します。

sub

sub は、正規表現R にマッチする 文字列A 中の全ての文字列を、指定した 文字列B で置き換えることができます。

具体的には次のようにすると、

re.sub(正規表現R, 置換する文字列B, 元になる文字列A)

R とマッチする A 中の全ての文字列を B と置き換えることができます。置き換えられた結果の文字列(新たに作られて)が返値となります。(もちろん、もとの文字列 A は変化しません。)

[34]:
str1 = re.sub('[346]', 'x', '03-5454-68284') #3,4,6をxに置き換える
print(str1)
str1 = re.sub('[.,:;!?]', '', "He has three pets: a cat, a dog and a giraffe, doesn't he?") #句読点を削除する(空文字列に置き換える)
print(str1)
str1 = re.sub('\(a\)|あっとまーく|@', '@', 'accountnameあっとまーくtest.ecc.u-tokyo.ac.jp') # スパム回避の文字列を@に置き換える
print(str1)# \(と\)の意味については、下記の「正規表現のエスケープシーケンス」の節を参照してください
0x-5x5x-x828x
He has three pets a cat a dog and a giraffe doesn't he
accountname@test.ecc.u-tokyo.ac.jp
<>:5: SyntaxWarning: invalid escape sequence '\('
<>:5: SyntaxWarning: invalid escape sequence '\('
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/2703320260.py:5: SyntaxWarning: invalid escape sequence '\('
  str1 = re.sub('\(a\)|あっとまーく|@', '@', 'accountnameあっとまーくtest.ecc.u-tokyo.ac.jp') # スパム回避の文字列を@に置き換える
re.sub(r'[ \t\n][ \t\n]*', ' ', str1)

とすると、文字列 str1 の空白文字の並びがスペース1個に置き換わります。

ここで、r'[ \t\n][ \t\n]*' という正規表現は、空白かタブか改行の1回以上の繰り返しのパターンを表します。つまり、aa* という形をした「1回以上の a という文字列とマッチする正規表現」は a+ という + を使った正規表現で置き換えることが可能です。この + は後で正式に紹介します。

[35]:
re.sub(r'[ \t\n][ \t\n]*', ' ', 'Hello,\n    World!\tHow are you?')
[35]:
'Hello, World! How are you?'

以下では、HTMLやXMLのタグを消しています(空文字列に置き換えています)。

[36]:
re.sub(r'<[^>]*>', '', '<body>\nClick <a href="a.href">this</a>\n</body>\n')
[36]:
'\nClick this\n\n'

r'<[^>]*>' という正規表現は、< の後に > 以外の文字の繰り返しがあって最後に > が来るというパターンを表します。

re.split

split は、正規表現R にマッチする文字列を区切り文字(デリミタ)として、文字列A を分割します。分割された文字列がリストに格納されて返値となります。

具体的には次のように用います。

re.split(正規表現R, 元になる文字列A)

以下が典型例です。

re.split(r'[^a-zA-Z][^a-zA-Z]*', 'Hello, World! How are you?')

[^a-zA-Z][^a-zA-Z]* という正規表現は、英文字以外の文字が1回以上繰り返されている、というパターンを表します。 この正規表現を Python の式の中で用いるときは、r'[^a-zA-Z][^a-zA-Z]*' という構文を用います。 先頭の r については、以下の説明を参照してください。

[37]:
list1 = re.split(' ', "He has three pets a cat a dog and a giraffe doesn't he")
print(list1)
list2 = re.split(r'[^a-zA-Z][^a-zA-Z]*', 'Hello, World! How are you?')
print(list2)
['He', 'has', 'three', 'pets', 'a', 'cat', 'a', 'dog', 'and', 'a', 'giraffe', "doesn't", 'he']
['Hello', 'World', 'How', 'are', 'you', '']

この例のように、返されたリストに空文字列が含まれる場合がありますので、注意してください。

r を付ける理由

さて、以上のような正規表現は、'hello*' のようにPythonの文字列として re.splitre.sub などの関数に与えればよいのですが、 以下のように文字列の前に r を付けることが推奨されます。

[38]:
r'hello*'
[38]:
'hello*'

r'hello*' の場合は r を付けても付けなくても同じなのですが、 以下のように r を付けるとエスケープすべき文字がエスケープシーケンスになった文字列が得られます。

[39]:
r'[ \t\n]+'
[39]:
'[ \\t\\n]+'

\t\\t に変わったことでしょう。\\ はバックスラッシュを表すエスケープシーケンスです。 \t はタブという文字を表しますが、\\t はバックススラッシュと t という2文字から成る文字列です。 この場合、正規表現を解釈する段階でバックスラッシュが処理されます。

特に \ という文字そのものを正規表現に含めたいときは \\ と書いた上で r を付けてください。

[40]:
r'\\t t/'
[40]:
'\\\\t t/'

この場合、文字列の中に \ が2個含まれており、正規表現を解釈する段階で正しく処理されます。すなわち、\ という文字そのものを表します。

練習

英語の文書が保存された text-sample.txt というファイルから読み込み、出現する単語のリストを返す関数 get_engsentences を作成してください。 ただし、重複する単語を削除してはいけませんが、空文字列は除きます。また、リストは返す前に中身を昇順に並べ替えてください。

以下のセルの ... のところを書き換えて解答してください。

[41]:
import ...
def get_engsentences():
    ...
  Cell In[41], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[42]:
list1 = get_engsentences()
print(len(list1) == 289)
print(list1[0] == 'a')
print(list1[100] == 'in')
print(list1[288] == 'would')
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[42], line 1
----> 1 list1 = get_engsentences()
      2 print(len(list1) == 289)
      3 print(list1[0] == 'a')

NameError: name 'get_engsentences' is not defined

練習

英語の文書が保存された text-sample.txt というファイルから読み込み、出現する単語のリストを返す関数 get_engsentences2 を作成してください。 ただし、空文字列は除きます。また、リストは返す前に中身を昇順に並べ替えてください。

以下のセルの ... のところを書き換えて解答してください。

[43]:
import ...
def get_engsentences2():
    ...
  Cell In[43], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[44]:
list1 = get_engsentences2()
print(len(list1) == 149)
print(list1[0] == 'a')
print(list1[100] == 'proclaim')
print(list1[148] == 'would')
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[44], line 1
----> 1 list1 = get_engsentences2()
      2 print(len(list1) == 149)
      3 print(list1[0] == 'a')

NameError: name 'get_engsentences2' is not defined

その他の反復演算

閉包以外の反復演算を説明します。

a? は、正規表現 a を高々1回反復する文字列とマッチします。たとえば、a(bc)?a|abc と同じ意味の正規表現です。

[45]:
match1 = re.search('colou?r', 'colour')
print(match1)
match1 = re.search('colou?r', 'color')
print(match1)
<re.Match object; span=(0, 6), match='colour'>
<re.Match object; span=(0, 5), match='color'>

a+ は、正規表現 a を1回以上反復する文字列とマッチします。つまり、a+aa* と同じ意味の正規表現です。

[46]:
match1 = re.search('boo+', 'boooo!')
print(match1)
match1 = re.search('boo+', 'bo!')
print(match1)
match1 = re.search('a+', 'abcdef')
print(match1)
match1 = re.search('a+', 'aabbcc')
print(match1)
match1 = re.search('a+', 'cde')
print(match1)
match1 = re.search('[^a-zA-Z]+', 'abc12345efg67hi89j0k')
print(match1)
match1 = re.search('[a-zA-Z]+', 'abc12345efg67hi89j0k')
print(match1)
<re.Match object; span=(0, 5), match='boooo'>
None
<re.Match object; span=(0, 1), match='a'>
<re.Match object; span=(0, 2), match='aa'>
None
<re.Match object; span=(3, 8), match='12345'>
<re.Match object; span=(0, 3), match='abc'>

上記の例を * を使う形に書き換えてみてください。

a{x,y}、は正規表現 ax 回以上かつ y 回以下繰り返す文字列とマッチします。

[47]:
match1 = re.search('bo{3,5}', 'booooooo!')
print(match1)
match1 = re.search('bo{3,5}', 'boo!')
print(match1)
match1 = re.search('a{2,5}', 'bacaad')
print(match1)
match1 = re.search('[0-9]{1,3},[0-9]{3,3}', '1,298円')
print(match1)
match1 = re.search('[0-9]{1,3},[0-9]{3,3}', '298円')
print(match1)
<re.Match object; span=(0, 6), match='booooo'>
None
<re.Match object; span=(3, 5), match='aa'>
<re.Match object; span=(0, 5), match='1,298'>
None

メタ文字

以下では、良く使うメタ文字(特殊文字)を紹介します。

.(ピリオド)は、あらゆる文字にマッチします。

[48]:
match1 = re.search('.', 'Hello')
print(match1)
match1 = re.search('3.*9', '1234567890')
print(match1)
match1 = re.search('ha(.|..)', 'He has an apple and they have pineapples.')
print(match1)
<re.Match object; span=(0, 1), match='H'>
<re.Match object; span=(2, 9), match='3456789'>
<re.Match object; span=(3, 6), match='has'>

ただし、文字クラスの中で . を用いても、あらゆる文字とはマッチせず、* の場合と同様に、ピリオドとマッチします。

[49]:
match1 = re.search('[.]', 'Hello')
print(match1)
match1 = re.search('[.]', '3.141592')
print(match1)
None
<re.Match object; span=(1, 2), match='.'>

\t は タブを表します。

[50]:
match1 = re.search('b\t', 'a        b       c       d')
print(match1)
<re.Match object; span=(2, 4), match='b\t'>

\s空白文字(スペース、タブ、改行など)を表します。

[51]:
match1 = re.search('b\s', 'a        b       c       d')
print(match1)
match1 = re.search('a\s\s\s', 'a      b      c      d')
print(match1)
match1 = re.search('b\s*', 'a         b      c      d')
print(match1)
<re.Match object; span=(2, 4), match='b\t'>
<re.Match object; span=(0, 4), match='a\t\u3000 '>
<re.Match object; span=(4, 7), match='b\t\u3000'>
<>:1: SyntaxWarning: invalid escape sequence '\s'
<>:3: SyntaxWarning: invalid escape sequence '\s'
<>:5: SyntaxWarning: invalid escape sequence '\s'
<>:1: SyntaxWarning: invalid escape sequence '\s'
<>:3: SyntaxWarning: invalid escape sequence '\s'
<>:5: SyntaxWarning: invalid escape sequence '\s'
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/1235538076.py:1: SyntaxWarning: invalid escape sequence '\s'
  match1 = re.search('b\s', 'a      b       c       d')
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/1235538076.py:3: SyntaxWarning: invalid escape sequence '\s'
  match1 = re.search('a\s\s\s', 'a    b      c      d')
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/1235538076.py:5: SyntaxWarning: invalid escape sequence '\s'
  match1 = re.search('b\s*', 'a       b      c      d')

\S\s 以外の全ての文字を表します。

[52]:
match1 = re.search('b\S', 'a        b       bc      d')
print(match1)

<re.Match object; span=(4, 6), match='bc'>
<>:1: SyntaxWarning: invalid escape sequence '\S'
<>:1: SyntaxWarning: invalid escape sequence '\S'
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/3290421489.py:1: SyntaxWarning: invalid escape sequence '\S'
  match1 = re.search('b\S', 'a      b       bc      d')

\w[a-zA-Z0-9_] と同じ意味です。

[53]:
match1 = re.search('\w\w', 'abcde')
print(match1)
match1 = re.search('b\w*g', 'abcdefgh')

<re.Match object; span=(0, 2), match='ab'>
<>:1: SyntaxWarning: invalid escape sequence '\w'
<>:3: SyntaxWarning: invalid escape sequence '\w'
<>:1: SyntaxWarning: invalid escape sequence '\w'
<>:3: SyntaxWarning: invalid escape sequence '\w'
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/3891737031.py:1: SyntaxWarning: invalid escape sequence '\w'
  match1 = re.search('\w\w', 'abcde')
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/3891737031.py:3: SyntaxWarning: invalid escape sequence '\w'
  match1 = re.search('b\w*g', 'abcdefgh')

\W\w 以外の全ての文字を表します。すなわち、[^a-zA-Z0-9_] と同じ意味です。

[54]:
match1 = re.search('g\W*', 'ab defg  hi jklm no p')
print(match1)
match1 = re.search('\W\w*\W', 'ab defg  hi jklm no p')
print(match1)
<re.Match object; span=(6, 9), match='g  '>
<re.Match object; span=(2, 8), match=' defg '>
<>:1: SyntaxWarning: invalid escape sequence '\W'
<>:3: SyntaxWarning: invalid escape sequence '\W'
<>:1: SyntaxWarning: invalid escape sequence '\W'
<>:3: SyntaxWarning: invalid escape sequence '\W'
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/3446286968.py:1: SyntaxWarning: invalid escape sequence '\W'
  match1 = re.search('g\W*', 'ab defg  hi jklm no p')
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/3446286968.py:3: SyntaxWarning: invalid escape sequence '\W'
  match1 = re.search('\W\w*\W', 'ab defg  hi jklm no p')

\d[0-9] と同じ意味です。

[55]:
match1 = re.search('\d\d\d-\d\d\d\d', '153-8902')
print(match1)
match1 = re.search('\d*-\d*', '153-8902')
print(match1)
match1 = re.search('\d\d-\d\d\d\d-\d\d\d\d', '03-5454-6828')
print(match1)
match1 = re.search('\d*-\d*-\d*', '03-5454-6828')
print(match1)
<re.Match object; span=(0, 8), match='153-8902'>
<re.Match object; span=(0, 8), match='153-8902'>
<re.Match object; span=(0, 12), match='03-5454-6828'>
<re.Match object; span=(0, 12), match='03-5454-6828'>
<>:1: SyntaxWarning: invalid escape sequence '\d'
<>:3: SyntaxWarning: invalid escape sequence '\d'
<>:5: SyntaxWarning: invalid escape sequence '\d'
<>:7: SyntaxWarning: invalid escape sequence '\d'
<>:1: SyntaxWarning: invalid escape sequence '\d'
<>:3: SyntaxWarning: invalid escape sequence '\d'
<>:5: SyntaxWarning: invalid escape sequence '\d'
<>:7: SyntaxWarning: invalid escape sequence '\d'
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/3067726332.py:1: SyntaxWarning: invalid escape sequence '\d'
  match1 = re.search('\d\d\d-\d\d\d\d', '153-8902')
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/3067726332.py:3: SyntaxWarning: invalid escape sequence '\d'
  match1 = re.search('\d*-\d*', '153-8902')
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/3067726332.py:5: SyntaxWarning: invalid escape sequence '\d'
  match1 = re.search('\d\d-\d\d\d\d-\d\d\d\d', '03-5454-6828')
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/3067726332.py:7: SyntaxWarning: invalid escape sequence '\d'
  match1 = re.search('\d*-\d*-\d*', '03-5454-6828')

\D\d 以外の全ての文字を表します。すなわち、[^0-9] と同じ意味です。

[56]:
match1 = re.search('\D*', 'He has 10 apples.')
print(match1)

<re.Match object; span=(0, 7), match='He has '>
<>:1: SyntaxWarning: invalid escape sequence '\D'
<>:1: SyntaxWarning: invalid escape sequence '\D'
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/174792290.py:1: SyntaxWarning: invalid escape sequence '\D'
  match1 = re.search('\D*', 'He has 10 apples.')

練習

文字列から数字列を切り出して、それを整数とみなして足し合せた結果を整数として返す関数 sumnumbers を定義してください。

[57]:
import ...
def sumnumbers(s):
    ...
  Cell In[57], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[58]:
print(sumnumbers(' 2  33 45, 67.9') == 156)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[58], line 1
----> 1 print(sumnumbers(' 2  33 45, 67.9') == 156)

NameError: name 'sumnumbers' is not defined

練習

文字列 str1 を引数として取り、str1 を構成する文字列が A, C, G, T の4種類の文字以外の文字を含むかどうか調べて、これら以外を含む場合は False、そうでない場合は True を返す関数 check_ACGTstr を作成してください。 ただし、大文字と小文字は区別しません。また、空列の場合は False を返してください。

以下のセルの ... のところを書き換えて解答してください。

[59]:
import ...
def check_ACGTstr(str1):
    ...
  Cell In[59], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[60]:
print(check_ACGTstr('AcCGTAGCacATcGgAaaTtGCacT') == True)
print(check_ACGTstr(':ACaacgta24FgtGH') == False)
print(check_ACGTstr('') == False)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[60], line 1
----> 1 print(check_ACGTstr('AcCGTAGCacATcGgAaaTtGCacT') == True)
      2 print(check_ACGTstr(':ACaacgta24FgtGH') == False)
      3 print(check_ACGTstr('') == False)

NameError: name 'check_ACGTstr' is not defined

練習

文字列 str1 を引数として取り、 str1 を構成する文字列が「日本の郵便番号」を表す文字列になっている場合は、 True を返し、そうでない場合は False を返す関数 check_postalcode を作成してください。 ただし、「日本の郵便番号」は abc-defg という形になっており、a, b, c, d, e, d, f, g はそれぞれ 0 から 9 までの値になっています。

以下のセルの ... のところを書き換えて解答してください。

[61]:
import ...
def check_postalcode(str1):
    ...
  Cell In[61], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[62]:
print(check_postalcode('113-8654') == True)
print(check_postalcode('119-110') == False)
print(check_postalcode('abc-defg') == False)
print(check_postalcode('〒153-0041') == False)
print(check_postalcode('113-86547') == False)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[62], line 1
----> 1 print(check_postalcode('113-8654') == True)
      2 print(check_postalcode('119-110') == False)
      3 print(check_postalcode('abc-defg') == False)

NameError: name 'check_postalcode' is not defined

練習

文字列 str1 を引数として取り、str1 を構成する文字列が「本郷の内線番号」を表す文字列になっている場合は、 True を返し、そうでない場合は False を返す関数 check_extension を作成してください。 ただし、「本郷の内線番号」は 2abcd という形になっており、a, b, c, d はそれぞれ 0 から 9 までの値になっています。

以下のセルの ... のところを書き換えて解答してください。

[63]:
import ...
def check_extension(str1):
    ...
  Cell In[63], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[64]:
print(check_extension('24115') == True)
print(check_extension('46858') == False)
print(check_extension('☎46666') == False)
print(check_extension('467890') == False)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[64], line 1
----> 1 print(check_extension('24115') == True)
      2 print(check_extension('46858') == False)
      3 print(check_extension('☎46666') == False)

NameError: name 'check_extension' is not defined

正規表現のエスケープシーケンス

丸括弧 () や演算子 (|, *) など正規表現の中で特殊な役割を果たす記号のマッチを行いたい場合、文字列のエスケープシーケンスのように \ を前につけてやる必要があります。

[65]:
match1 = re.search('03(5454)6666', '03(5454)6666') #電話番号。つけないと丸括弧として扱われないのでマッチしない
print(match1)
match1 = re.search('03(5454)6666', '0354546666') # 括弧が含まれない文字列にマッチ
print(match1)
match1 = re.search('03\(5454\)6666', '03(5454)6666') # \(と\)で左右の丸括弧として扱われるのでマッチする
print(match1)
match1 = re.search('3*4+5=17', '3*4+5=17') #計算式。*と+が演算子扱いされているのでマッチしない
print(match1)
match1 = re.search('3*4+5=17', '33345=17') #\がないと、たとえば、このような文字列とマッチする
print(match1)
match1 = re.search('3\*4\+5=17', '3*4+5=17') #意図した文字列にマッチ
print(match1)
match1 = re.search('|ω・`)チラ ', '|ω・`)チラ ') #顔文字。 空列にマッチしてしまう
print(match1)
match1 = re.search('\|ω・`)チラ ', '|ω・`)チラ ') #意図した文字列にマッチ
print(match1)
None
<re.Match object; span=(0, 10), match='0354546666'>
<re.Match object; span=(0, 12), match='03(5454)6666'>
None
<re.Match object; span=(0, 8), match='33345=17'>
<re.Match object; span=(0, 8), match='3*4+5=17'>
<re.Match object; span=(0, 0), match=''>
<re.Match object; span=(0, 8), match='|ω・`)チラ '>
<>:5: SyntaxWarning: invalid escape sequence '\('
<>:11: SyntaxWarning: invalid escape sequence '\*'
<>:15: SyntaxWarning: invalid escape sequence '\|'
<>:5: SyntaxWarning: invalid escape sequence '\('
<>:11: SyntaxWarning: invalid escape sequence '\*'
<>:15: SyntaxWarning: invalid escape sequence '\|'
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/4112574947.py:5: SyntaxWarning: invalid escape sequence '\('
  match1 = re.search('03\(5454\)6666', '03(5454)6666') # \(と\)で左右の丸括弧として扱われるのでマッチする
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/4112574947.py:11: SyntaxWarning: invalid escape sequence '\*'
  match1 = re.search('3\*4\+5=17', '3*4+5=17') #意図した文字列にマッチ
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/4112574947.py:15: SyntaxWarning: invalid escape sequence '\|'
  match1 = re.search('\|ω・`)チラ ', '|ω・`)チラ ') #意図した文字列にマッチ

特殊な意味を持つ記号は次の14個です。

. ^ $ * + ? { } [ ] \ | ( )

これらの特殊記号が含まれる場合(かつ意図したマッチの結果が得られない場合)には、エスケープシーケンスを使う(エスケープする)べき(可能性がある)ことも考慮に入れておいてください。

正規表現に関する関数とメソッド

以下では更に幾つかの関数とメソッドを紹介します。

findall

findall は、正規表現R にマッチする 文字列A 中の全ての文字列を、リストに格納して返します。

具体的には次のように実行します。

re.findall(正規表現R, 文字列A)
[66]:
list1 = re.findall('had', 'James while John had had had had had had had had had had had a better effect on the teacher.')
#James, while John had had 'had', had had 'had had'; 'had had' had had a better effect on the teacher.
print(list1) #全てのhadを抜き出す
list1 = re.findall('p[^ .]*', 'Peter Piper picked a peck of pickled peppers.', re.I)
print(list1)# pで始まる全ての単語を取得する, 大文字小文字を区別しない
['had', 'had', 'had', 'had', 'had', 'had', 'had', 'had', 'had', 'had', 'had']
['Peter', 'Piper', 'picked', 'peck', 'pickled', 'peppers']

finditer

finditer は、正規表現R にマッチする 文字列A 中の全ての matchオブジェクトを、特殊なリスト(のようなもの)に格納して返します。

具体的には次のように実行します。

re.finditer(正規表現R, 文字列A)

返値は特殊なリスト(のようなもの)であり、for文の in の後ろに置いて使ってください。

[67]:
print('1:正規表現 had の結果:')
iter1 = re.finditer('had', 'James while John had had had had had had had had had had had a better effect on the teacher.')
#James, while John had had 'had', had had 'had had'; 'had had' had had a better effect on the teacher.
for match in iter1:
    print(match) #全てのhadを抜き出す
print('2:正規表現 p[^ .]* の結果:')
iter1 = re.finditer('p[^ .]*', 'Peter Piper picked a peck of pickled peppers.', re.I)
for match in iter1:
    print(match)# pで始まる全ての単語を取得する, 大文字小文字を区別しない
1:正規表現 had の結果:
<re.Match object; span=(17, 20), match='had'>
<re.Match object; span=(21, 24), match='had'>
<re.Match object; span=(25, 28), match='had'>
<re.Match object; span=(29, 32), match='had'>
<re.Match object; span=(33, 36), match='had'>
<re.Match object; span=(37, 40), match='had'>
<re.Match object; span=(41, 44), match='had'>
<re.Match object; span=(45, 48), match='had'>
<re.Match object; span=(49, 52), match='had'>
<re.Match object; span=(53, 56), match='had'>
<re.Match object; span=(57, 60), match='had'>
2:正規表現 p[^ .]* の結果:
<re.Match object; span=(0, 5), match='Peter'>
<re.Match object; span=(6, 11), match='Piper'>
<re.Match object; span=(12, 18), match='picked'>
<re.Match object; span=(21, 25), match='peck'>
<re.Match object; span=(29, 36), match='pickled'>
<re.Match object; span=(37, 44), match='peppers'>

group

matchオブジェクトのメソッド group は、正規表現にマッチした文字列を(部分的に)取り出します。正規表現内に丸括弧を用いると、括弧内の正規表現とマッチした文字列を取得できるようになっています。なお、group によるこの操作を、括弧内の文字列をキャプチャするといいます。

i 番目のキャプチャした値を取得するには次のようにします。i = 0 の場合は、マッチした文字列全体を取得できます。

matchオブジェクト.group(i)
[68]:
import re
match1 = re.search('03-5454-(\d\d\d\d)', '03-5454-6666')
print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1)) # 内線番号の取得
match1 = re.search('([^@]*)@[^.]*(\.[^.]*)?\.u-tokyo\.ac\.jp', 'accountname@test.ecc.u-tokyo.ac.jp') # \.はピリオドを表します
print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1)) # アカウント名の取得
match1 = re.search('([^@]*)@[^.]*(\.[^.]*)?\.u-tokyo\.ac\.jp', 'accountname@test.u-tokyo.ac.jp') # \.はピリオドを表します
print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1)) # アカウント名の取得
match1 = re.search("href=\"([^\"]*)\"", '<a href="http://www.u-tokyo.ac.jp" target="_blank">U-Tokyo</a>')# \"はダブルクォートを表します
print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1)) # リンク先URLの取得

マッチした文字列= 03-5454-6666  キャプチャした文字列= 6666
マッチした文字列= accountname@test.ecc.u-tokyo.ac.jp  キャプチャした文字列= accountname
マッチした文字列= accountname@test.u-tokyo.ac.jp  キャプチャした文字列= accountname
マッチした文字列= href="http://www.u-tokyo.ac.jp"  キャプチャした文字列= http://www.u-tokyo.ac.jp
<>:2: SyntaxWarning: invalid escape sequence '\d'
<>:4: SyntaxWarning: invalid escape sequence '\.'
<>:6: SyntaxWarning: invalid escape sequence '\.'
<>:2: SyntaxWarning: invalid escape sequence '\d'
<>:4: SyntaxWarning: invalid escape sequence '\.'
<>:6: SyntaxWarning: invalid escape sequence '\.'
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/2781033459.py:2: SyntaxWarning: invalid escape sequence '\d'
  match1 = re.search('03-5454-(\d\d\d\d)', '03-5454-6666')
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/2781033459.py:4: SyntaxWarning: invalid escape sequence '\.'
  match1 = re.search('([^@]*)@[^.]*(\.[^.]*)?\.u-tokyo\.ac\.jp', 'accountname@test.ecc.u-tokyo.ac.jp') # \.はピリオドを表します
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/2781033459.py:6: SyntaxWarning: invalid escape sequence '\.'
  match1 = re.search('([^@]*)@[^.]*(\.[^.]*)?\.u-tokyo\.ac\.jp', 'accountname@test.u-tokyo.ac.jp') # \.はピリオドを表します

マッチに失敗した場合は、matchオブジェクトが返らずに None が返るので、それを確かめずに group を使おうとするとエラーが出ますので注意してください。

[69]:
match1 = re.search('03-5454-(\d\d\d\d)', '03-5454-666') #マッチしない文字列
print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1))
<>:1: SyntaxWarning: invalid escape sequence '\d'
<>:1: SyntaxWarning: invalid escape sequence '\d'
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/778018344.py:1: SyntaxWarning: invalid escape sequence '\d'
  match1 = re.search('03-5454-(\d\d\d\d)', '03-5454-666') #マッチしない文字列
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/778018344.py:1: SyntaxWarning: invalid escape sequence '\d'
  match1 = re.search('03-5454-(\d\d\d\d)', '03-5454-666') #マッチしない文字列
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[69], line 2
      1 match1 = re.search('03-5454-(\d\d\d\d)', '03-5454-666') #マッチしない文字列
----> 2 print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1))

AttributeError: 'NoneType' object has no attribute 'group'

たとえば、if文でエラーを回避します。

[70]:
match1 = re.search('03-5454-(\d\d\d\d)', '03-5454-666')
if match1 != None:
    print('マッチした文字列=', match1.group(0), ' キャプチャした文字列=', match1.group(1))
else:
    print('マッチしていません')
マッチしていません
<>:1: SyntaxWarning: invalid escape sequence '\d'
<>:1: SyntaxWarning: invalid escape sequence '\d'
/var/folders/4n/53v5yxcx5t7d2sld1grw124w0000gn/T/ipykernel_97089/971918040.py:1: SyntaxWarning: invalid escape sequence '\d'
  match1 = re.search('03-5454-(\d\d\d\d)', '03-5454-666')

練習

文字列 str1 を引数として取り、str1 を構成する文字列が A, C, G, T の4種類の文字以外の文字を含むかどうか調べて、これら以外を含む場合は False を、そうでない場合は True を返す関数 check_ACGTstr を作成してください。 ただし、大文字と小文字は区別しません。また、空列の場合は False を返してください。

以下のセルの ... のところを書き換えて解答してください。

[71]:
import ...
def check_ACGTstr(str1):
    ...
  Cell In[71], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が全て True になることを確認してください。

[72]:
print(check_ACGTstr('AcCGTAGCacATcGgAaaTtGCacT') == True)
print(check_ACGTstr(':ACaacgta24FgtGH') == False)
print(check_ACGTstr('') == False)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[72], line 1
----> 1 print(check_ACGTstr('AcCGTAGCacATcGgAaaTtGCacT') == True)
      2 print(check_ACGTstr(':ACaacgta24FgtGH') == False)
      3 print(check_ACGTstr('') == False)

NameError: name 'check_ACGTstr' is not defined

練習

xmlファイル B1S.xml は http://www.natcorp.ox.ac.uk から入手できるイギリス英語のコーパスのファイルです。

B1S.xmlに含まれるwタグで囲まれる英単語をキー key に、その wタグの属性posの値を key の値とする辞書を返す関数 get_pos を作成してください。ただし、一般にwタグは、次のような形式で記述されます。

<w pos="PRON" ( > 記号以外の何らかの文字列)>(英単語) </w>

たとえば、以下のような具合です。

<w pos="VERB" hw="have" c5="VHI">have </w>

以下のセルの ... のところを書き換えて解答してください。

[73]:
import ...
def get_pos():
    ...
  Cell In[73], line 1
    import ...
           ^
SyntaxError: invalid syntax

上のセルで解答を作成した後、以下のセルを実行し、実行結果が True になることを確認してください。

[74]:
print(get_pos()['They '] == 'PRON')
print(get_pos()['know '] == 'VERB')
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[74], line 1
----> 1 print(get_pos()['They '] == 'PRON')
      2 print(get_pos()['know '] == 'VERB')

NameError: name 'get_pos' is not defined

練習の解答

[75]:
import re
def check_monthstr(str1):
    reg_month = '((0(1|2|3|4|5|6|7|8|9))|10|11|12)' #
    #reg_month = '01|02|03|04|05|06|07|08|09|10|11|12' # としてもよい
    match1 = re.search(reg_month, str1) # 文字列を「含む」なので、(matchではなく)searchを使う
    return match1
[76]:
import re
def check_timestr(str1):
    reg_hour = '((0(0|1|2|3|4|5|6|7|8|9))|10|11)' #「時」部分の正規表現
    #reg_hour = '((0[0-9]|10|11)' # 文字クラスを使ってと表すこともできます(文字クラスは後で学習します
    reg_min = '((0|2|3|4|5)(0|1|2|3|4|5|6|7|8|9))' #「分」部分の正規表現
    #reg_min = '([0-5][0-9])' # 文字クラスを使ってと表すこともできます(文字クラスは後で学習します
    reg_time = reg_hour + ':' + reg_min # 時部分と分部分を、「:」を挟んで結合した新しい正規表現
    #print(reg_time)
    match1 = re.search(reg_time, str1) # 文字列を「含む」なので、(matchではなく)searchを使う
    return match1
[77]:
import re
def check_ipv4str(str1):
    reg_0to9 = '(0|1|2|3|4|5|6|7|8|9)' # 0から9の数を表す正規表現
    #reg_0to9 = '[0-9]' # 文字クラスを使ってと表すこともできます(文字クラスは後で学習します
    reg_0_1 = '(0|1)' + reg_0to9 + reg_0to9 # 先頭の文字が0もしくは1だったときの正規表現(000から199まで)
    reg_20_24 = '2(0|1|2|3|4)' + reg_0to9 # 先頭が20,21,22,23,24だったときの正規表現(200から249まで)
    #reg_20_24 = '2[0-4]' + reg_0to9 # 文字クラスを使ってと表すこともできます
    reg_25 = '25(0|1|2|3|4|5)' # 先頭が25だったときの正規表現(250から255まで)
    #reg_25 = '25[0-5]' # 文字クラスを使ってと表すこともできます
    reg_000_255 = '(' + reg_0_1 + '|' + reg_20_24 + '|' + reg_25 + ')'# aaa(000から255)を表す正規表現
    #print(reg_000_255)
    reg_ip = reg_000_255 + ':' + reg_000_255 + ':' + reg_000_255 + ':' + reg_000_255 # aaa:bbb:ccc:dddを表す正規表現
    #print(reg_ip)
    match1 = re.search(reg_ip, str1) # 文字列を「含む」なので、(matchではなく)searchを使う
    return match1
[78]:
import re
def check_monthdaystr(str1):
    reg_month_31 = '(01|03|05|07|08|10|12)' #ddが01から31になるmm
    reg_month_30 = '(04|06|09|11)' #ddが01から30になるmm
    reg_1to9 = '(1|2|3|4|5|6|7|8|9)' # [1-9]でもよい
    reg_0to9 = '(0|1|2|3|4|5|6|7|8|9)' # [0-9]でもよい
    reg_day_01to09 = '(0' + reg_1to9 + ')' # ddが01から09になる場合
    reg_day_10to19 = '(1' + reg_0to9 + ')' # ddが10から19になる場合
    reg_day_20to29 = '(2' + reg_0to9 + ')' # ddが21から29になる場合
    reg_day_01to29 = reg_day_01to09 + '|' + reg_day_10to19 + '|' + reg_day_20to29 # ddが01から29になる場合
    reg_day_01to30 = reg_day_01to29 + '|' + '30' # ddが01から30になる場合
    reg_day_01to31 = reg_day_01to30 + '|' + '31' # ddが01から31になる場合
    reg_monthday_31 = reg_month_31 + '/(' + reg_day_01to31 + ')' # mmとddを組み合わせる(01-31の場合)
    reg_monthday_30 = reg_month_30 + '/(' + reg_day_01to30 + ')' # mmとddを組み合わせる(01-30の場合)
    reg_monthday_29 = '02/(' + reg_day_01to29 + ')' # mmとddを組み合わせる(01-29の場合はmmは02のみ)
    # 文字列を「含む」なので、(matchではなく)searchを使う
    match1 = re.search(reg_monthday_31, str1) # 問題文の条件3を満たす文字列とマッチするかどうか
    if match1 != None:
        return match1
    match1 = re.search(reg_monthday_30, str1) # 問題文の条件4を満たす文字列とマッチするかどうか
    if match1 != None:
        return match1
    match1 = re.search(reg_monthday_29, str1) # 問題文の条件5を満たす文字列とマッチするかどうか
    return match1
[79]:
import re
def sumnumbers(s):
    numbers = re.split('[^0-9]+', s)
    numbers.remove('')
    n = 0
    for number in numbers:
        n += int(number)
    return n
[80]:
import re
def get_engsentences():
    word_list = [] # 結果を格納するリスト
    with open('text-sample.txt', 'r') as f:
        file_str = f.read() #ファイルの中身を文字列に格納
    str_list = re.split(r'[^a-zA-Z][^a-zA-Z]*', file_str) # 文字列を単語に区切る
    for word in str_list: #`re.split(r'[^a-zA-Z][^a-zA-Z]*', f.read())` は、ファイル全体の文字列を単語に区切ります。
    #for word in re.split(r'[^a-zA-Z][^a-zA-Z]*', f.read()): # と一行にまとめてもよい
        if word != '': #空文字列を除く
            word = word.lower() #単語(文字列)の中の大文字を小文字に変換します
            word_list.append(word) #リストに追加
            #word_list.append(word.lower())でも大丈夫
    word_list.sort() # sortメソッドは破壊的
    return word_list
[81]:
import re
def get_engsentences2():
    word_dict = {} # 重複する単語を削除する為に辞書を使ってみる
    with open('text-sample.txt', 'r') as f:
        file_str = f.read() #ファイルの中身を文字列に格納
    str_list = re.split(r'[^a-zA-Z][^a-zA-Z]*', file_str) # 文字列を単語に区切る
    for word in str_list: #`re.split(r'[^a-zA-Z][^a-zA-Z]*', f.read())` は、ファイル全体の文字列を単語に区切ります。
        if word != '': #空文字列を除く
            word = word.lower() #単語(文字列)の中の大文字を小文字に変換します
            word_dict[word] = 'anthing good' #wordという単語があったことを辞書に記録する(wordに対応する値は何でもよい)
            #word_dict[word.lower()] = 'anthing good'でも大丈夫
    word_list = [] # 結果を格納するリスト
    for word in word_dict:
        word_list.append(word)
    word_list.sort()
    return word_list
[82]:
import re
def check_ACGTstr(str1):
    reg_ACGT = '(A|C|G|T)+' # A,C,G,Tを表す正規表現  # +→* だと空文字列がマッチしてしまう
    #reg_ACGT = '(A|C|G|T)(A|C|G|T)*' # A,C,G,Tを表す正規表現
    #reg_ACGT = '[ACGT]+' # A,C,G,Tを表す正規表現
    match1 = re.search(reg_ACGT, str1, re.I) # re.I を入れて、大文字と小文字を区別しない
    if match1 != None and str1 == match1.group(): # str1全体とマッチした文字列が等しいかチェック
        return True
    return False
#別解
#def check_ACGTstr(str1):
#    reg_ACGT = '(A|C|G|T)+$' # A,C,G,Tを表す正規表現  # +→* だと空文字列がマッチしてしまう
#    #reg_ACGT = '(A|C|G|T)(A|C|G|T)*$' # A,C,G,Tを表す正規表現
#    #reg_ACGT = '[ACGT]+$' # A,C,G,Tを表す正規表現
#    match1 = re.search(reg_ACGT, str1, re.I) # re.I を入れて、大文字と小文字を区別しない
#    if match1 != None: # str1全体とマッチした文字列が等しいかチェック
#        return True
#    return False
[83]:
import re
def check_postalcode(str1):
    reg1 = '[0-9]{3,3}-[0-9]{4,4}'
    #reg1 = '\d{3,3}-\d{4,4}' #でも可
    #reg1 = '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]' #でも可
    match1 = re.match(reg1, str1)
    if match1 == None:
        return False
    if match1.group() == str1:
        return True
    return False
#別解
#def check_postalcode(str1):
#    reg1 = '[0-9]{3,3}-[0-9]{4,4}$' #ドル記号を使って行末からマッチを調べる
#    #reg1 = '\d{3,3}-\d{4,4}$' #でも可
#    #reg1 = '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$' #でも可
#    match1 = re.match(reg1, str1)
#    if match1 == None:
#        return False
#    return True
[84]:
import re
def check_extension(str1):
    reg1 = '2[0-9]{4,4}'
#    reg1 = '2\d{4,4}' #でも可
#    reg1 = '2[0-9][0-9][0-9][0-9]' #でも可
    match1 = re.match(reg1, str1)
    if match1 == None:
        return False
    if match1.group() == str1:
        return True
    return False
#別解
#def check_extension(str1):
#    reg1 = '2[0-9]{4,4}$'
#    #reg1 = '2\d{4,4}$' #でも可
#    #reg1 = '2[0-9][0-9][0-9][0-9]$' #でも可
#    match1 = re.match(reg1, str1)
#    if match1 == None:
#        return False
#    return True
[85]:
import re
def get_pos():
    str_file = 'B1S.xml'
    with open(str_file, 'r', encoding='utf-8') as f:
        str_script = f.read() # ファイルの中身を1つの文字列に格納する
    #print(str_script)
    itr1 = re.finditer("<w[^>]*pos=\"([^>\"]*)\"[^>]*>([^<]*)</w>", str_script) # 正規表現を使ってwタグ周辺の文字列をマッチ
    dic1 = {} # 辞書初期化
    for m1 in itr1:
        #print(m1)
        #print(m1.group(1), m1.group(2))
        dic1[m1.group(2)] = m1.group(1) # groupを使ってマッチした文字列をキャプチャする
    return dic1
================================================ FILE: docs/genindex.html ================================================ Index — Pythonプログラミング入門 documentation ================================================ FILE: docs/index.html ================================================ Pythonプログラミング入門 — Pythonプログラミング入門 documentation

Pythonプログラミング入門

▲で始まる項目は授業では扱いません。興味にしたがって学習してください。

ノートブック全体に▲が付いているものもありますので注意してください。

================================================ FILE: docs/index_of_terms.html ================================================ 索引 — Pythonプログラミング入門 documentation

索引

================================================ FILE: docs/search.html ================================================ Search — Pythonプログラミング入門 documentation ================================================ FILE: docs/searchindex.js ================================================ Search.setIndex({"alltitles": {"1-0. Colaboratory (Colab) \u306e\u4f7f\u3044\u65b9": [[0, null]], "1-1. \u6570\u5024\u6f14\u7b97": [[1, null]], "1-2. \u5909\u6570\u3068\u95a2\u6570\u306e\u57fa\u790e": [[2, null]], "1-3. \u8ad6\u7406\u30fb\u6bd4\u8f03\u6f14\u7b97\u3068\u6761\u4ef6\u5206\u5c90\u306e\u57fa\u790e": [[3, null]], "1-4. \u30c6\u30b9\u30c8\u3068\u30c7\u30d0\u30c3\u30b0": [[4, null]], "2-1. \u6587\u5b57\u5217 (string)": [[5, null]], "2-2. \u30ea\u30b9\u30c8 (list)": [[6, null]], "2-3. \u6761\u4ef6\u5206\u5c90": [[7, null]], "3-1. \u8f9e\u66f8 (dictionary)": [[8, null]], "3-2. \u7e70\u308a\u8fd4\u3057": [[9, null]], "3-3. \u95a2\u6570": [[10, null]], "4-1. \u30d5\u30a1\u30a4\u30eb\u5165\u51fa\u529b\u306e\u57fa\u672c": [[11, null]], "4-2. \u30a4\u30c6\u30e9\u30d6\u30eb\u3068\u30a4\u30c6\u30ec\u30fc\u30bf": [[12, null]], "4-3. \u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3068\u6728\u69cb\u9020": [[13, null]], "5-1. \u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u4f7f\u3044\u65b9": [[14, null]], "5-2. \u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u4f5c\u308a\u65b9": [[15, null]], "5-3. NumPy\u30e9\u30a4\u30d6\u30e9\u30ea": [[16, null]], "6-1. \u5185\u5305\u8868\u8a18": [[17, null]], "6-2. \u9ad8\u968e\u95a2\u6570": [[18, null]], "6-3. \u30af\u30e9\u30b9": [[19, null]], "7-1. pandas\u30e9\u30a4\u30d6\u30e9\u30ea": [[20, null]], "7-2. scikit-learn\u30e9\u30a4\u30d6\u30e9\u30ea": [[21, null]], "CSV\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u306e\u30c7\u30fc\u30bf\u30d5\u30ec\u30fc\u30e0\u306e\u4f5c\u6210": [[20, "CSV\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u306e\u30c7\u30fc\u30bf\u30d5\u30ec\u30fc\u30e0\u306e\u4f5c\u6210"]], "CSV\u30d5\u30a1\u30a4\u30eb\u306b\u5bfe\u3059\u308bfor\u6587": [[26, "CSV\u30d5\u30a1\u30a4\u30eb\u306b\u5bfe\u3059\u308bfor\u6587"]], "CSV\u30d5\u30a1\u30a4\u30eb\u306b\u5bfe\u3059\u308bwith\u6587": [[26, "CSV\u30d5\u30a1\u30a4\u30eb\u306b\u5bfe\u3059\u308bwith\u6587"]], "CSV\u30d5\u30a1\u30a4\u30eb\u306e\u66f8\u304d\u8fbc\u307f": [[26, "CSV\u30d5\u30a1\u30a4\u30eb\u306e\u66f8\u304d\u8fbc\u307f"]], "CSV\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f": [[26, "CSV\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u8fbc\u307f"]], "CSV\u5f62\u5f0f\u3068\u306f": [[26, "CSV\u5f62\u5f0f\u3068\u306f"]], "Colaboratory\u306e\u7acb\u3061\u4e0a\u3052": [[0, "Colaboratory\u306e\u7acb\u3061\u4e0a\u3052"]], "Jupyter Notebook \u3067\u306e\u5b9f\u884c\u65b9\u6cd5": [[28, "Jupyter-Notebook-\u3067\u306e\u5b9f\u884c\u65b9\u6cd5"]], "None": [[3, "None"]], "Python\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u5165\u9580": [[31, null]], "Windows\u3067\u306e\u5b9f\u884c\u65b9\u6cd5": [[28, "Windows\u3067\u306e\u5b9f\u884c\u65b9\u6cd5"]], "add": [[23, "add"]], "arange": [[16, "arange"]], "as": [[14, "as"]], "assert\u6587": [[4, "assert\u6587"]], "break\u6587": [[9, "break\u6587"]], "clear": [[23, "clear"]], "continue\u6587": [[9, "continue\u6587"]], "discard": [[23, "discard"]], "dot": [[16, "dot"]], "enumerate": [[9, "enumerate"]], "filter": [[18, "filter"]], "findall": [[30, "findall"]], "finditer": [[30, "finditer"]], "for\u6587": [[16, "for\u6587"]], "for\u6587\u3068\u30a4\u30c6\u30e9\u30d6\u30eb\u3068\u30a4\u30c6\u30ec\u30fc\u30bf": [[12, "for\u6587\u3068\u30a4\u30c6\u30e9\u30d6\u30eb\u3068\u30a4\u30c6\u30ec\u30fc\u30bf"]], "for\u6587\u306b\u3088\u308b\u30ea\u30b9\u30c8\u521d\u671f\u5316\u306e\u77ed\u7e2e\u8a18\u6cd5": [[6, "for\u6587\u306b\u3088\u308b\u30ea\u30b9\u30c8\u521d\u671f\u5316\u306e\u77ed\u7e2e\u8a18\u6cd5"]], "for\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057": [[9, "for\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057"]], "for\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057\u3068\u30d5\u30a1\u30a4\u30eb\u30aa\u30d6\u30b8\u30a7\u30af\u30c8": [[12, "for\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057\u3068\u30d5\u30a1\u30a4\u30eb\u30aa\u30d6\u30b8\u30a7\u30af\u30c8"]], "for\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057\u3068\u30ea\u30b9\u30c8\u30fb\u30bf\u30d7\u30eb": [[6, "for\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057\u3068\u30ea\u30b9\u30c8\u30fb\u30bf\u30d7\u30eb"]], "for\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057\u3068\u6587\u5b57\u5217": [[6, "for\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057\u3068\u6587\u5b57\u5217"]], "for\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057\u3068\u8f9e\u66f8": [[9, "for\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057\u3068\u8f9e\u66f8"]], "for\u6587\u306e\u4ed5\u7d44\u307f": [[12, "for\u6587\u306e\u4ed5\u7d44\u307f"]], "for\u6587\u306e\u5165\u308c\u5b50": [[9, "for\u6587\u306e\u5165\u308c\u5b50"]], "for\u6587\u306e\u8a08\u7b97\u91cf": [[9, "for\u6587\u306e\u8a08\u7b97\u91cf"]], "from": [[14, "from"]], "group": [[30, "group"]], "if \u2026 elif \u2026 else \u306b\u304a\u3051\u308b\u6761\u4ef6\u306e\u8a55\u4fa1": [[7, "if-...-elif-...-else-\u306b\u304a\u3051\u308b\u6761\u4ef6\u306e\u8a55\u4fa1"]], "if \u2026 elif \u2026 else \u306b\u3088\u308b\u6761\u4ef6\u5206\u5c90": [[7, "if-...-elif-...-else-\u306b\u3088\u308b\u6761\u4ef6\u5206\u5c90"]], "if \u2026 else \u306b\u3088\u308b\u6761\u4ef6\u5206\u5c90": [[7, "if-...-else-\u306b\u3088\u308b\u6761\u4ef6\u5206\u5c90"]], "if\u6587\u306b\u3088\u308b\u6761\u4ef6\u5206\u5c90": [[3, "if\u6587\u306b\u3088\u308b\u6761\u4ef6\u5206\u5c90"]], "iloc \u3068 loc": [[20, "iloc-\u3068-loc"]], "in": [[9, "in"]], "iter": [[12, "iter"]], "linspace": [[16, "linspace"]], "macOS \u3067\u306e\u5b9f\u884c\u65b9\u6cd5": [[28, "macOS-\u3067\u306e\u5b9f\u884c\u65b9\u6cd5"]], "map": [[18, "map"]], "matplotlib": [[25, "matplotlib"]], "max": [[18, "max"]], "max \u3068 min": [[6, "max-\u3068-min"]], "next": [[12, "next"]], "or \u3082\u3057\u304f\u306f and \u3067\u7d50\u5408\u3055\u308c\u305f\u6761\u4ef6\u306e\u8a55\u4fa1": [[7, "or-\u3082\u3057\u304f\u306f-and-\u3067\u7d50\u5408\u3055\u308c\u305f\u6761\u4ef6\u306e\u8a55\u4fa1"]], "pass\u6587": [[9, "pass\u6587"]], "pop": [[23, "pop"]], "print": [[2, "print"]], "print \u3068 return": [[2, "print-\u3068-return"]], "r \u3092\u4ed8\u3051\u308b\u7406\u7531": [[30, "r-\u3092\u4ed8\u3051\u308b\u7406\u7531"]], "random.rand": [[16, "random.rand"]], "range": [[9, "range"]], "range \u3068\u30ea\u30b9\u30c8": [[9, "range-\u3068\u30ea\u30b9\u30c8"]], "re.split": [[30, "re.split"]], "remove": [[23, "remove"]], "shebang": [[28, "shebang"]], "sort": [[16, "sort"]], "sorted": [[18, "sorted"]], "sub": [[30, "sub"]], "sum": [[6, "sum"]], "sum, max, min, mean": [[16, "sum,-max,-min,-mean"]], "union, intersection, difference": [[23, "union,-intersection,-difference"]], "while\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057": [[9, "while\u6587\u306b\u3088\u308b\u7e70\u308a\u8fd4\u3057"]], "zeros \u3068 ones": [[16, "zeros-\u3068-ones"]], "\u25b2 copy": [[6, "\u25b2-copy"]], "\u25b2 global \u5ba3\u8a00": [[10, "\u25b2-global-\u5ba3\u8a00"]], "\u25b2 keys, values, items \u306e\u8fd4\u5024": [[8, "\u25b2-keys,-values,-items-\u306e\u8fd4\u5024"]], "\u25b23\u9805\u6f14\u7b97\u5b50\uff08\u6761\u4ef6\u5f0f\uff09": [[7, "\u25b23\u9805\u6f14\u7b97\u5b50\uff08\u6761\u4ef6\u5f0f\uff09"]], "\u25b2Bokeh\u30e9\u30a4\u30d6\u30e9\u30ea": [[27, null]], "\u25b2CSV\u30d5\u30a1\u30a4\u30eb\u306e\u5165\u51fa\u529b": [[26, null]], "\u25b2Jupyter Notebook \u306e\u4f7f\u3044\u65b9": [[22, null]], "\u25b2Matplotlib\u30e9\u30a4\u30d6\u30e9\u30ea": [[29, null]], "\u25b2Python\u30b9\u30af\u30ea\u30d7\u30c8\u3068\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5b9f\u884c": [[28, null]], "\u25b2for\u6587\u3068while\u6587\u306b\u304a\u3051\u308b else": [[9, "\u25b2for\u6587\u3068while\u6587\u306b\u304a\u3051\u308b-else"]], "\u25b2with\u6587\u3078\u306e\u5bfe\u5fdc": [[19, "\u25b2with\u6587\u3078\u306e\u5bfe\u5fdc"]], "\u25b2\u30a4\u30c6\u30e9\u30d6\u30eb\u3068\u30a4\u30c6\u30ec\u30fc\u30bf\u306e\u5b9a\u7fa9": [[12, "\u25b2\u30a4\u30c6\u30e9\u30d6\u30eb\u3068\u30a4\u30c6\u30ec\u30fc\u30bf\u306e\u5b9a\u7fa9"]], "\u25b2\u30a8\u30b9\u30b1\u30fc\u30d7\u30b7\u30fc\u30b1\u30f3\u30b9": [[5, "\u25b2\u30a8\u30b9\u30b1\u30fc\u30d7\u30b7\u30fc\u30b1\u30f3\u30b9"]], "\u25b2\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u7b49\u4fa1\u6027\u3068\u540c\u4e00\u6027": [[6, "\u25b2\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u7b49\u4fa1\u6027\u3068\u540c\u4e00\u6027"]], "\u25b2\u30ad\u30fc\u304c\u306a\u3044\u5834\u5408\u306b\u767b\u9332\u3092\u884c\u3046": [[8, "\u25b2\u30ad\u30fc\u304c\u306a\u3044\u5834\u5408\u306b\u767b\u9332\u3092\u884c\u3046"]], "\u25b2\u30ad\u30fc\u3092\u6307\u5b9a\u3057\u305f\u524a\u9664": [[8, "\u25b2\u30ad\u30fc\u3092\u6307\u5b9a\u3057\u305f\u524a\u9664"]], "\u25b2\u30ad\u30fc\u30ef\u30fc\u30c9\u5f15\u6570": [[10, "\u25b2\u30ad\u30fc\u30ef\u30fc\u30c9\u5f15\u6570"]], "\u25b2\u30b0\u30ed\u30fc\u30d0\u30eb\u5909\u6570": [[2, "\u25b2\u30b0\u30ed\u30fc\u30d0\u30eb\u5909\u6570"]], "\u25b2\u30b8\u30a7\u30cd\u30ec\u30fc\u30bf\u5f0f": [[17, "\u25b2\u30b8\u30a7\u30cd\u30ec\u30fc\u30bf\u5f0f"]], "\u25b2\u30bb\u30c3\u30c8 (set)": [[23, null]], "\u25b2\u30bb\u30c3\u30c8\u5185\u5305\u8868\u8a18": [[17, "\u25b2\u30bb\u30c3\u30c8\u5185\u5305\u8868\u8a18"]], "\u25b2\u30c7\u30fc\u30bf\u306e\u30b0\u30eb\u30fc\u30d7\u5316": [[20, "\u25b2\u30c7\u30fc\u30bf\u306e\u30b0\u30eb\u30fc\u30d7\u5316"]], "\u25b2\u30c7\u30fc\u30bf\u306e\u7d50\u5408": [[20, "\u25b2\u30c7\u30fc\u30bf\u306e\u7d50\u5408"]], "\u25b2\u30c7\u30fc\u30bf\u306e\u9023\u7d50": [[20, "\u25b2\u30c7\u30fc\u30bf\u306e\u9023\u7d50"]], "\u25b2\u30ea\u30b9\u30c8\u304b\u3089\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3067\u6307\u5b9a\u3057\u305f\u8981\u7d20\u3092\u524a\u9664\u3059\u308b": [[6, "\u25b2\u30ea\u30b9\u30c8\u304b\u3089\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3067\u6307\u5b9a\u3057\u305f\u8981\u7d20\u3092\u524a\u9664\u3059\u308b"]], "\u25b2\u30ea\u30b9\u30c8\u304b\u3089\u8981\u7d20\u3092\u524a\u9664\u3059\u308b": [[6, "\u25b2\u30ea\u30b9\u30c8\u304b\u3089\u8981\u7d20\u3092\u524a\u9664\u3059\u308b"]], "\u25b2\u30ea\u30b9\u30c8\u306b\u30ea\u30b9\u30c8\u306e\u8981\u7d20\u3092\u8ffd\u52a0\u3059\u308b": [[6, "\u25b2\u30ea\u30b9\u30c8\u306b\u30ea\u30b9\u30c8\u306e\u8981\u7d20\u3092\u8ffd\u52a0\u3059\u308b"]], "\u25b2\u30ea\u30b9\u30c8\u306b\u8981\u7d20\u3092\u633f\u5165\u3059\u308b": [[6, "\u25b2\u30ea\u30b9\u30c8\u306b\u8981\u7d20\u3092\u633f\u5165\u3059\u308b"]], "\u25b2\u30ea\u30b9\u30c8\u306e\u8981\u7d20\u3092\u9006\u9806\u306b\u3059\u308b": [[6, "\u25b2\u30ea\u30b9\u30c8\u306e\u8981\u7d20\u3092\u9006\u9806\u306b\u3059\u308b"]], "\u25b2\u30ea\u30b9\u30c8\u8981\u7d20\u3092\u524a\u9664\u3059\u308b": [[6, "\u25b2\u30ea\u30b9\u30c8\u8981\u7d20\u3092\u524a\u9664\u3059\u308b"]], "\u25b2\u5168\u3066\u306e\u30ad\u30fc\u3068\u5024\u306e\u524a\u9664": [[8, "\u25b2\u5168\u3066\u306e\u30ad\u30fc\u3068\u5024\u306e\u524a\u9664"]], "\u25b2\u518d\u5e30": [[3, "\u25b2\u518d\u5e30"], [24, null]], "\u25b2\u53ef\u5909\u9577\u5f15\u6570": [[10, "\u25b2\u53ef\u5909\u9577\u5f15\u6570"]], "\u25b2\u5909\u6570\u3068\u3057\u3066\u306e\u95a2\u6570": [[10, "\u25b2\u5909\u6570\u3068\u3057\u3066\u306e\u95a2\u6570"]], "\u25b2\u5f15\u6570\u306e\u521d\u671f\u5024": [[10, "\u25b2\u5f15\u6570\u306e\u521d\u671f\u5024"]], "\u25b2\u5f15\u6570\u306e\u9806\u756a": [[10, "\u25b2\u5f15\u6570\u306e\u9806\u756a"]], "\u25b2\u6761\u4ef6\u3068\u3057\u3066\u4f7f\u308f\u308c\u308b\u4ed6\u306e\u5024": [[3, "\u25b2\u6761\u4ef6\u3068\u3057\u3066\u4f7f\u308f\u308c\u308b\u4ed6\u306e\u5024"]], "\u25b2\u6761\u4ef6\u4ed8\u304d\u5185\u5305\u8868\u8a18": [[17, "\u25b2\u6761\u4ef6\u4ed8\u304d\u5185\u5305\u8868\u8a18"]], "\u25b2\u6b20\u640d\u5024\u3001\u6642\u7cfb\u5217\u30c7\u30fc\u30bf\u306e\u51e6\u7406": [[20, "\u25b2\u6b20\u640d\u5024\u3001\u6642\u7cfb\u5217\u30c7\u30fc\u30bf\u306e\u51e6\u7406"]], "\u25b2\u6b63\u898f\u8868\u73fe": [[30, null]], "\u25b2\u771f\u7406\u5024\u914d\u5217\u306b\u3088\u308b\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30a2\u30af\u30bb\u30b9": [[16, "\u25b2\u771f\u7406\u5024\u914d\u5217\u306b\u3088\u308b\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30a2\u30af\u30bb\u30b9"]], "\u25b2\u7a7a\u767d\u6587\u5b57\u306e\u524a\u9664": [[5, "\u25b2\u7a7a\u767d\u6587\u5b57\u306e\u524a\u9664"]], "\u25b2\u7c21\u5358\u306a\u30c7\u30fc\u30bf\u306e\u53ef\u8996\u5316": [[25, null]], "\u25b2\u7dda\u5f62\u4ee3\u6570\u306e\u6f14\u7b97": [[16, "\u25b2\u7dda\u5f62\u4ee3\u6570\u306e\u6f14\u7b97"]], "\u25b2\u8907\u6570\u884c\u306b\u307e\u305f\u304c\u308b\u6761\u4ef6\u5f0f": [[7, "\u25b2\u8907\u6570\u884c\u306b\u307e\u305f\u304c\u308b\u6761\u4ef6\u5f0f"]], "\u25b2\u8f9e\u66f8\u3092\u8907\u88fd\u3059\u308b": [[8, "\u25b2\u8f9e\u66f8\u3092\u8907\u88fd\u3059\u308b"]], "\u25b2\u8f9e\u66f8\u5185\u5305\u8868\u8a18": [[17, "\u25b2\u8f9e\u66f8\u5185\u5305\u8868\u8a18"]], "\u25b2\u8f9e\u66f8\u578b\u306e\u53ef\u5909\u9577\u5f15\u6570": [[10, "\u25b2\u8f9e\u66f8\u578b\u306e\u53ef\u5909\u9577\u5f15\u6570"]], "\u25b2\u914d\u5217\u306e\u30c7\u30fc\u30bf\u5c5e\u6027": [[16, "\u25b2\u914d\u5217\u306e\u30c7\u30fc\u30bf\u5c5e\u6027"]], "\u3044\u304f\u3089\u3067\u3082\u5927\u304d\u304f\u306a\u308b\u6574\u6570": [[1, "\u3044\u304f\u3089\u3067\u3082\u5927\u304d\u304f\u306a\u308b\u6574\u6570"]], "\u305d\u306e\u4ed6\u306e\u53cd\u5fa9\u6f14\u7b97": [[30, "\u305d\u306e\u4ed6\u306e\u53cd\u5fa9\u6f14\u7b97"]], "\u3088\u304f\u4f7f\u308f\u308c\u308b\u914d\u5217\u64cd\u4f5c": [[16, "\u3088\u304f\u4f7f\u308f\u308c\u308b\u914d\u5217\u64cd\u4f5c"]], "\u30a4\u30c6\u30e9\u30d6\u30eb\u306f\u30a4\u30c6\u30ec\u30fc\u30bf\u3067\u306f\u306a\u3044": [[12, "\u30a4\u30c6\u30e9\u30d6\u30eb\u306f\u30a4\u30c6\u30ec\u30fc\u30bf\u3067\u306f\u306a\u3044"]], "\u30a4\u30c6\u30ec\u30fc\u30bf\u306f\u7279\u6b8a\u306a\u30a4\u30c6\u30e9\u30d6\u30eb": [[12, "\u30a4\u30c6\u30ec\u30fc\u30bf\u306f\u7279\u6b8a\u306a\u30a4\u30c6\u30e9\u30d6\u30eb"]], "\u30a4\u30c6\u30ec\u30fc\u30bf\u3092\u8fd4\u3059 enumerate": [[12, "\u30a4\u30c6\u30ec\u30fc\u30bf\u3092\u8fd4\u3059-enumerate"]], "\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30a2\u30af\u30bb\u30b9": [[16, "\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30a2\u30af\u30bb\u30b9"]], "\u30a4\u30f3\u30c7\u30f3\u30c8\u306b\u3088\u308b\u69cb\u6587": [[7, "\u30a4\u30f3\u30c7\u30f3\u30c8\u306b\u3088\u308b\u69cb\u6587"]], "\u30a8\u30e9\u30fc": [[1, "\u30a8\u30e9\u30fc"]], "\u30a8\u30e9\u30fc\u306e\u5206\u985e": [[4, "\u30a8\u30e9\u30fc\u306e\u5206\u985e"]], "\u30aa\u30d6\u30b8\u30a7\u30af\u30c8": [[3, "\u30aa\u30d6\u30b8\u30a7\u30af\u30c8"]], "\u30ab\u30ec\u30f3\u30c8\u30ef\u30fc\u30ad\u30f3\u30b0\u30c7\u30a3\u30ec\u30af\u30c8\u30ea": [[13, "\u30ab\u30ec\u30f3\u30c8\u30ef\u30fc\u30ad\u30f3\u30b0\u30c7\u30a3\u30ec\u30af\u30c8\u30ea"]], "\u30ad\u30fc\u3068\u5024\u306e\u4e00\u89a7\u3092\u5f97\u308b": [[8, "\u30ad\u30fc\u3068\u5024\u306e\u4e00\u89a7\u3092\u5f97\u308b"]], "\u30ad\u30fc\u306e\u4e00\u89a7\u3092\u5f97\u308b": [[8, "\u30ad\u30fc\u306e\u4e00\u89a7\u3092\u5f97\u308b"]], "\u30ad\u30fc\u3092\u6307\u5b9a\u3057\u3066\u5024\u3092\u5f97\u308b\u30e1\u30bd\u30c3\u30c9": [[8, "\u30ad\u30fc\u3092\u6307\u5b9a\u3057\u3066\u5024\u3092\u5f97\u308b\u30e1\u30bd\u30c3\u30c9"]], "\u30af\u30e9\u30b9\u5b9a\u7fa9": [[19, "\u30af\u30e9\u30b9\u5b9a\u7fa9"]], "\u30b0\u30e9\u30d5\u306e\u30d5\u30a1\u30a4\u30eb\u51fa\u529b": [[27, "\u30b0\u30e9\u30d5\u306e\u30d5\u30a1\u30a4\u30eb\u51fa\u529b"]], "\u30b0\u30e9\u30d5\u306e\u4f8b\uff1a\u30bd\u30fc\u30c8\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0\u306b\u304a\u3051\u308b\u6bd4\u8f03\u56de\u6570": [[27, "\u30b0\u30e9\u30d5\u306e\u4f8b\uff1a\u30bd\u30fc\u30c8\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0\u306b\u304a\u3051\u308b\u6bd4\u8f03\u56de\u6570"], [29, "\u30b0\u30e9\u30d5\u306e\u4f8b\uff1a\u30bd\u30fc\u30c8\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0\u306b\u304a\u3051\u308b\u6bd4\u8f03\u56de\u6570"]], "\u30b0\u30e9\u30d5\u306e\u753b\u50cf\u30d5\u30a1\u30a4\u30eb\u51fa\u529b": [[29, "\u30b0\u30e9\u30d5\u306e\u753b\u50cf\u30d5\u30a1\u30a4\u30eb\u51fa\u529b"]], "\u30b3\u30de\u30f3\u30c9\u30e2\u30fc\u30c9": [[22, "\u30b3\u30de\u30f3\u30c9\u30e2\u30fc\u30c9"]], "\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5b9f\u884c\u306e\u5177\u4f53\u4f8b": [[28, "\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5b9f\u884c\u306e\u5177\u4f53\u4f8b"]], "\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5f15\u6570": [[28, "\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5f15\u6570"]], "\u30b3\u30e1\u30f3\u30c8": [[1, "\u30b3\u30e1\u30f3\u30c8"]], "\u30b3\u30e1\u30f3\u30c8\u3068\u7a7a\u884c": [[2, "\u30b3\u30e1\u30f3\u30c8\u3068\u7a7a\u884c"]], "\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u30b9\u30bf\u30a4\u30eb": [[4, "\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u30b9\u30bf\u30a4\u30eb"]], "\u30b7\u30ea\u30fc\u30ba (Series) \u306e\u4f5c\u6210": [[20, "\u30b7\u30ea\u30fc\u30ba-(Series)-\u306e\u4f5c\u6210"]], "\u30b7\u30ea\u30fc\u30ba\u3068\u30c7\u30fc\u30bf\u30d5\u30ec\u30fc\u30e0": [[20, "\u30b7\u30ea\u30fc\u30ba\u3068\u30c7\u30fc\u30bf\u30d5\u30ec\u30fc\u30e0"]], "\u30b9\u30e9\u30a4\u30b9": [[16, "\u30b9\u30e9\u30a4\u30b9"]], "\u30bb\u30c3\u30c8\u306e\u30e1\u30bd\u30c3\u30c9": [[23, "\u30bb\u30c3\u30c8\u306e\u30e1\u30bd\u30c3\u30c9"]], "\u30bb\u30c3\u30c8\u306e\u7d44\u307f\u8fbc\u307f\u95a2\u6570": [[23, "\u30bb\u30c3\u30c8\u306e\u7d44\u307f\u8fbc\u307f\u95a2\u6570"]], "\u30bb\u30eb": [[0, "\u30bb\u30eb"], [22, "\u30bb\u30eb"]], "\u30bb\u30eb\u306e\u5b9f\u884c\u304c\u6b62\u307e\u3089\u306a\u3044\u3068\u304d": [[0, "\u30bb\u30eb\u306e\u5b9f\u884c\u304c\u6b62\u307e\u3089\u306a\u3044\u3068\u304d"]], "\u30bb\u30eb\u306e\u633f\u5165": [[0, "\u30bb\u30eb\u306e\u633f\u5165"]], "\u30bb\u30eb\u306e\u64cd\u4f5c": [[0, "\u30bb\u30eb\u306e\u64cd\u4f5c"]], "\u30bb\u30eb\u306e\u7de8\u96c6": [[0, "\u30bb\u30eb\u306e\u7de8\u96c6"]], "\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u5148\u982d\u90e8\u5206\u306b\u3042\u308b\u5ba3\u8a00": [[28, "\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb\u5148\u982d\u90e8\u5206\u306b\u3042\u308b\u5ba3\u8a00"]], "\u30bf\u30d7\u30eb (tuple)": [[6, "\u30bf\u30d7\u30eb-(tuple)"]], "\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3068\u968e\u5c64\u69cb\u9020": [[13, "\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3068\u968e\u5c64\u69cb\u9020"]], "\u30c7\u30d0\u30c3\u30b0\u306e\u5177\u4f53\u4f8b": [[4, "\u30c7\u30d0\u30c3\u30b0\u306e\u5177\u4f53\u4f8b"]], "\u30c7\u30fc\u30bf": [[21, "\u30c7\u30fc\u30bf"]], "\u30c7\u30fc\u30bf\u306e\u4e26\u3073\u66ff\u3048": [[20, "\u30c7\u30fc\u30bf\u306e\u4e26\u3073\u66ff\u3048"]], "\u30c7\u30fc\u30bf\u306e\u53c2\u7167": [[20, "\u30c7\u30fc\u30bf\u306e\u53c2\u7167"]], "\u30c7\u30fc\u30bf\u306e\u6761\u4ef6\u53d6\u308a\u51fa\u3057": [[20, "\u30c7\u30fc\u30bf\u306e\u6761\u4ef6\u53d6\u308a\u51fa\u3057"]], "\u30c7\u30fc\u30bf\u306e\u7d71\u8a08\u91cf": [[20, "\u30c7\u30fc\u30bf\u306e\u7d71\u8a08\u91cf"]], "\u30c7\u30fc\u30bf\u30d5\u30ec\u30fc\u30e0 (DataFrame) \u306e\u4f5c\u6210": [[20, "\u30c7\u30fc\u30bf\u30d5\u30ec\u30fc\u30e0-(DataFrame)-\u306e\u4f5c\u6210"]], "\u30c7\u30fc\u30bf\u8868\u73fe\u3068\u3057\u3066\u306e\u6728\u69cb\u9020": [[13, "\u30c7\u30fc\u30bf\u8868\u73fe\u3068\u3057\u3066\u306e\u6728\u69cb\u9020"]], "\u30ce\u30fc\u30c8\u30d6\u30c3\u30af\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9": [[0, "\u30ce\u30fc\u30c8\u30d6\u30c3\u30af\u306e\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9"]], "\u30ce\u30fc\u30c8\u30d6\u30c3\u30af\u306e\u53c2\u7167": [[0, "\u30ce\u30fc\u30c8\u30d6\u30c3\u30af\u306e\u53c2\u7167"]], "\u30ce\u30fc\u30c8\u30d6\u30c3\u30af\u306e\u64cd\u4f5c": [[0, "\u30ce\u30fc\u30c8\u30d6\u30c3\u30af\u306e\u64cd\u4f5c"]], "\u30ce\u30fc\u30c8\u30d6\u30c3\u30af\u30d5\u30a1\u30a4\u30eb\u3092\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb\u306b\u5909\u63db\u3059\u308b": [[15, "\u30ce\u30fc\u30c8\u30d6\u30c3\u30af\u30d5\u30a1\u30a4\u30eb\u3092\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb\u306b\u5909\u63db\u3059\u308b"]], "\u30d0\u30c3\u30af\u30b9\u30e9\u30c3\u30b7\u30e5\u306e\u8868\u793a\u3068\u5165\u529b": [[5, "\u30d0\u30c3\u30af\u30b9\u30e9\u30c3\u30b7\u30e5\u306e\u8868\u793a\u3068\u5165\u529b"]], "\u30d1\u30b9": [[13, "\u30d1\u30b9"]], "\u30d2\u30b9\u30c8\u30b0\u30e9\u30e0": [[27, "\u30d2\u30b9\u30c8\u30b0\u30e9\u30e0"], [29, "\u30d2\u30b9\u30c8\u30b0\u30e9\u30e0"]], "\u30d2\u30fc\u30c8\u30de\u30c3\u30d7": [[27, "\u30d2\u30fc\u30c8\u30de\u30c3\u30d7"], [29, "\u30d2\u30fc\u30c8\u30de\u30c3\u30d7"]], "\u30d5\u30a1\u30a4\u30eb\u306b\u5bfe\u3059\u308bwith\u6587": [[11, "\u30d5\u30a1\u30a4\u30eb\u306b\u5bfe\u3059\u308bwith\u6587"]], "\u30d5\u30a1\u30a4\u30eb\u306e\u30aa\u30fc\u30d7\u30f3": [[11, "\u30d5\u30a1\u30a4\u30eb\u306e\u30aa\u30fc\u30d7\u30f3"]], "\u30d5\u30a1\u30a4\u30eb\u306e\u30af\u30ed\u30fc\u30ba": [[11, "\u30d5\u30a1\u30a4\u30eb\u306e\u30af\u30ed\u30fc\u30ba"]], "\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u66f8\u304d\u306b\u304a\u3051\u308b\u6587\u5b57\u30b3\u30fc\u30c9\u6307\u5b9a": [[11, "\u30d5\u30a1\u30a4\u30eb\u306e\u8aad\u307f\u66f8\u304d\u306b\u304a\u3051\u308b\u6587\u5b57\u30b3\u30fc\u30c9\u6307\u5b9a"]], "\u30d5\u30a1\u30a4\u30eb\u3078\u306e\u66f8\u304d\u8fbc\u307f": [[11, "\u30d5\u30a1\u30a4\u30eb\u3078\u306e\u66f8\u304d\u8fbc\u307f"]], "\u30d5\u30a1\u30a4\u30eb\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u30a4\u30c6\u30ec\u30fc\u30bf": [[12, "\u30d5\u30a1\u30a4\u30eb\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306f\u30a4\u30c6\u30ec\u30fc\u30bf"]], "\u30d5\u30a1\u30a4\u30eb\u5168\u4f53\u306e\u8aad\u307f\u8fbc\u307f": [[11, "\u30d5\u30a1\u30a4\u30eb\u5168\u4f53\u306e\u8aad\u307f\u8fbc\u307f"]], "\u30e1\u30bf\u6587\u5b57": [[30, "\u30e1\u30bf\u6587\u5b57"]], "\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8": [[14, "\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8"]], "\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5b9f\u884c": [[28, "\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5b9f\u884c"]], "\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb": [[15, "\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb"]], "\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3059\u308b": [[15, "\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9\u3059\u308b"]], "\u30e2\u30c7\u30eb\u5b66\u7fd2\u306e\u57fa\u790e": [[21, "\u30e2\u30c7\u30eb\u5b66\u7fd2\u306e\u57fa\u790e"]], "\u30e6\u30cb\u30d0\u30fc\u30b5\u30eb\u95a2\u6570": [[16, "\u30e6\u30cb\u30d0\u30fc\u30b5\u30eb\u95a2\u6570"]], "\u30e9\u30e0\u30c0\u5f0f": [[18, "\u30e9\u30e0\u30c0\u5f0f"]], "\u30ea\u30b9\u30c8\u304b\u3089\u30a4\u30c6\u30e9\u30d6\u30eb\u3078": [[18, "\u30ea\u30b9\u30c8\u304b\u3089\u30a4\u30c6\u30e9\u30d6\u30eb\u3078"]], "\u30ea\u30b9\u30c8\u3068\u30a4\u30f3\u30c7\u30c3\u30af\u30b9": [[6, "\u30ea\u30b9\u30c8\u3068\u30a4\u30f3\u30c7\u30c3\u30af\u30b9"]], "\u30ea\u30b9\u30c8\u3068\u6587\u5b57\u5217\u306e\u76f8\u4e92\u5909\u63db": [[6, "\u30ea\u30b9\u30c8\u3068\u6587\u5b57\u5217\u306e\u76f8\u4e92\u5909\u63db"]], "\u30ea\u30b9\u30c8\u3068\u6f14\u7b97\u5b50": [[6, "\u30ea\u30b9\u30c8\u3068\u6f14\u7b97\u5b50"]], "\u30ea\u30b9\u30c8\u306b\u5bfe\u3059\u308b\u95a2\u6570\u30fb\u6f14\u7b97\u5b50\u30fb\u30e1\u30bd\u30c3\u30c9": [[6, "\u30ea\u30b9\u30c8\u306b\u5bfe\u3059\u308b\u95a2\u6570\u30fb\u6f14\u7b97\u5b50\u30fb\u30e1\u30bd\u30c3\u30c9"]], "\u30ea\u30b9\u30c8\u306b\u8981\u7d20\u3092\u8ffd\u52a0\u3059\u308b": [[6, "\u30ea\u30b9\u30c8\u306b\u8981\u7d20\u3092\u8ffd\u52a0\u3059\u308b"]], "\u30ea\u30b9\u30c8\u306e\u8981\u7d20\u6570": [[6, "\u30ea\u30b9\u30c8\u306e\u8981\u7d20\u6570"]], "\u30ea\u30b9\u30c8\u3084\u30bf\u30d7\u30eb\u306e\u6bd4\u8f03\u6f14\u7b97": [[6, "\u30ea\u30b9\u30c8\u3084\u30bf\u30d7\u30eb\u306e\u6bd4\u8f03\u6f14\u7b97"]], "\u30ea\u30b9\u30c8\u3092\u64cd\u4f5c\u3059\u308b\u30e1\u30bd\u30c3\u30c9\u306a\u3069": [[6, "\u30ea\u30b9\u30c8\u3092\u64cd\u4f5c\u3059\u308b\u30e1\u30bd\u30c3\u30c9\u306a\u3069"]], "\u30ea\u30b9\u30c8\u5185\u5305\u8868\u8a18": [[17, "\u30ea\u30b9\u30c8\u5185\u5305\u8868\u8a18"]], "\u30ed\u30fc\u30ab\u30eb\u5909\u6570": [[2, "\u30ed\u30fc\u30ab\u30eb\u5909\u6570"]], "\u4e26\u3079\u66ff\u3048\uff08sort \u30e1\u30bd\u30c3\u30c9\uff09": [[6, "\u4e26\u3079\u66ff\u3048\uff08sort-\u30e1\u30bd\u30c3\u30c9\uff09"]], "\u4e26\u3079\u66ff\u3048\uff08sorted \u7d44\u307f\u8fbc\u307f\u95a2\u6570\uff09": [[6, "\u4e26\u3079\u66ff\u3048\uff08sorted-\u7d44\u307f\u8fbc\u307f\u95a2\u6570\uff09"]], "\u4e88\u7d04\u8a9e": [[2, "\u4e88\u7d04\u8a9e"]], "\u4ed5\u69d8\u30fb\u30c6\u30b9\u30c8\u30fb\u30c7\u30d0\u30c3\u30b0": [[4, "\u4ed5\u69d8\u30fb\u30c6\u30b9\u30c8\u30fb\u30c7\u30d0\u30c3\u30b0"]], "\u4ee3\u5165\u6587": [[2, "\u4ee3\u5165\u6587"]], "\u5024\u306e\u4e00\u89a7\u3092\u5f97\u308b": [[8, "\u5024\u306e\u4e00\u89a7\u3092\u5f97\u308b"]], "\u5168\u89d2\u306e\u7a7a\u767d": [[1, "\u5168\u89d2\u306e\u7a7a\u767d"]], "\u5185\u5305\u8868\u8a18\u306e\u5165\u308c\u5b50": [[17, "\u5185\u5305\u8868\u8a18\u306e\u5165\u308c\u5b50"]], "\u518d\u5e30\u95a2\u6570\u306e\u4f8b\uff1a\u3079\u304d\u4e57\u306e\u8a08\u7b97": [[24, "\u518d\u5e30\u95a2\u6570\u306e\u4f8b\uff1a\u3079\u304d\u4e57\u306e\u8a08\u7b97"]], "\u518d\u5e30\u95a2\u6570\u306e\u4f8b\uff1a\u30de\u30fc\u30b8\u30bd\u30fc\u30c8": [[24, "\u518d\u5e30\u95a2\u6570\u306e\u4f8b\uff1a\u30de\u30fc\u30b8\u30bd\u30fc\u30c8"]], "\u518d\u5e30\u95a2\u6570\u306e\u4f8b\uff1a\u63a5\u982d\u8f9e\u30ea\u30b9\u30c8\u3068\u63a5\u5c3e\u8f9e\u30ea\u30b9\u30c8": [[24, "\u518d\u5e30\u95a2\u6570\u306e\u4f8b\uff1a\u63a5\u982d\u8f9e\u30ea\u30b9\u30c8\u3068\u63a5\u5c3e\u8f9e\u30ea\u30b9\u30c8"]], "\u5217\u306e\u8ffd\u52a0\u3068\u524a\u9664": [[20, "\u5217\u306e\u8ffd\u52a0\u3068\u524a\u9664"]], "\u521d\u5fc3\u8005\u306b\u3088\u304f\u3042\u308b\u8aa4\u89e3 \u2014 \u5909\u6570\u3068\u6587\u5b57\u5217\u306e\u6df7\u4e71": [[5, "\u521d\u5fc3\u8005\u306b\u3088\u304f\u3042\u308b\u8aa4\u89e3-----\u5909\u6570\u3068\u6587\u5b57\u5217\u306e\u6df7\u4e71"]], "\u521d\u671f\u5316\u3068\u5c5e\u6027": [[19, "\u521d\u671f\u5316\u3068\u5c5e\u6027"]], "\u5236\u5fa1\u69cb\u9020\u3068return\u6587": [[9, "\u5236\u5fa1\u69cb\u9020\u3068return\u6587"]], "\u5358\u9805\u306e + \u3068 -": [[1, "\u5358\u9805\u306e-+-\u3068--"]], "\u5909\u6570": [[2, "\u5909\u6570"]], "\u5909\u6570\u3068\u30b9\u30b3\u30fc\u30d7": [[10, "\u5909\u6570\u3068\u30b9\u30b3\u30fc\u30d7"]], "\u591a\u6b21\u5143\u914d\u5217": [[16, "\u591a\u6b21\u5143\u914d\u5217"]], "\u591a\u91cd\u30ea\u30b9\u30c8": [[6, "\u591a\u91cd\u30ea\u30b9\u30c8"]], "\u591a\u91cd\u4ee3\u5165": [[6, "\u591a\u91cd\u4ee3\u5165"]], "\u5927\u6587\u5b57\u30fb\u5c0f\u6587\u5b57": [[5, "\u5927\u6587\u5b57\u30fb\u5c0f\u6587\u5b57"]], "\u5b9f\u6570\u306e\u3079\u304d\u8868\u793a": [[1, "\u5b9f\u6570\u306e\u3079\u304d\u8868\u793a"]], "\u5b9f\u884c\u6642\u30a8\u30e9\u30fc": [[4, "\u5b9f\u884c\u6642\u30a8\u30e9\u30fc"]], "\u5f15\u6570": [[10, "\u5f15\u6570"]], "\u6298\u308c\u7dda\u30b0\u30e9\u30d5": [[25, "\u6298\u308c\u7dda\u30b0\u30e9\u30d5"]], "\u6307\u5b9a\u3057\u305f\u8981\u7d20\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u53d6\u5f97\u3068\u6570\u3048\u3042\u3052": [[6, "\u6307\u5b9a\u3057\u305f\u8981\u7d20\u306e\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u53d6\u5f97\u3068\u6570\u3048\u3042\u3052"]], "\u6539\u884c\u6587\u5b57\u306e\u524a\u9664": [[11, "\u6539\u884c\u6587\u5b57\u306e\u524a\u9664"]], "\u6559\u5e2b\u3042\u308a\u5b66\u7fd2": [[21, "\u6559\u5e2b\u3042\u308a\u5b66\u7fd2"]], "\u6559\u5e2b\u3042\u308a\u5b66\u7fd2\u30fb\u5206\u985e\u306e\u4f8b": [[21, "\u6559\u5e2b\u3042\u308a\u5b66\u7fd2\u30fb\u5206\u985e\u306e\u4f8b"]], "\u6559\u5e2b\u3042\u308a\u5b66\u7fd2\u30fb\u56de\u5e30\u306e\u4f8b": [[21, "\u6559\u5e2b\u3042\u308a\u5b66\u7fd2\u30fb\u56de\u5e30\u306e\u4f8b"]], "\u6559\u5e2b\u306a\u3057\u5b66\u7fd2": [[21, "\u6559\u5e2b\u306a\u3057\u5b66\u7fd2"]], "\u6559\u5e2b\u306a\u3057\u5b66\u7fd2\u30fb\u30af\u30e9\u30b9\u30bf\u30ea\u30f3\u30b0\u306e\u4f8b": [[21, "\u6559\u5e2b\u306a\u3057\u5b66\u7fd2\u30fb\u30af\u30e9\u30b9\u30bf\u30ea\u30f3\u30b0\u306e\u4f8b"]], "\u6559\u5e2b\u306a\u3057\u5b66\u7fd2\u30fb\u6b21\u5143\u524a\u6e1b\u306e\u4f8b": [[21, "\u6559\u5e2b\u306a\u3057\u5b66\u7fd2\u30fb\u6b21\u5143\u524a\u6e1b\u306e\u4f8b"]], "\u6559\u6750\u306e\u30aa\u30fc\u30d7\u30f3": [[0, "\u6559\u6750\u306e\u30aa\u30fc\u30d7\u30f3"]], "\u6563\u5e03\u56f3": [[25, "\u6563\u5e03\u56f3"], [27, "\u6563\u5e03\u56f3"], [29, "\u6563\u5e03\u56f3"]], "\u6570\u3048\u4e0a\u3052": [[5, "\u6570\u3048\u4e0a\u3052"]], "\u6570\u5024\u8aa4\u5dee": [[1, "\u6570\u5024\u8aa4\u5dee"]], "\u6570\u5b66\u95a2\u6570\uff08\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\uff09": [[1, "\u6570\u5b66\u95a2\u6570\uff08\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\uff09"]], "\u6574\u6570\u3068\u5b9f\u6570": [[1, "\u6574\u6570\u3068\u5b9f\u6570"]], "\u6574\u6570\u3068\u5b9f\u6570\u306e\u9593\u306e\u5909\u63db": [[1, "\u6574\u6570\u3068\u5b9f\u6570\u306e\u9593\u306e\u5909\u63db"]], "\u6587\u5b57\u30af\u30e9\u30b9": [[30, "\u6587\u5b57\u30af\u30e9\u30b9"]], "\u6587\u5b57\u30b3\u30fc\u30c9\u5ba3\u8a00": [[28, "\u6587\u5b57\u30b3\u30fc\u30c9\u5ba3\u8a00"]], "\u6587\u5b57\u5217\u3068\u30a4\u30f3\u30c7\u30c3\u30af\u30b9": [[5, "\u6587\u5b57\u5217\u3068\u30a4\u30f3\u30c7\u30c3\u30af\u30b9"]], "\u6587\u5b57\u5217\u3068\u30b9\u30e9\u30a4\u30b9": [[5, "\u6587\u5b57\u5217\u3068\u30b9\u30e9\u30a4\u30b9"]], "\u6587\u5b57\u5217\u3068\u30e1\u30bd\u30c3\u30c9": [[5, "\u6587\u5b57\u5217\u3068\u30e1\u30bd\u30c3\u30c9"]], "\u6587\u5b57\u5217\u306e\u691c\u7d22": [[5, "\u6587\u5b57\u5217\u306e\u691c\u7d22"]], "\u6587\u5b57\u5217\u306e\u6bd4\u8f03\u6f14\u7b97": [[5, "\u6587\u5b57\u5217\u306e\u6bd4\u8f03\u6f14\u7b97"]], "\u6587\u5b57\u5217\u306e\u9023\u7d50": [[5, "\u6587\u5b57\u5217\u306e\u9023\u7d50"]], "\u6728\u69cb\u9020": [[13, "\u6728\u69cb\u9020"]], "\u6771\u4eac\u306e7\u6708\u306e\u6c17\u6e29": [[26, "\u6771\u4eac\u306e7\u6708\u306e\u6c17\u6e29"]], "\u68d2\u30b0\u30e9\u30d5": [[25, "\u68d2\u30b0\u30e9\u30d5"], [27, "\u68d2\u30b0\u30e9\u30d5"], [29, "\u68d2\u30b0\u30e9\u30d5"]], "\u691c\u7d22": [[5, "\u691c\u7d22"]], "\u69cb\u6587\u30a8\u30e9\u30fc": [[4, "\u69cb\u6587\u30a8\u30e9\u30fc"]], "\u69d8\u3005\u306a\u6761\u4ef6": [[3, "\u69d8\u3005\u306a\u6761\u4ef6"]], "\u6a5f\u68b0\u5b66\u7fd2\u306b\u3064\u3044\u3066": [[21, "\u6a5f\u68b0\u5b66\u7fd2\u306b\u3064\u3044\u3066"]], "\u6b63\u898f\u8868\u73fe\u306b\u95a2\u3059\u308b\u57fa\u672c\u7684\u306a\u95a2\u6570": [[30, "\u6b63\u898f\u8868\u73fe\u306b\u95a2\u3059\u308b\u57fa\u672c\u7684\u306a\u95a2\u6570"]], "\u6b63\u898f\u8868\u73fe\u306b\u95a2\u3059\u308b\u95a2\u6570\u3068\u30e1\u30bd\u30c3\u30c9": [[30, "\u6b63\u898f\u8868\u73fe\u306b\u95a2\u3059\u308b\u95a2\u6570\u3068\u30e1\u30bd\u30c3\u30c9"]], "\u6b63\u898f\u8868\u73fe\u306e\u30a8\u30b9\u30b1\u30fc\u30d7\u30b7\u30fc\u30b1\u30f3\u30b9": [[30, "\u6b63\u898f\u8868\u73fe\u306e\u30a8\u30b9\u30b1\u30fc\u30d7\u30b7\u30fc\u30b1\u30f3\u30b9"]], "\u6b63\u898f\u8868\u73fe\u306e\u57fa\u672c": [[30, "\u6b63\u898f\u8868\u73fe\u306e\u57fa\u672c"]], "\u6bd4\u8f03\u6f14\u7b97": [[23, "\u6bd4\u8f03\u6f14\u7b97"]], "\u6f14\u7b97\u5b50\u306e\u512a\u5148\u9806\u4f4d\u3068\u62ec\u5f27": [[1, "\u6f14\u7b97\u5b50\u306e\u512a\u5148\u9806\u4f4d\u3068\u62ec\u5f27"]], "\u7279\u6b8a\u30e1\u30bd\u30c3\u30c9": [[19, "\u7279\u6b8a\u30e1\u30bd\u30c3\u30c9"]], "\u771f\u7406\u5024\u3092\u8fd4\u3059\u95a2\u6570": [[3, "\u771f\u7406\u5024\u3092\u8fd4\u3059\u95a2\u6570"]], "\u7834\u58ca\u7684\uff08\u30a4\u30f3\u30d7\u30ec\u30fc\u30b9\uff09\u306a\u64cd\u4f5c\u3068\u975e\u7834\u58ca\u7684\u306a\u751f\u6210": [[6, "\u7834\u58ca\u7684\uff08\u30a4\u30f3\u30d7\u30ec\u30fc\u30b9\uff09\u306a\u64cd\u4f5c\u3068\u975e\u7834\u58ca\u7684\u306a\u751f\u6210"]], "\u7a7a\u6587\u5b57\u5217": [[5, "\u7a7a\u6587\u5b57\u5217"]], "\u7a7a\u767d": [[1, "\u7a7a\u767d"]], "\u7b97\u8853\u6f14\u7b97\u5b50\u306e\u307e\u3068\u3081": [[1, "\u7b97\u8853\u6f14\u7b97\u5b50\u306e\u307e\u3068\u3081"]], "\u7c21\u5358\u306a\u7b97\u8853\u8a08\u7b97": [[1, "\u7c21\u5358\u306a\u7b97\u8853\u8a08\u7b97"]], "\u7d22\u5f15": [[32, null]], "\u7d2f\u7a4d\u4ee3\u5165\u6587": [[2, "\u7d2f\u7a4d\u4ee3\u5165\u6587"]], "\u7d99\u627f": [[19, "\u7d99\u627f"]], "\u7d99\u627f\u306b\u3088\u308b\u632f\u821e\u3044\u306e\u6539\u5909": [[19, "\u7d99\u627f\u306b\u3088\u308b\u632f\u821e\u3044\u306e\u6539\u5909"]], "\u7dda\u30b0\u30e9\u30d5": [[27, "\u7dda\u30b0\u30e9\u30d5"], [29, "\u7dda\u30b0\u30e9\u30d5"]], "\u7de8\u96c6\u30e2\u30fc\u30c9": [[22, "\u7de8\u96c6\u30e2\u30fc\u30c9"]], "\u7de8\u96c6\u4e2d\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u52d5\u4f5c": [[11, "\u7de8\u96c6\u4e2d\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u52d5\u4f5c"]], "\u7df4\u7fd2": [[0, "\u7df4\u7fd2"], [1, "\u7df4\u7fd2"], [5, "\u7df4\u7fd2"], [5, "id11"], [5, "id13"], [5, "id15"], [5, "id19"], [5, "id21"], [6, "\u7df4\u7fd2"], [6, "id18"], [6, "id19"], [6, "id22"], [6, "id24"], [7, "\u7df4\u7fd2"], [7, "id4"], [7, "id7"], [8, "\u7df4\u7fd2"], [8, "id12"], [9, "\u7df4\u7fd2"], [9, "id4"], [9, "id5"], [9, "id8"], [9, "id9"], [9, "id11"], [9, "id12"], [9, "id13"], [9, "id14"], [9, "id15"], [9, "id16"], [9, "id17"], [9, "id18"], [9, "id19"], [9, "id20"], [11, "\u7df4\u7fd2"], [11, "id7"], [11, "id10"], [12, "\u7df4\u7fd2"], [12, "id6"], [14, "\u7df4\u7fd2"], [16, "\u7df4\u7fd2"], [17, "\u7df4\u7fd2"], [17, "id4"], [17, "id5"], [17, "id7"], [17, "id8"], [18, "\u7df4\u7fd2"], [18, "id5"], [18, "id6"], [18, "id7"], [19, "\u7df4\u7fd2"], [21, "\u7df4\u7fd2"], [21, "id10"], [22, "\u7df4\u7fd2"], [23, "\u7df4\u7fd2"], [23, "id3"], [23, "id7"], [26, "\u7df4\u7fd2"], [26, "id6"], [28, "\u7df4\u7fd2"], [28, "id4"], [28, "id5"], [28, "id6"], [28, "id7"], [29, "\u7df4\u7fd2"], [29, "id4"], [29, "id6"], [29, "id8"], [29, "id10"], [29, "id12"], [30, "\u7df4\u7fd2"], [30, "id4"], [30, "id5"], [30, "id6"], [30, "id7"], [30, "id10"], [30, "id11"], [30, "id14"], [30, "id15"], [30, "id16"], [30, "id17"], [30, "id20"], [30, "id21"]], "\u7df4\u7fd2 absolute": [[3, "\u7df4\u7fd2-absolute"]], "\u7df4\u7fd2 ft_to_cm": [[2, "\u7df4\u7fd2-ft_to_cm"]], "\u7df4\u7fd2 qe_disc qe_solution1 qe_solution1": [[2, "\u7df4\u7fd2-qe_disc-qe_solution1-qe_solution1"]], "\u7df4\u7fd2 quadratic": [[2, "\u7df4\u7fd2-quadratic"]], "\u7df4\u7fd2 sign": [[3, "\u7df4\u7fd2-sign"]], "\u7df4\u7fd2\u306e\u89e3\u7b54": [[2, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [3, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [5, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [6, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [7, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [8, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [9, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [9, "id23"], [11, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [12, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [14, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [16, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [17, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [18, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [19, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [23, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [26, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [28, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [29, "\u7df4\u7fd2\u306e\u89e3\u7b54"], [30, "\u7df4\u7fd2\u306e\u89e3\u7b54"]], "\u7df4\u7fd2\u306e\u89e3\u7b54\u4f8b": [[21, "\u7df4\u7fd2\u306e\u89e3\u7b54\u4f8b"]], "\u7df4\u7fd2\u306e\u89e3\u8aac": [[7, "\u7df4\u7fd2\u306e\u89e3\u8aac"], [9, "\u7df4\u7fd2\u306e\u89e3\u8aac"]], "\u7f6e\u63db": [[5, "\u7f6e\u63db"]], "\u81ea\u4f5c\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u4f7f\u3044\u65b9": [[15, "\u81ea\u4f5c\u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u4f7f\u3044\u65b9"]], "\u884c\u306e\u8aad\u307f\u8fbc\u307f": [[11, "\u884c\u306e\u8aad\u307f\u8fbc\u307f"]], "\u884c\u306e\u8ffd\u52a0\u3068\u524a\u9664": [[20, "\u884c\u306e\u8ffd\u52a0\u3068\u524a\u9664"]], "\u8907\u6570\u306e\u5f15\u6570": [[10, "\u8907\u6570\u306e\u5f15\u6570"]], "\u8981\u7d20\u578b": [[16, "\u8981\u7d20\u578b"]], "\u8981\u7d20\u6bce\u306e\u6f14\u7b97": [[16, "\u8981\u7d20\u6bce\u306e\u6f14\u7b97"]], "\u8ad6\u7406\u30a8\u30e9\u30fc": [[4, "\u8ad6\u7406\u30a8\u30e9\u30fc"]], "\u8f9e\u66f8\u3068\u30ea\u30b9\u30c8": [[8, "\u8f9e\u66f8\u3068\u30ea\u30b9\u30c8"]], "\u8f9e\u66f8\u306e\u30e1\u30bd\u30c3\u30c9": [[8, "\u8f9e\u66f8\u306e\u30e1\u30bd\u30c3\u30c9"]], "\u8fd4\u5024": [[10, "\u8fd4\u5024"]], "\u914d\u5217\u306e\u30b9\u30ab\u30e9\u6f14\u7b97": [[16, "\u914d\u5217\u306e\u30b9\u30ab\u30e9\u6f14\u7b97"]], "\u914d\u5217\u306e\u4fdd\u5b58\u3068\u5fa9\u5143": [[16, "\u914d\u5217\u306e\u4fdd\u5b58\u3068\u5fa9\u5143"]], "\u914d\u5217\u306e\u69cb\u7bc9": [[16, "\u914d\u5217\u306e\u69cb\u7bc9"]], "\u914d\u5217\u540c\u58eb\u306e\u6f14\u7b97": [[16, "\u914d\u5217\u540c\u58eb\u306e\u6f14\u7b97"]], "\u914d\u5217\u8981\u7d20\u306e\u64cd\u4f5c": [[16, "\u914d\u5217\u8981\u7d20\u306e\u64cd\u4f5c"]], "\u914d\u5217\u8981\u7d20\u3092\u751f\u6210\u3059\u308b\u69cb\u7bc9\u95a2\u6570": [[16, "\u914d\u5217\u8981\u7d20\u3092\u751f\u6210\u3059\u308b\u69cb\u7bc9\u95a2\u6570"]], "\u95a2\u6570\u306e\u53c2\u7167\u306e\u66f8\u304d\u65b9": [[2, "\u95a2\u6570\u306e\u53c2\u7167\u306e\u66f8\u304d\u65b9"]], "\u95a2\u6570\u306e\u5b9a\u7fa9": [[10, "\u95a2\u6570\u306e\u5b9a\u7fa9"]], "\u95a2\u6570\u306e\u5b9a\u7fa9\u3068\u8fd4\u5024": [[2, "\u95a2\u6570\u306e\u5b9a\u7fa9\u3068\u8fd4\u5024"]], "\u96c6\u5408\u6f14\u7b97": [[23, "\u96c6\u5408\u6f14\u7b97"]], "\uff08\u6ce8\u610f\uff09Shift-Enter\u306b\u53cd\u5fdc\u304c\u306a\u304f\u306a\u3063\u305f\u3068\u304d": [[22, "\uff08\u6ce8\u610f\uff09Shift-Enter\u306b\u53cd\u5fdc\u304c\u306a\u304f\u306a\u3063\u305f\u3068\u304d"]]}, "docnames": ["1/1-0", "1/1-1", "1/1-2", "1/1-3", "1/1-4", "2/2-1", "2/2-2", "2/2-3", "3/3-1", "3/3-2", "3/3-3", "4/4-1", "4/4-2", "4/4-3", "5/5-1", "5/5-2", "5/5-3", "6/6-1", "6/6-2", "6/6-3", "7/7-1", "7/7-2", "appendix/1-jupyter-notebook", "appendix/2-set", "appendix/3-recursion", "appendix/3-visualization", "appendix/4-csv", "appendix/5-bokeh", "appendix/5-command", "appendix/5-matplotlib", "appendix/5-re", "index", "index_of_terms"], "envversion": {"nbsphinx": 4, "sphinx": 63, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["1/1-0.ipynb", "1/1-1.ipynb", "1/1-2.ipynb", "1/1-3.ipynb", "1/1-4.ipynb", "2/2-1.ipynb", "2/2-2.ipynb", "2/2-3.ipynb", "3/3-1.ipynb", "3/3-2.ipynb", "3/3-3.ipynb", "4/4-1.ipynb", "4/4-2.ipynb", "4/4-3.ipynb", "5/5-1.ipynb", "5/5-2.ipynb", "5/5-3.ipynb", "6/6-1.ipynb", "6/6-2.ipynb", "6/6-3.ipynb", "7/7-1.ipynb", "7/7-2.ipynb", "appendix/1-jupyter-notebook.ipynb", "appendix/2-set.ipynb", "appendix/3-recursion.ipynb", "appendix/3-visualization.ipynb", "appendix/4-csv.ipynb", "appendix/5-bokeh.ipynb", "appendix/5-command.ipynb", "appendix/5-matplotlib.ipynb", "appendix/5-re.ipynb", "index.rst", "index_of_terms.ipynb"], "indexentries": {}, "objects": {}, "objnames": {}, "objtypes": {}, "terms": {"!&": 5, "!'": [5, 9, 23, 30], "!/": 28, "!=": [5, 6, 9, 23], "!?": 30, "!\\": 30, "\"\"": [5, 30], "\"(": 30, "\")": [7, 11, 30], "\",": 8, "\">": 30, "\"[": 30, "# '": [11, 20], "# k": 21, "# x": [3, 24], "# \u03c0": 14, "# \u6708": 29, "##": [7, 10, 21], "#'": 1, "#\\": 30, "#`": 30, "#add": 32, "#arg": 28, "#break": 9, "#clear": 32, "#csv": 32, "#defining": [2, 10], "#dictionaries": 8, "#discard": 32, "#findall": 32, "#finditer": 32, "#first": [2, 9], "#for": 9, "#group": 32, "#if": 7, "#iterators": 12, "#list": 17, "#lists": 6, "#matplotlib": 32, "#nested": 17, "#numargs": 28, "#pass": 9, "#pop": 32, "#print": 2, "#re": 32, "#reading": 11, "#remove": 32, "#scriptname": 28, "#sets": 23, "#shebang": 32, "#sphx": 25, "#strings": 5, "#sub": 32, "#sum": 28, "#term": 12, "#the": 9, "#tuples": 6, "#typeiter": 12, "#union": 32, "#using": 1, "#w": 6, "#\u25b2": 32, "#\u300c": 30, "#\u30e1\u30bf": 32, "$'": 30, "$\uff09": 14, "%matplotlib": [25, 29], "& (": [16, 20], "&#": [2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 17, 18, 19, 23, 24, 26, 27, 28, 29, 30], ">": [9, 11, 18], "<": [9, 13, 18, 19, 20, 30], "' #": 30, "'\"": 5, "'#": 27, "''": [5, 11, 19, 24, 30], "'(": 30, "')": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 20, 21, 23, 24, 25, 26, 27, 29, 30], "'*": 29, "'+": 9, "',": [2, 4, 5, 6, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 26, 27, 28, 29, 30], "'.": [5, 6, 11, 26], "':": [4, 6, 8, 9, 10, 13, 17, 20, 23, 25, 27, 28], "';": 30, "'<": 30, "'>": 30, "'[": [5, 30], "'\\": 30, "']": [6, 8, 9, 10, 13, 17, 19, 20, 21, 27], "'__": 28, "'a": [4, 5, 6, 9, 11, 23, 30], "'a']": 9, "'aaaaaaa": 5, "'aabccc": 23, "'apple": 8, "'atgc": 6, "'b": [6, 9, 23], "'b']": 4, "'banana": [6, 8], "'black": 9, "'bool": 16, "'c": [5, 6, 9, 23], "'cat": 17, "'complex": 16, "'d": [6, 9], "'e": [6, 9], "'f": [6, 9, 20], "'float": 16, "'g": [5, 6, 9], "'h": 9, "'hello": [5, 10, 19, 30], "'i": 9, "'int": 16, "'j": 9, "'k": 9, "'l": 9, "'lo": 5, "'mod": 28, "'mycolumn": 20, "'n": 6, "'pen": 8, "'r": [4, 11, 12, 13, 18, 26, 29, 30], "'s": [5, 30], "'sample": 11, "'sepal": 20, "'shift": 26, "'species": 20, "'str": 5, "'t": [5, 27, 30], "'tokyo": 26, "'user": 26, "'utf": 26, "'w": [11, 26], "'w']": 20, "'white": 9, "'x": [7, 27], "'y": [6, 27], "'z": [5, 6, 9], "'}": [9, 10, 20], "'\u5217": 20, "'\uff09": 10, "(\"": [5, 7, 8, 30], "(&": [4, 5, 6, 7, 8, 10, 11, 12, 13, 19, 30], "('": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 23, 24, 26, 27, 28, 29, 30], "('s": 30, "((": [6, 14, 16, 18, 23, 30], "()": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 20, 21, 23, 25, 26, 27, 28, 29, 30], "(*": 10, "(-": [1, 3, 4, 27, 29], "(.": 30, "(..": [13, 24], "([": [6, 7, 8, 9, 10, 12, 16, 17, 18, 20, 23, 26, 27, 29, 30], "(\\": 7, "(a": [1, 2, 3, 6, 7, 16, 24, 30], "(ab": 30, "(abs": 18, "(add": 9, "(all": 16, "(args": 10, "(ary": 29, "(aryx": 29, "(atgc": [5, 6], "(b": [1, 16, 30], "(base": 24, "(bc": 30, "(c": [6, 9, 16], "(change": 6, "(characters": 6, "(check": [5, 23, 30], "(chr": 9, "(cls": 1, "(collect": 9, "(color": 27, "(colors": 27, "(comprehension": 17, "(construct": 9, "(cos": 14, "(count": [9, 23], "(csv": 26, "(d": [9, 18, 20, 25, 27, 29], "(data": [24, 27, 29], "(datareader": 26, "(datawriter": 26, "(desired": 27, "(dic": [8, 9, 23], "(e": 14, "(egory": 30, "(email": 6, "(en": 10, "(english": 25, "(escaped": 5, "(exception": 7, "(expt": 24, "(f": [2, 11, 12, 13, 18, 19, 26, 29], "(fact": [14, 28], "(factorial": 14, "(file": [4, 11, 13, 18], "(filter": 18, "(float": [1, 26, 29], "(floor": 14, "(format": 27, "(ft": 2, "(get": 30, "(greet": 10, "(greeting": 10, "(h": 2, "(handle": 9, "(height": [2, 9], "(hellofile": 19, "(hellofileiterator": 19, "(helloforever": 19, "(i": [1, 9, 12, 16, 17, 26, 29, 30], "(identify": 9, "(idx": 16, "(im": 29, "(infile": 11, "(int": [9, 21], "(iris": [20, 21], "(it": [12, 18], "(iter": 12, "(iterable": 12, "(iterator": 12, "(itms": 8, "(j": 9, "(k": [27, 29], "(ks": 8, "(kwargs": 10, "(l": [24, 27, 29], "(lambda": 18, "(last": 11, "(ld": 8, "(left": 9, "(len": [8, 9, 17, 20, 26, 27, 29, 30], "(length": 17, "(line": [11, 12, 19, 21], "(list": [8, 9, 17, 19, 23, 27, 30], "(ln": [6, 9, 18], "(ln1": 9, "(log": 14, "(ls": [6, 12, 18], "(ls1": 25, "(ls2": 25, "(lst": [9, 17, 27, 29], "(m": [2, 30], "(map": [16, 18], "(mapping": 9, "(marker": 27, "(match": 30, "(math": [1, 2, 14], "(max": 18, "(mi": 26, "(month": 29, "(months": 29, "(mycolumn": 20, "(n": [3, 9, 15, 16, 21, 27, 28], "(name": [10, 11, 12, 26], "(none": 3, "(np": [14, 16, 20], "(num": 28, "(number": [11, 18, 30], "(numbers": [6, 8], "(numpy": [14, 26], "(nums": 10, "(obj": 1, "(ord": 9, "(outfile": 11, "(p": 27, "(palette": 27, "(pi": 14, "(point": 6, "(pos": 18, "(ppap": 8, "(qe": 2, "(r": [24, 30], "(random": 9, "(range": [9, 27], "(reg": 30, "(regular": 30, "(remove": [5, 6], "(res": 29, "(reverse": [6, 8, 9], "(row": [16, 26, 29], "(s": [2, 9, 11, 12, 17, 20, 24, 28, 30], "(self": [1, 11, 19], "(sepal": 20, "(seq": 9, "(set": 23, "(shape": 16, "(sign": 7, "(simple": 9, "(sin": 14, "(size": 27, "(solver": 21, "(some": 9, "(sorted": 6, "(sqrt": 14, "(src": 11, "(start": 20, "(str": [5, 6, 8, 9, 23, 30], "(stream": 1, "(sum": [6, 9, 17], "(sumnumbers": 30, "(swap": [5, 9], "(sys": 28, "(temp": 29, "(temperature": 2, "(temps": 29, "(title": 27, "(top": 27, "(triple": 5, "(true": 29, "(u": 30, "(v": [16, 28], "(value": [6, 8, 9], "(var": 17, "(ve": 30, "(vs": 8, "(w": [9, 17], "(word": [5, 30], "(words": 9, "(x": [1, 2, 3, 4, 6, 7, 9, 12, 17, 18, 21, 24, 25, 26, 27, 29], "(xp": 26, "(y": [1, 6, 21, 27, 29], "(year": [26, 29], "(years": [26, 29], "({": [8, 9, 18, 20, 23, 27], "(\u00d7": 30, "(\u5f0f": [5, 19], ")\n#": [9, 30], ")\np": 27, ")\"": 30, ")#": 30, ")%": 26, ")&": [18, 30], ")'": [29, 30], ")(": [1, 30], "))": [1, 2, 6, 7, 8, 9, 14, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30], ")*": [1, 2, 9, 17, 24, 30], ")+": [9, 17, 30], "),": [8, 16, 20, 24, 26, 27, 29, 30], ")-": 9, ").": [16, 20, 29], ")/": [1, 9, 10, 17, 21, 27, 29], "):": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 23, 24, 26, 27, 28, 29, 30], ");": [21, 29], ")": 18, ")?": 30, ")@": 30, ")[": 6, ")\\": 30, ")]": [8, 9, 16, 17, 18, 20, 24, 27, 29, 30], ")`": 30, ")d": 30, ")e": 30, ")t": 30, ")|": 30, ")\u3001": [2, 9], ")\u3002": 22, ")\u30fb": 20, "* (": 2, "* b": 16, "*&": 30, "*'": [29, 30], "*(": [1, 2, 24], "*(\\": 30, "*)": 30, "**": [1, 2, 4, 6, 9, 10, 11, 13, 17, 24], "*-": [28, 30], "*..": 24, "*\\": 30, "*]": [22, 30], "*av": 17, "*b": 2, "*c": 2, "*g": [2, 30], "*m": 24, "*n": 27, "*number": 10, "*x": [2, 4, 17, 24], "*y": 17, "+ a": 7, "+ c": 9, "+'": [10, 30], "+(": [27, 29], "+1": 9, "+=": [9, 29], "+[": 9, "+b": 2, "+c": [0, 2, 22], "+enter": [0, 22], "+i": 16, "+j": 9, "+name": 10, "+return": 0, "+s": [0, 22], "+v": [0, 22], "+w": 21, "+x": [0, 4, 6, 22], "+z": [0, 22], "+\u2192": 30, ", \"": 30, ", '": [5, 9, 10, 11, 20, 23, 27, 30], ", [": [6, 9, 17, 20], ", axis": 20, ", color": 29, ", count": 9, ", dic": 9, ", digits": 5, ", end": 13, ", fact": 28, ", file": 11, ", float": 26, ", high": 27, ", i": 9, ", index": 20, ", j": 9, ", key": 9, ", label": 29, ", line": 27, ", list": 9, ", match": 30, ", numbers": 6, ", ppap": 8, ", str": 30, ", tick": 25, ", value": [6, 9], ",&": 19, ",'": [5, 9, 20, 23, 26], ",')": [5, 17], ",'+": 10, ",(": 16, ",)": [6, 10, 16], ",-": 18, ",:": 16, ",:;": 30, ",[": [16, 20], ",\\": 30, ",b": 2, ",c": 30, ",t": 30, ",y": 6, "-&": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 23, 26, 29, 30], "-'": [11, 12, 26], "-(": 30, "-(w1": 21, "--": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 23, 26, 28, 29, 30], "--&": [1, 4, 5, 8, 10, 11, 16, 17, 19, 28], "-5": 18, "-7": 16, "-\\": 30, "-a": [1, 2], "-and": [6, 9, 11], "-as": 1, "-av": 9, "-average": 9, "-b": [1, 2], "-c": [1, 2, 21, 30], "-calculator": 1, "-clauses": 9, "-comprehensions": 17, "-continue": 9, "-d": 1, "-defg": 30, "-docs": 20, "-else": 9, "-enter": 31, "-except": 12, "-existent": 4, "-f": 28, "-files": 11, "-function": 9, "-functions": [2, 10], "-g": 30, "-glr": 25, "-input": 2, "-introductory": 25, "-ipp": 6, "-iterable": 12, "-jp": 11, "-july": [13, 26], "-l": [27, 29], "-learn": [31, 32], "-list": 17, "-loops": 9, "-means": 21, "-notebook": 13, "-on": 9, "-packages": [1, 4, 11, 13, 28], "-place": [6, 32], "-printable": [1, 4], "-programming": [2, 9], "-py": 25, "-pyplot": 25, "-python": 1, "-range": 9, "-sample": [13, 30], "-separated": 26, "-sequences": 6, "-statements": [7, 9], "-steps": [2, 9], "-tab": 7, "-temps": [13, 26, 29], "-test": 11, "-tokyo": [6, 21, 30], "-towards": [2, 9], "-tutorials": 25, "-upper": 11, "-writing": 11, "-x": [18, 30], "-z": 30, "-za": 30, ".\"": [5, 30], ".&": [1, 4, 11, 13, 18, 30], ".'": [5, 7, 9, 23, 30], ".)": [13, 24, 27], ".*": 30, ".+": 16, ".,": 13, "..": [2, 3, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 18, 19, 20, 23, 24, 26, 27, 29, 30], "...": [2, 5, 6, 7, 8, 11, 13, 14, 19, 26, 27, 29, 30], "../": 13, "./": 13, ".[^": 30, ".\\": [11, 12, 19], ".]": [14, 16, 30], "._": [1, 12, 19], ".ac": [6, 21, 30], ".add": 27, ".app": 28, ".append": [6, 8, 9, 12, 26, 29, 30], ".arange": [16, 27, 29, 32], ".argv": 28, ".array": [16, 27, 29, 32], ".assign": 20, ".bak": 11, ".bar": [9, 25, 29], ".binomial": [16, 32], ".bool": [16, 32], ".break": 1, ".capitalize": 5, ".chdir": [13, 32], ".circle": 27, ".clear": 8, ".close": [11, 12, 26], ".cluster": 21, ".coef": 21, ".colab": 15, ".colorbar": 29, ".columndatasource": [27, 32], ".columns": 20, ".com": 0, ".complex": [16, 32], ".concat": 20, ".copy": [6, 8], ".core": 20, ".cos": [1, 14, 27, 29, 32], ".count": [5, 6], ".cross": 27, ".csv": [13, 20, 21, 26, 29], ".data": [21, 26], ".dataframe": 20, ".dataframegroupby": 20, ".datasets": 21, ".decomposition": 21, ".deferred": 1, ".describe": 20, ".dot": [16, 32], ".dtype": 16, ".e": 14, ".ecc": 30, ".exp": 29, ".extend": 6, ".fact": [15, 28], ".factorial": 14, ".figure": [27, 32], ".find": 5, ".findall": 30, ".finditer": 30, ".fit": 21, ".flat": 16, ".flip": 29, ".float": [16, 20, 21, 32], ".floor": 14, ".flush": 1, ".gauss": 9, ".generic": 20, ".get": 8, ".getvalue": 1, ".go": 26, ".google": 0, ".grid": 29, ".group": 1, ".groupby": 20, ".gz": 16, ".he": 21, ".head": [20, 21], ".hist": 29, ".histogram": [27, 32], ".href": 30, ".html": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 26, 27, 28, 30], ".i": [30, 32], ".identity": [16, 32], ".ignorecase": [30, 32], ".iloc": 20, ".imshow": 29, ".index": [5, 6, 20], ".insert": 6, ".int": [16, 32], ".intercept": 21, ".io": [0, 22], ".ipynb": [13, 15], ".items": 8, ".j": 16, ".jma": 26, ".join": 6, ".jp": [6, 21, 26, 30], ".keys": [8, 25], ".legend": 29, ".linalg": [16, 32], ".line": [9, 27], ".linear": 21, ".linearcolormapper": [27, 32], ".lines": 9, ".linspace": [16, 21, 26, 32], ".lmplot": 21, ".loadtxt": [16, 32], ".loc": 20, ".log": 14, ".lower": [5, 30], ".match": 30, ".matmul": [16, 32], ".max": [1, 27], ".merge": 20, ".metrics": 21, ".min": 27, ".model": 21, ".models": [27, 32], ".modules": 15, ".n": 19, ".natcorp": 30, ".ndarray": [16, 32], ".ndenumerate": 16, ".ndim": 16, ".newaxis": 21, ".newline": 1, ".norm": [16, 32], ".ones": [14, 16, 32], ".org": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 23, 25, 26, 27, 28, 29], ".output": [27, 32], ".ox": 30, ".palettes": 27, ".pi": [1, 14, 27, 29, 32], ".plot": [9, 21, 25, 26, 29], ".plotting": [27, 32], ".png": [13, 29], ".poisson": [16, 32], ".poly": 26, ".polyfit": 26, ".pop": [6, 8], ".predict": 21, ".pretty": 1, ".py": [1, 4, 11, 13, 15, 28], ".pydata": [20, 27], ".pyplot": [9, 21, 25, 26, 29], ".python": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 17, 18, 19, 23, 26, 28, 30], ".quad": 27, ".rand": [20, 27, 29, 32], ".randint": [24, 27, 29], ".randn": [16, 27, 29, 32], ".random": [16, 20, 27, 29, 32], ".ravel": 16, ".read": [11, 13, 20, 21, 30], ".reader": [26, 29, 32], ".readline": [11, 12, 19], ".readthedocs": [0, 22], ".rect": 27, ".remove": [6, 30], ".replace": [5, 9, 23], ".representationprinter": 1, ".research": 0, ".reset": [27, 32], ".reshape": 16, ".reverse": 6, ".rstrip": 11, ".s": 19, ".savefig": 29, ".savetxt": [16, 32], ".scatter": [21, 25, 27, 29], ".scipy": 16, ".search": 30, ".series": 20, ".set": 1, ".setdefault": 8, ".shape": 16, ".show": [25, 26, 27, 32], ".sin": [1, 14, 27, 29, 32], ".singleton": 1, ".size": 16, ".sort": [6, 16, 20, 30, 32], ".split": [6, 9, 32], ".splitlines": 1, ".sqrt": [1, 2, 14, 16, 32], ".sre": 30, ".sub": 30, ".sum": 16, ".t": 16, ".target": 21, ".textiowrapper": 13, ".title": 29, ".transform": [21, 27], ".txt": [4, 11, 12, 13, 18, 30], ".type": 1, ".u": [6, 21, 30], ".uk": 30, ".upload": 15, ".upper": [5, 6, 11], ".values": [8, 25], ".vbar": 27, ".verbose": 1, ".write": 11, ".writer": [26, 32], ".writerow": 26, ".xlabel": 29, ".xml": [13, 30], ".ylabel": 29, ".zeros": [16, 29, 32], ".\u300d": 14, "/ b": 16, "/ n": 27, "/&": 30, "/'": 30, "/(": 30, "/)&": 18, "/..": 13, "//": [1, 9, 24], "/appendix": 28, "/basics": 16, "/bin": 28, "/classes": [12, 19], "/compound": 3, "/controlflow": [2, 3, 7, 9, 10], "/core": [1, 4, 11, 13], "/courses": 21, "/csv": 26, "/datamodel": 19, "/datastructures": [6, 8, 17, 23], "/dd": 30, "/doc": 16, "/en": [0, 22], "/env": 28, "/errors": 4, "/folders": 30, "/formatters": 1, "/functional": 18, "/functions": 2, "/getting": [20, 21], "/gmd": 26, "/import": [14, 15, 28], "/index": [20, 21], "/inputoutput": 11, "/interactiveshell": [4, 11, 13], "/interpreter": 28, "/introduction": [1, 2, 5, 6, 9], "/introductory": 25, "/ipykernel": [28, 30], "/ipython": [1, 4, 11, 13], "/ja": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 17, 18, 19, 23, 26, 28], "/jmori": 28, "/latest": [0, 22], "/len": 9, "/lib": [1, 4, 11, 13, 28], "/math": [1, 14], "/modules": [1, 14, 15, 28], "/n": 17, "/novel": [11, 13], "/numeric": 1, "/numpy": 16, "/obsdl": 26, "/pandas": 20, "/pretty": 1, "/projects": 28, "/pyplot": 25, "/python": [1, 4, 11, 13, 28], "/quickstart": 16, "/re": 30, "/risk": 26, "/sample": 13, "/sec": 30, "/stable": [20, 21], "/stdtypes": [3, 12], "/sys": 28, "/t": 30, "/text": 13, "/tutorial": 21, "/tutorials": 25, "/user": 16, "/users": 28, "/utpython": [1, 4, 11, 13, 28], "/y": 1, "/z": 1, "0d": 30, "0k": 30, "0to": 30, "0x": [9, 11, 18, 19, 20, 30], "0\u304b": 5, "10": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 21, 23, 26, 27, 29, 30], "11": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 21, 23, 26, 27, 29, 30], "12": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 21, 23, 26, 27, 29, 30], "12\u6708": 29, "13": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 21, 23, 26, 27, 29, 30], "14": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 21, 23, 26, 27, 29, 30], "15": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 21, 23, 26, 27, 29, 30], "16": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 23, 26, 27, 29, 30], "17": [1, 2, 3, 5, 6, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 23, 26, 27, 29, 30], "18": [1, 2, 3, 5, 6, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 23, 26, 29, 30], "19": [1, 2, 3, 5, 6, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 23, 26, 29, 30], "1]": 9, "1d": [26, 27], "1e": 1, "1f": 27, "1grw": 30, "1s": [13, 30], "1st": 25, "1to": 30, "1\u305a": 0, "1\u3064": [1, 2, 4, 5, 6, 7, 9, 11, 12, 17, 19, 21, 23, 24, 26, 28, 30], "1\u30d0\u30a4\u30c8": 1, "1\u6708": 29, "1\u6b21": 16, "1\u884c": [6, 7, 11, 26, 29], "2abcd": 30, "2b": 18, "2c": 30, "2d": [9, 21, 30], "2e": 27, "2m": 24, "2nd": 25, "2sld": 30, "2x": [16, 30], "2\u3064": [1, 3, 4, 5, 6, 7, 9, 11, 16, 20, 21, 23, 25, 29, 30], "2\u4e57": 16, "2\u91cd": 17, "2\u9805": 1, "30": 6, "3xx": 30, "3\u3064": [4, 6, 9, 10, 17, 21, 27, 28, 30], "47": 29, "4ac": 2, "4e": 30, "4n": 30, "4str": 30, "4\u3064": [4, 7, 16, 20, 21, 29], "53": 29, "5ax": 30, "5b": 30, "5f": 30, "5t": 30, "5x": 30, "5yxcx": 30, "5\u3064": 29, "6g": 30, "6\u6708": 29, "7a": 30, "7b": 27, "7d": 30, "7\u6708": [29, 32], "8b": 30, "9c": 30, "9d": 27, ":#": [5, 9], ":&": [6, 30], ":'": [5, 6, 9, 12, 20, 23, 28, 29, 30], ":,": 16, ":-": [5, 16], ":/": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30], "::": 6, ":[a": 30, ":]": [5, 16, 20, 24, 27, 28], ":bbb": 30, ":ccc": 30, ":ddd": 30, ":hello": 5, ":j": 17, ":len": 17, ":mm": 30, ":world": 5, ":y": 6, ":\u300d": 30, ";&": [1, 5, 7, 11, 13, 19, 30], ";'": [5, 9, 23], ";(": [18, 30], ";)": [4, 5, 6, 7, 8, 10, 11, 12, 13, 30], ";*": 30, ";-": 28, ";.": 30, ";:": [4, 8, 9, 10, 11, 17, 19, 30], ";=": 4, ";@": 30, ";[": 30, ";\\": 30, ";]": [4, 6, 8, 9, 12, 17, 18, 19, 24, 26, 30], ";^": 30, ";_": [13, 19, 26], ";barcontainer": 9, ";frozen": 11, ";function": 18, ";lambda": 18, ";map": 18, ";matplotlib": 9, ";pandas": 20, ";re": 30, ";|": 30, ";}": [10, 17, 23], ";\u260e": 30, "< '": 5, "\"": 30, ">'": 30, ">(": 30, ">=": [3, 4, 26], ">>": 28, ">\\": 30, ">\\\"": 30, ">]*": 30, ">n": 18, "?\"": 30, "?&": 30, "?'": [5, 9, 23, 30], "?=": 30, "?\\": 30, "?r": 30, "@'": [6, 30], "@ipp": 6, "@test": 30, "@utokyo": 6, "[&": [6, 8, 9, 12, 17, 18, 24, 26, 30], "['": [6, 8, 9, 10, 13, 17, 19, 20, 21, 27, 30], "['a": [6, 9], "['b": 20, "['x": 6, "[(": [8, 16, 20, 21], "[-": [5, 16, 18, 20], "[.": 30, "[1": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30], "[2": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30], "[3": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30], "[4": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30], "[5": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30], "[6": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30], "[7": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, 18, 19, 20, 21, 23, 24, 26, 27, 28, 29, 30], "[8": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 17, 18, 19, 20, 21, 23, 24, 26, 27, 29, 30], "[9": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 21, 23, 26, 27, 29, 30], "[:": [5, 9, 16, 20, 21, 24, 27], "[[": [6, 9, 14, 16, 17, 20, 21, 26], "[['": 20, "[]": 6, "[^": 30, "[^<": 30, "[^>": 30, "[^@": 30, "[^a": 30, "[a": [6, 16, 30], "[a*]": 30, "[abc": 30, "[abcdefg": 30, "[abs": 18, "[b": 6, "[chr": 17, "[cls": 1, "[d": 30, "[gcdbeaf": 30, "[i": [9, 17, 24, 26, 27, 29], "[i1": [24, 27, 29], "[i2": [24, 27, 29], "[int": 5, "[j": 9, "[k": 18, "[ord": 9, "[sd": 30, "[value": 9, "[w": 9, "[word": 30, "[x": [6, 17, 18], "[y": [6, 29], "\\\"": [5, 30], "\\'": 5, "\\(": 30, "\\(a": 30, "\\)": 30, "\\*": 30, "\\+": 30, "\\.": 30, "\\\\": 30, "\\\\\\": 30, "\\d": [30, 32], "\\ge": 16, "\\n": [5, 11, 30], "\\nc": 6, "\\nworld": 11, "\\pi": [27, 29], "\\r": 11, "\\s": [30, 32], "\\sum": 9, "\\t": [5, 11, 30, 32], "\\times": 16, "\\u": 30, "\\w": [30, 32], "\\|": 30, "]\nb": 6, "]\nx": 21, "] #": 6, "]$": 30, "]'": 30, "](": [1, 30], "])": [5, 6, 7, 8, 9, 10, 12, 16, 17, 18, 20, 23, 24, 26, 27, 28, 29, 30], "]*": [6, 9, 24, 27, 29, 30], "]+": [9, 30], "],": [3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 16, 17, 20, 26, 27, 28, 29], "]-": 30, "].": [9, 20, 21], "]:": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], "]=": 9, "][": [6, 8, 9, 17, 29, 30], "]]": [6, 9, 16, 17, 18, 20, 26], "]e": 30, "]{": 30, "]|": 30, "]}": 8, "^>": 30, "^@": 30, "^a": 30, "^abc": 30, "^bcdef": 30, "^ef": 30, "^{": 29, "_(": 1, "_)": 16, "_[": 21, "_]": 30, "__": [1, 12, 18, 19, 26, 28, 32], "_abs": 18, "_acgt": 30, "_acgtstr": 30, "_air": 2, "_atgc": [5, 6], "_augc": 9, "_axis": 27, "_bar": 27, "_big": 18, "_bpcnt": 6, "_bpname": 5, "_bppair": 5, "_browser": 13, "_c": 21, "_capitalletters": 9, "_characters": [11, 23], "_class": 1, "_clause": 5, "_clusters": 21, "_codonnum": 9, "_codons": 9, "_collision": [8, 9], "_colon": 5, "_color": 27, "_commas": 9, "_components": 21, "_conv": 13, "_count": [5, 6, 9], "_countlist": 6, "_csv": [20, 21, 32], "_d": [8, 20], "_dash": 27, "_day": 30, "_deferred": 1, "_dic": 17, "_dicsize": 23, "_dict": [10, 30], "_difference": 23, "_digits": 1, "_dna": 5, "_domain": 6, "_double": 5, "_edges": 27, "_engsentence": 9, "_engsentences": [5, 9, 23, 30], "_engwords": 9, "_enter": [19, 32], "_error": 21, "_escaped": 5, "_even": 3, "_evenindex": 6, "_ex": 26, "_exit": [19, 32], "_exp": 29, "_extension": 30, "_file": [27, 30, 32], "_first": 12, "_fruits": 6, "_function": 24, "_global": 10, "_hour": 30, "_in": 13, "_index": [5, 20, 32], "_init": [19, 32], "_int": 1, "_ip": 30, "_ipv": 30, "_iris": [20, 21], "_irist": 21, "_iter": [12, 19, 32], "_jis": [11, 13, 26, 28], "_key": 18, "_km": 21, "_label": [9, 25, 27], "_launcher": 28, "_layout": 27, "_len": 20, "_lengh": 21, "_length": [1, 20, 21], "_line": [11, 12], "_lines": 18, "_list": [6, 9, 10, 17, 30], "_lists": [9, 17], "_local": 10, "_long": 18, "_lookup": [8, 9], "_lower": 5, "_lsearch": 9, "_mac": 13, "_main": 19, "_mapper": 27, "_match": [9, 30], "_matrix": [9, 16, 17, 26], "_max": 1, "_menu": 13, "_min": 30, "_model": 21, "_month": 30, "_monthday": 30, "_monthdaystr": 30, "_months": 29, "_monthstr": 30, "_mro": 1, "_n": 9, "_name": [28, 32], "_next": [12, 19, 32], "_notebook": [27, 32], "_num": 27, "_numbers": 18, "_odd": 3, "_of": [11, 13, 18], "_open": [4, 11, 13], "_output": [27, 32], "_pair": 5, "_plot": 21, "_pos": 30, "_postalcode": 30, "_pprint": 1, "_pprinters": 1, "_predicted": 21, "_printers": 1, "_punctuation": 9, "_punctuations": 5, "_py": 13, "_quated": 5, "_rdic": 17, "_rec": [24, 27, 29], "_reg": 21, "_res": 5, "_row": 29, "_score": 21, "_script": 30, "_selection": 21, "_seq": 1, "_set": 17, "_sin": 29, "_single": 5, "_size": [9, 21], "_sort": [24, 27, 29], "_split": 21, "_square": 16, "_squared": 21, "_sre": 30, "_started": [20, 21], "_state": 21, "_stmts": 3, "_str": [1, 9, 30], "_strings": 9, "_subclass": 26, "_sum": 6, "_temperature": 2, "_temps": [26, 29], "_terms": 13, "_test": 21, "_text": 5, "_textbook": 13, "_ticks": 27, "_time": 30, "_timestr": 30, "_tokyotemps": 29, "_totuple": 6, "_train": 21, "_type": 19, "_types": 1, "_upper": 11, "_value": [18, 19], "_values": [20, 32], "_variable": 4, "_wid": 20, "_width": [1, 20, 21, 27], "_win": 13, "_words": 23, "_x": 29, "_years": 29, "_{": 9, "`)": 29, "`;": 29, "`\uff09": 30, "a1": [6, 16, 28], "a1b": 30, "a5bab": 27, "aa": [5, 9, 24, 30], "aaa": [17, 30], "aaaaaa": 30, "aab": 24, "aabbcc": 30, "aabc": 24, "aabcc": 24, "aabccc": 23, "aabdceabdae": 23, "aagccccatggtaa": [5, 6], "ab": [5, 17, 30], "ababc": 30, "ababcd": 30, "abb": 30, "abbb": 30, "abc": [5, 6, 9, 17, 19, 30], "abcc": 24, "abcd": 6, "abcde": 30, "abcdef": 30, "abcdefg": 30, "abcdefgh": 30, "abcdefxyz": 30, "abcdefxyzdef": 30, "abd": [5, 30], "abe": 30, "above": 22, "abs": [3, 18, 26], "ac": 30, "acaacgta": 30, "acaba": 23, "access": [4, 10], "accgtagcacatcggaaattgcact": 30, "accountname": 30, "accuracy": 21, "acd": 30, "acdb": 12, "acdf": 30, "acgt": 30, "ackroyd": 9, "across": 23, "act": 9, "ad": [11, 12, 13], "add": [9, 32], "ade": 30, "adipiscing": [11, 12, 13], "adriatic": 23, "after": [4, 6, 9, 16], "ah": 30, "aliqua": [11, 12, 13], "aliquip": [11, 12, 13], "all": [5, 6], "allsubstrings": 17, "almost": 30, "alpha": [27, 29], "alt": 5, "amet": [11, 12, 13], "an": [4, 6, 9, 16, 23, 30], "anaconda": 28, "anaonda": 28, "and": [1, 2, 3, 6, 9, 16, 20, 26, 27, 29, 30, 31, 32], "anim": [11, 12, 13], "ans": 29, "anthing": 30, "app": 28, "append": [6, 9, 17, 32], "appendix": [13, 32], "apple": [6, 8, 9, 23, 25, 30], "apples": 30, "application": 28, "arange": [27, 29, 32], "are": [4, 7, 11, 13, 30], "aren": 5, "arg": 28, "args": [4, 10, 11, 13], "argsprint": [13, 28], "argument": [10, 32], "argv": 28, "array": 16, "artists": 9, "ary": 29, "aryx": 29, "aryy": 29, "as": [4, 9, 11, 12, 13, 15, 16, 18, 19, 20, 21, 25, 26, 27, 29, 30, 31, 32], "ascending": [20, 32], "ascii": 16, "assert": [2, 3, 12, 31, 32], "assertionerror": [2, 3, 4, 12], "assign": [16, 20, 32], "assignment": [2, 5, 32], "associated": [4, 10], "astype": 21, "at": [4, 9, 18, 19, 20], "atgc": [5, 6], "attribute": [19, 30], "attributeerror": [19, 30], "augmented": [2, 32], "aute": [11, 12, 13], "auxiliary": 5, "av": [9, 17], "average": [9, 10], "ax": 2, "axis": [20, 29, 32], "a\u4e00\u6587\u5b57": 30, "ba": 6, "bacaad": 30, "baltic": 23, "banana": [6, 8, 25, 30], "bar": [2, 29, 32], "base": [24, 28], "bash": 28, "basicticker": 27, "bbacbabbbbc": 30, "bbb": [17, 30], "bc": [17, 30], "bcc": 24, "bcdef": 30, "bdata": [27, 29], "be": [7, 27], "being": 5, "below": 22, "better": 30, "big": 9, "bin": 27, "bins": 29, "bit": [16, 28], "black": 9, "blank": [5, 30], "block": [4, 6, 9], "blue": [9, 27, 29], "bmax": [3, 7], "bmi": 2, "bo": 30, "body": 30, "bokeh": [13, 27, 32], "bokehdeprecationwarning": 27, "bokehjs": 27, "bonjour": 10, "boo": [2, 20, 30], "boooo": 30, "booooo": 30, "booooooo": 30, "bottom": 27, "bp": 6, "brandy": 8, "break": [11, 31, 32], "brown": 17, "bubble": [27, 29], "builtins": [4, 11, 13], "but": [5, 7, 12, 30], "bx": 2, "by": [1, 4, 11, 13], "byte": 11, "c1": 20, "ca": 30, "call": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 23, 26, 28, 29, 30], "called": 18, "can": [4, 11, 13, 16], "cannot": [4, 10], "capitalize": [5, 32], "car": 30, "carpet": [9, 30], "castanets": 30, "cat": [8, 9, 17, 30], "category": [9, 27, 30], "cattle": 30, "cc": 24, "cc7": 27, "ccc": [9, 17, 30], "cccccggcacct": 9, "ccg": 9, "ccnt": 9, "cct": 9, "cd": [28, 30], "cde": 30, "cell": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 23, 26, 28, 29, 30], "change": 6, "character": [1, 4], "characters": 6, "check": [5, 23, 30], "checkpoint": 22, "chelly": 6, "chicken": 8, "chr": [9, 32], "cillum": [11, 12, 13], "circle": [27, 32], "class": [19, 26], "clear": [8, 32], "close": [11, 32], "clouds": 9, "cls": 1, "cluster": 21, "cm": 2, "cmd": [0, 22], "coast": 5, "code": [21, 22], "codec": 11, "codecs": 11, "code\u30bb\u30eb": [0, 1, 2, 7, 15, 22, 25], "coding": 28, "coffee": 8, "col": 5, "colab": [13, 31], "colaboratory": [7, 13, 15, 31], "colabratory": 0, "collect": 9, "colo": 30, "color": [9, 27, 29, 30], "colorbar": [27, 29], "colormap": 21, "colors": [9, 27], "colou": 30, "colour": 30, "columndatasource": 27, "columns": 20, "come": 23, "comma": 26, "command": [13, 32], "commodo": [11, 12, 13], "comparisons": [27, 29], "complex": [26, 32], "concat": [20, 32], "consectetur": [11, 12, 13], "consequat": [11, 12, 13], "console": 13, "construct": 9, "contains": 28, "continent": 23, "continue": [31, 32], "conversion": 1, "copy": [0, 8, 22, 32], "cos": [1, 14, 27, 29], "count": [5, 6, 9, 20, 23, 32], "crash": [4, 11, 13], "cross": [27, 32], "csv": [13, 29, 31, 32], "ctrl": [0, 22], "culpa": [11, 12, 13], "cupidatat": [11, 12, 13], "current": 15, "curried": 8, "curtain": 23, "curves": [27, 29], "cut": [0, 22], "cycle": 1, "d1": 9, "d10": 9, "d3": 27, "dashed": 27, "data": [11, 13, 21, 24, 27, 29], "dataframe": [31, 32], "dataframegroupby": 20, "datareader": [26, 29], "datawriter": 26, "day": 30, "dd": 30, "ddb": 27, "ddd": 30, "de": [10, 30], "decode": 11, "def": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 23, 24, 26, 27, 28, 29, 30, 32], "defabcxyz": 30, "default": [4, 11, 13], "deferred": 1, "defg": 30, "defined": [2, 4, 7, 10, 17, 29, 30], "definition": 4, "del": [6, 7, 8, 20, 32], "delattr": 26, "delimiter": 16, "deprecated": 27, "descended": 23, "describe": [20, 32], "deserunt": [11, 12, 13], "detected": [4, 16], "dfccce": 27, "dialect": 26, "dic": [8, 9, 23, 30], "dict": 8, "dictionary": [31, 32], "difference": 32, "different": 7, "digits": [1, 5], "dimensions": 16, "dir": 26, "directory": [4, 11, 13, 15], "discard": 32, "division": [1, 4], "dna": 5, "do": [9, 11, 12, 13], "doc": 26, "docs": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 23, 26, 28, 30], "does": 5, "doesn": 30, "dog": [8, 9, 17, 30], "doing": [4, 11, 13], "dolor": [11, 12, 13], "dolore": [11, 12, 13], "domain": 6, "don": 30, "donation": 5, "donations": 5, "doors": 5, "dot": 32, "dotted": 27, "doublequated": 5, "down": 5, "downloads": 28, "dozens": 8, "drive": 0, "drop": [20, 32], "dst": 11, "dtype": [16, 20, 29], "duis": [11, 12, 13], "during": 6, "ea": [11, 12, 13], "eccs": 0, "edgware": 9, "edit": 22, "efa": 9, "effect": 30, "efg": 30, "egg": 8, "eiusmod": [11, 12, 13], "element": 16, "elems": 16, "elephant": [8, 9, 17], "elf": 21, "elif": [9, 24, 27, 29, 31, 32], "elit": [11, 12, 13], "else": [1, 3, 8, 18, 24, 27, 29, 30, 31, 32], "email": 6, "empty": [6, 8], "emptyfile": 19, "en": 10, "encoding": [11, 12, 13, 18, 20, 26, 29, 30, 32], "end": [9, 11, 29], "enim": [11, 12, 13], "enter": [0, 1, 19, 22], "enumerate": [16, 31, 32], "env": 28, "eq": 26, "equal": [7, 9], "errno": [4, 11, 13], "error": [4, 9, 26, 27], "esc": 22, "escape": 30, "escaped": 5, "esse": [11, 12, 13], "est": [11, 12, 13], "et": [11, 12, 13], "eu": [11, 12, 13], "euc": 11, "evening": 30, "ex": [11, 12, 13], "example": 7, "exceeds": 1, "excel": 26, "except": 12, "excepteur": [11, 12, 13], "exception": [7, 19], "execution": 27, "exercitation": [11, 12, 13], "exit": 19, "exp": 29, "expected": [4, 6, 9], "expression": 30, "expt": 24, "extend": [6, 32], "fa": 30, "fact": [14, 15, 28], "factorial": [13, 14, 15, 28], "false": [3, 5, 6, 7, 8, 9, 11, 16, 17, 18, 20, 23, 24, 26, 27, 29, 30, 32], "fd": [4, 11, 13], "felt": 2, "fgadeab": 30, "fgdeab": 30, "fgtgh": 30, "fib": 3, "fig": 13, "figure": 27, "file": [1, 4, 11, 13, 18, 22, 30], "filenotfounderror": [4, 11, 13], "files": 15, "fill": 27, "filter": [31, 32], "final": 11, "find": [1, 5, 6, 30, 32], "findall": 32, "finder": 11, "finditer": 32, "fine": 30, "finish": 9, "first": 29, "firstvalue": 28, "fit": [21, 32], "fitp": 26, "flatten": [16, 32], "float": [1, 2, 5, 20, 26, 29, 32], "fmatch": 9, "foo": [2, 20], "for": [1, 2, 8, 15, 17, 18, 19, 24, 27, 28, 29, 30, 31, 32], "force": 2, "format": 26, "formatter": 27, "found": 5, "four": 9, "fr": 10, "from": [9, 15, 21, 23, 24, 27, 29, 31, 32], "fruits": 6, "fugiat": [11, 12, 13], "func": 5, "function": [1, 4, 10], "gca": 9, "ge": 26, "get": [1, 8, 9, 30, 32], "getattribute": 26, "getstate": 26, "giraffe": [17, 30], "global": 32, "glossary": 12, "gn": 30, "good": 30, "google": [0, 15], "graph": 29, "greater": 7, "green": [9, 27, 29], "greet": 10, "greeting": 10, "grid": [29, 32], "group": 32, "groupby": [20, 32], "gt": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 23, 26, 28, 29, 30], "guard": 5, "guten": 10, "gzip": 16, "ha": 30, "had": 30, "hall": 5, "ham": 8, "handle": [8, 9], "has": [16, 19, 23, 30], "hash": 26, "have": 30, "he": [5, 30], "head": [20, 32], "heat": 29, "height": [2, 9], "hello": [5, 6, 7, 10, 11, 18, 19, 30], "hellofile": 19, "hellofileiterator": 19, "helloforever": 19, "hellohello": 10, "hellohellohello": [5, 10], "hellooooo": 30, "here": 21, "heron": 2, "hh": 30, "hi": [9, 10, 30], "him": 30, "hist": [27, 29, 32], "hit": 30, "hour": 30, "house": 9, "how": 30, "howto": 18, "href": 30, "html": [0, 27, 30], "http": [20, 26, 30], "https": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 27, 28, 29, 30], "hue": 21, "humidity": 2, "hundreds": 8, "hw": 30, "i1": [24, 27, 29], "i2": [24, 27, 29], "id": [11, 12, 13, 26], "identify": 9, "idx": 16, "if": [1, 4, 5, 6, 8, 9, 11, 13, 15, 17, 18, 19, 24, 26, 27, 28, 29, 30, 31, 32], "if\u6587": [3, 7], "ignore": 20, "iii": 9, "iloc": 32, "im": 29, "ime": 5, "import": [1, 2, 9, 13, 14, 15, 16, 20, 21, 24, 25, 26, 27, 28, 29, 30, 32], "impshow": 29, "imshow": 29, "in": [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32], "incididunt": [11, 12, 13], "increase": 1, "indentationerror": [4, 6, 9], "indented": [4, 6, 9], "index": [5, 6, 8, 13, 20, 32], "indexerror": 5, "infile": 11, "inhomogeneous": 16, "init": [19, 26, 29], "initial": 20, "inline": [21, 25, 26, 29], "inplace": [20, 32], "input": 11, "insert": [6, 32], "insert\u30e1\u30cb\u30e5\u30fc": 1, "instead": 27, "int": [1, 5, 6, 9, 17, 20, 26, 28, 29, 30, 32], "integer": 1, "intersection": 32, "invalid": [1, 4, 5, 11, 14, 28, 29, 30], "invert": 18, "io": [4, 11, 13], "ip": 30, "ipp": [6, 13], "ipsum": [11, 12, 13], "ipv4": 30, "ipynb": [0, 13, 22], "ipython": [2, 4, 11, 13], "iris": [13, 20, 21], "iron": 23, "irure": [11, 12, 13], "is": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 17, 19, 23, 29, 30, 32], "it": [4, 5, 9, 10, 11, 12, 13, 17, 18, 30], "itarator": 12, "item": [5, 9], "items": [9, 27, 29, 32], "iter": [19, 30, 31, 32], "iterable": [6, 12, 16], "iterate": 12, "itms": 8, "itr": 30, "james": 30, "japan": 10, "jis": 5, "jklm": 30, "john": [9, 30], "join": [6, 32], "jp": 30, "jugemu": [13, 18], "july": 26, "jupyter": [0, 13, 15, 22], "just": 1, "kernel": 22, "key": [8, 9, 18, 30, 32], "keyerror": [4, 8, 23], "keys": [9, 32], "kg": 2, "kick": 9, "king": 9, "kiwi": [8, 25], "kmeans": [21, 32], "kmk": 28, "know": [4, 11, 13, 30], "ks": 8, "kwargs": [4, 10, 11, 13], "label": [25, 29], "labels": 9, "labore": [11, 12, 13], "laboris": [11, 12, 13], "laborum": [11, 12, 13], "lambda": [18, 32], "larger": [7, 9], "last": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 23, 26, 28, 29, 30], "latin": 16, "lbfgs": 21, "ld": 8, "le": 26, "lear": 9, "left": [9, 27], "legend": [27, 29, 32], "len": [5, 6, 8, 9, 10, 11, 16, 17, 18, 20, 23, 24, 27, 28, 29, 32], "lengend": 29, "length": [17, 20], "less": 7, "let": [4, 11, 13], "library": [1, 2, 3, 12, 14, 26, 28, 30], "license": 13, "likely": [4, 11, 13], "limit": 1, "line": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 26, 27, 28, 29, 30, 32], "linear": [27, 29], "linearcolormapper": 27, "linearregression": [21, 32], "lines": [1, 12], "linestyle": 29, "link": 9, "linspace": 32, "linux": [11, 13], "list": [8, 9, 12, 16, 17, 18, 23, 27, 30, 31, 32], "list1": 17, "literal": [4, 28], "little": 9, "ln": [6, 9, 18], "ln1": 9, "ln2": [6, 9], "lns": 6, "lo": 5, "load": 21, "loading": 27, "loadtxt": 16, "loc": [29, 32], "local": [4, 10], "locate": 30, "location": [9, 27], "locked": 5, "log": 14, "logisticregression": [21, 32], "loop": 6, "lorem": [11, 12, 13], "low": 27, "lower": [5, 9, 32], "ls": [6, 8, 18, 25], "ls1": 25, "ls2": 25, "lst": [9, 17, 27, 29], "lstrip": 5, "lt": [9, 11, 18, 26, 30], "m1": 30, "ma": 26, "macos": [5, 11, 13], "magna": [11, 12, 13], "main": [18, 19, 28], "make": 5, "map": [31, 32], "mapper": 27, "mapping": 9, "mar": 23, "markdown": 22, "markdown\u30bb\u30eb": [0, 15, 22], "marker": [27, 29], "match": [30, 32], "matches": 30, "materials": 28, "math": [1, 2, 14, 32], "matoplotlib": 29, "matplotlib": [9, 13, 21, 26, 29, 31, 32], "max": [1, 3, 20, 26, 31, 32], "mdata": [27, 29], "me": [5, 30], "mean": [20, 21, 32], "median": 4, "merge": [20, 24, 27, 29, 32], "method": 27, "mi": 26, "midsummer": 9, "min": [20, 26, 32], "mine": [5, 30], "minim": [11, 12, 13], "minute": 30, "mm": 30, "mod": 28, "mode": 13, "model": 21, "modified": [4, 11, 13], "module": [2, 26], "mollit": [11, 12, 13], "mon": 30, "money": 5, "month": [29, 30], "months": 29, "month\u6708": 29, "more": 9, "morning": 30, "most": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 23, 26, 28, 29, 30], "mouse": 9, "my": 29, "mybin": 29, "mycolumn": 20, "myiris": 20, "myitem": 9, "n1": [24, 27, 29], "n2": 24, "name": [2, 4, 7, 10, 11, 12, 13, 17, 20, 28, 29, 30], "nameerror": [2, 4, 7, 10, 17, 29, 30], "nclick": 30, "ndarray": 16, "nduis": 11, "ne": 26, "negative": 7, "negatives": 7, "new": [22, 26, 28], "newline": 26, "newlines": 1, "nexcepteur": 11, "next": [18, 19, 26, 31, 32], "ng": 3, "nisi": [11, 12, 13], "no": [4, 9, 11, 13, 19, 30], "non": [1, 4, 5, 11, 12, 13], "none": [2, 5, 6, 7, 8, 9, 10, 17, 30, 31, 32], "nonetype": [2, 6, 30], "normal": 1, "nostrud": [11, 12, 13], "not": [2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 17, 20, 23, 29, 30, 32], "notebook": [0, 15, 31], "notip": 30, "novel": [11, 13], "np": [14, 16, 20, 21, 27, 29], "ntime": 5, "nulla": [11, 12, 13], "num": 28, "numargs": 28, "number": [10, 11, 18, 27, 29, 30], "numbers": [6, 8, 30], "numpy": [14, 20, 21, 26, 27, 29, 31, 32], "obj": 1, "object": [5, 6, 9, 19, 20, 23, 30], "observing": 5, "occaecat": [11, 12, 13], "of": [2, 5, 9, 27, 28, 29, 30], "officia": [11, 12, 13], "ok": [3, 5], "on": [4, 6, 9, 18, 20, 30, 32], "onde": 23, "ones": 32, "online": 4, "only": [16, 25], "onlyone": 6, "open": [4, 11, 12, 13, 18, 26, 29, 30, 32], "operand": 2, "or": [3, 4, 6, 9, 11, 13, 16, 20, 26, 31, 32], "orange": [8, 9, 23, 25], "ord": [9, 17, 32], "orient": 9, "orig": [8, 9], "os": [11, 13, 32], "os\u4e0a": 13, "othello": 9, "out": [5, 26], "outfile": 11, "output": [1, 27], "palette": 27, "pandas": [16, 21, 27, 31, 32], "parameter": [10, 32], "pariatur": [11, 12, 13], "part": 16, "pass": [0, 12, 19, 22, 31, 32], "paste": [0, 22], "pca": [21, 32], "pd": [20, 21], "peck": 30, "pen": [6, 8, 9, 23], "pep": [4, 5, 7, 32], "pep8": 4, "peppers": 30, "petal": [20, 21], "peter": 30, "pets": [8, 30], "pi": [14, 27, 29], "picked": 30, "pickled": 30, "piece": 30, "pinapple": 8, "pineapples": 30, "piper": 30, "plaintextformatter": 1, "play": 30, "please": 30, "plot": [25, 29, 32], "plt": [9, 21, 25, 26, 29], "plutonium": 9, "png": [13, 27], "point": 6, "pop": [6, 8, 32], "port": 8, "pos": [18, 30], "position": 11, "positive": [7, 9], "positives": 6, "power": 24, "powershell": 28, "ppap": 8, "pprint": 1, "predict": [21, 32], "prefixes": 24, "pretty": 1, "price": 5, "print": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 23, 26, 28, 29, 30, 31, 32], "printer": 1, "printftickformatter": 27, "proclaim": 30, "prod": [15, 28], "proident": [11, 12, 13], "projects": [1, 4, 11, 13], "prompt": 28, "pron": 30, "py": [13, 15, 28, 30], "pycodestyle": 4, "pyplot": 29, "python": [0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 25, 26, 28, 30, 32], "pythontest": 28, "quad": [27, 29, 32], "quadratic": 27, "que": 9, "qui": [11, 12, 13], "quick": 17, "quiet": 5, "quis": [11, 12, 13], "rained": 30, "rainy": 30, "raise": [4, 11, 13, 19, 32], "random": [9, 21, 24, 27, 29, 32], "range": [5, 12, 15, 16, 17, 24, 26, 27, 28, 29, 31, 32], "rangeindex": 20, "ravel": [16, 32], "re": [13, 32], "read": [11, 20, 32], "readline": [11, 12, 19, 32], "recent": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 23, 26, 28, 29, 30], "rect": 27, "recursion": [13, 32], "recursive": 24, "red": 9, "redirects": 1, "reduce": 26, "reference": [3, 14, 15, 19, 28], "reg": 30, "registered": 1, "remove": [5, 6, 32], "removed": 27, "replace": [1, 5, 23, 32], "repr": [1, 26], "reprehenderit": [11, 12, 13], "representationprinter": 1, "requested": 16, "requires": 9, "res": 29, "reset": 27, "reshape": [16, 20, 29, 32], "result": 8, "return": [1, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, 19, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32], "reverse": [6, 8, 9, 18, 32], "richard": 9, "right": 27, "round": [2, 5], "row": [16, 20, 26, 29], "rows": 26, "rstrip": [5, 11], "sample": [11, 12, 13, 28], "sato": 28, "save": 27, "savefig": [29, 32], "savetxt": 16, "saw": 30, "scatter": [27, 29, 32], "scikit": [31, 32], "scriptname": 28, "sd": 30, "seaborn": 21, "search": [30, 32], "secondvalue": 28, "sed": [11, 12, 13], "seen": 5, "self": [1, 19], "sep": 11, "sepal": [20, 21], "seq": 9, "sequence": [16, 30], "ser": 9, "series": [31, 32], "set": [13, 31, 32], "setattr": 26, "setdefault": [8, 32], "setosa": [20, 21], "setting": 16, "shape": 16, "she": 30, "shebang": 32, "shift": [0, 1, 7, 11, 13, 22, 26, 28], "show": [27, 29], "sign": 7, "simple": 9, "sin": [14, 27, 29], "singleton": 1, "sint": [11, 12, 13], "sit": [11, 12, 13], "site": [1, 4, 11, 13, 28], "size": 27, "sizeof": 26, "sjis": 29, "sklearn": 21, "sleep": 9, "slipped": 30, "small": [13, 26], "smaller": 9, "sns": 21, "soccer": 9, "solver": 21, "some": 9, "something": 9, "sort": [6, 20, 27, 29, 32], "sorted": [6, 16, 20, 31, 32], "sort\u30e1\u30bd\u30c3\u30c9": [6, 30], "source": 27, "spam": 6, "span": 30, "species": [20, 21], "split": [6, 17, 23, 30, 32], "sqrt": [14, 16], "square": 4, "squares": [6, 17], "src": [11, 27], "start": [9, 11, 28], "statement": [2, 6, 9, 32], "std": 20, "step": [9, 20], "stettin": 23, "stop": [9, 20], "stopiteration": [12, 19, 26, 32], "str": [5, 6, 8, 9, 10, 11, 17, 23, 26, 30, 32], "str1": 8, "stratify": 21, "stream": 1, "string": [1, 4, 31, 32], "stringfileiterator": 19, "stringio": 1, "strings": 17, "strip": 5, "styles": 9, "sub": 32, "subclasshook": 26, "subscriptable": 23, "substitution": 2, "substr": 5, "substring": 5, "such": [4, 11, 13], "suffixes": 24, "suit": 30, "sum": [9, 10, 17, 18, 28, 32], "sumnumbers": 30, "sunt": [11, 12, 13], "super": [19, 32], "supercalifragilisticexpialidocious": 9, "support": 5, "swap": [5, 9], "symmetric": 23, "syntax": [1, 5, 14, 29, 30], "syntaxerror": [1, 4, 5, 14, 29, 30], "syntaxwarning": 30, "sys": [1, 15, 28], "ta": 0, "tab": 7, "tag": 10, "target": 30, "tea": 8, "teacher": 30, "temp": 29, "temperature": 2, "tempest": 9, "tempor": [11, 12, 13], "temps": 29, "terminal": [13, 28], "terra": 23, "test": [11, 13, 21, 28, 30], "text": [5, 11, 13, 30], "than": [7, 9], "that": [1, 30], "the": [1, 2, 4, 5, 10, 15, 16, 17, 23, 28, 30], "them": 1, "there": 5, "they": [5, 30], "thirdvalue": 28, "this": [4, 5, 10, 30], "thow": 30, "three": [9, 30], "tick": 9, "ticker": 27, "time": [5, 9, 30], "title": [27, 29, 32], "to": [1, 4, 5, 7, 9, 11, 13, 15, 23, 30], "today": 30, "tokyo": [13, 26, 29], "too": 6, "total": 9, "traceback": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 16, 17, 19, 23, 26, 28, 29, 30], "train": [9, 21], "transform": [21, 27, 32], "trieste": 23, "triple": 5, "true": [0, 1, 3, 5, 6, 7, 8, 9, 11, 12, 16, 17, 18, 19, 20, 22, 23, 24, 26, 27, 29, 30, 32], "try": 12, "ttcggggtaccatt": 5, "tup": 6, "tuple": [17, 31, 32], "tutorial": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 17, 19, 23, 28], "txt": [11, 13, 16], "type": [1, 2, 5, 6, 8, 10, 12, 16, 19, 23, 32], "typeerror": [2, 5, 6, 16, 23], "uh": 5, "ullamco": [11, 12, 13], "unboundlocalerror": [4, 10], "undefined": 4, "undo": [0, 22], "unfortunately": 9, "unicode": 26, "unicodedecodeerror": 11, "union": 32, "unix": 28, "unsupported": 2, "unterminated": 4, "untitled": 22, "upload": 15, "uploaded": 15, "upper": [5, 9, 11, 32], "url": [0, 5], "use": [1, 4, 11, 13, 27], "user": 26, "usr": 28, "ut": [11, 12, 13], "utf": [11, 12, 13, 15, 18, 26, 28, 30], "utilities": 28, "v2": 28, "val": 9, "value": [2, 4, 6, 8, 9, 10, 27, 28, 32], "valueerror": [1, 4, 5, 6, 11, 13, 16, 28], "values": [9, 21, 26, 32], "var": [17, 30], "variable": [4, 10], "variance": 9, "vb": 30, "vbar": [27, 32], "velit": [11, 12, 13], "veniam": [11, 12, 13], "verb": 30, "versicolor": [20, 21], "vhi": 30, "vietnam": 30, "virginica": [20, 21], "viridis": 21, "visualization": [13, 32], "voluptate": [11, 12, 13], "vs": [8, 27, 29], "want": 5, "was": [16, 27, 30], "we": 30, "weight": 2, "were": 5, "what": [4, 11, 13, 30], "where": [4, 10], "while": [0, 11, 12, 18, 22, 30, 31, 32], "white": [9, 27], "width": 20, "wikipedia": 1, "will": [7, 27], "windows": [5, 11, 13], "wine": 8, "with": [1, 4, 9, 10, 12, 13, 16, 18, 19, 27, 28, 29, 30, 31, 32], "won": [4, 11, 13], "woo": 20, "word": [5, 9, 30], "words": [9, 17], "work": [24, 27, 29], "world": [5, 7, 10, 11, 18, 30], "would": 30, "write": [11, 32], "writerow": 26, "writerows": 26, "www": [26, 30], "w\u30bf\u30b0": 30, "xlabel": [29, 32], "xml": 30, "xp": 26, "xs": 12, "xyz": 30, "x\u8ef8": [27, 29], "yeah": 9, "year": [26, 29, 30], "years": [26, 29], "yesterday": 30, "ylabel": [29, 32], "you": [4, 5, 11, 13, 30], "your": [21, 30], "youth": 5, "yx": 27, "y\u8ef8": [27, 29], "zero": [1, 4, 6, 7], "zerodivisionerror": [1, 4], "zeros": 32, "zip": 13, "{&": [8, 9, 10, 17, 23], "{'": [8, 9, 10, 13, 25], "{w": 17, "{x": [30, 32], "{}": [8, 23], "|&": 30, "|'": 30, "|(": 21, "|)": 30, "|..": 30, "|abc": 30, "|ade": 30, "|an": 30, "|b": 30, "|c": 30, "|d": 30, "|de": 30, "|evening": 30, "|g": 30, "|i": 30, "|t": 30, "|the": 30, "|tle": 30, "|\u03c9\u30fb": 30, "|\uff20": 30, "} #": [9, 23], "}$": 30, "}'": 30, "})": [8, 9, 18, 23, 27], "},": [8, 13, 20, 30], "}-": 30, "}:": [4, 11, 13], "}[": 4, "}^": 9, "\u00a5n": 5, "\u00e1'": 9, "\u00e1,": 9, "\u00e7a": 23, "\u03c9\u30fb`": 30, "\u2026\u300d": 7, "\u2026\uff1f": 9, "\u2500\u2500": 13, "\u25b2bokeh": 31, "\u25b2csv": 31, "\u25b2for": 31, "\u25b2jupyter": 31, "\u25b2matplotlib": 31, "\u25b2python": 31, "\u25b2with": 31, "\u29f5n": 5, "\u3001\"": 6, "\u3001$": 14, "\u3001'": 20, "\u3001*": [22, 30], "\u3001for": 18, "\u3001|": 30, "\u3001\u2026": [7, 29], "\u3001\u25cf": 0, "\u3001\u300c": [0, 2, 7, 9, 14, 21, 30], "\u3001\u300c\u6708": 30, "\u3001\u6708": 29, "\u3001\uff08": [16, 30], "\u3002*": 30, "\u3002csv": 20, "\u3002numpy": 20, "\u3002return": 2, "\u3002scikit": 21, "\u3002shift": 22, "\u3002sin": 1, "\u3002y": 29, "\u3002\u3002": 28, "\u3002\u300d": [9, 11], "\u3002\u3044": 20, "\u3002\u304f\u308b": 11, "\u3002\u3057\u304b\u3057": 30, "\u3002\u3059": 30, "\u3002\u3064\u3051": 30, "\u3002\u3064\u307e\u308a": 30, "\u3002\u307e\u305a": 21, "\u3002\u307e\u305f": [2, 5, 6, 9, 20, 21, 29, 30], "\u3002\u30ad\u30fc": 9, "\u3002\u7d04": 1, "\u3002\uff08": [1, 3, 5, 7, 11, 23, 26, 28, 30], "\u3002\uff09": [0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18, 19, 23, 26, 30], "\u300c+": 0, "\u300c.": [0, 15], "\u300cipv4": 30, "\u300copen": 0, "\u300c\u25b2": 6, "\u300c\u3059\u3079\u3066": 0, "\u300c\u30d1\u30a4": 14, "\u300c\u30e2\u30b8\u30e5\u30fc\u30eb": 14, "\u300c\u30ea\u30b9\u30c8": 8, "\u300c\u53f3": 1, "\u300c\u542b\u3080": 30, "\u300c\u5f0f": 7, "\u300c\u6708": 30, "\u300c\u9e7f": 11, "\u300f\u300e": 26, "\u3042\u3044\u3046\u3048": 11, "\u3042\u3048": 16, "\u3042\u3052": [1, 32], "\u3042\u3063": [1, 2, 4, 7, 10, 12, 17, 20, 30], "\u3042\u3063\u3068\u307e\u30fc\u304f": 30, "\u3042\u3068": 7, "\u3042\u307e\u3059": 7, "\u3042\u3089\u304b\u3058\u3081": 3, "\u3042\u3089\u3086\u308b": [6, 8, 30], "\u3042\u308a": [0, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 30, 31, 32], "\u3042\u308b": [0, 1, 2, 3, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 26, 27, 30, 31, 32], "\u3042\u308b\u3044": [5, 6, 7, 9, 10, 11, 20, 21, 28], "\u3042\u308c": [5, 6, 7, 9, 10, 21], "\u3044\u3044": [1, 2, 6, 14, 18, 24, 30], "\u3044\u304b": 30, "\u3044\u304d": [2, 6, 9, 12, 20, 24], "\u3044\u304f\u3064\u304b": [1, 4, 5, 24], "\u3044\u304f\u3089": 2, "\u3044\u3061\u3044\u3061": 18, "\u3044\u3064\u307e\u3067": 0, "\u3044\u307e\u305b": [0, 9, 11, 14, 15, 19, 30], "\u3044\u308b": [0, 1, 2, 3, 4, 5, 7, 8, 9, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31], "\u3044\u308c": [0, 3, 5, 16, 30], "\u3044\u308f\u3086\u308b": [5, 6], "\u3046\u3061": [2, 3, 7, 9, 18, 19, 30], "\u3046\u3064": 9, "\u304a\u3044": [5, 6, 13, 14, 17, 19, 21, 24, 30], "\u304a\u304a\u307e\u304b": 9, "\u304a\u304a\u3088\u305d\u306e": 4, "\u304a\u304d": [1, 5, 8, 9, 26], "\u304a\u304d\u307e\u3057\u3087": 1, "\u304a\u304f": [3, 30], "\u304a\u3051\u3070": 2, "\u304a\u3051\u308b": [2, 3, 4, 6, 8, 9, 12, 13, 18, 19, 20, 21, 28, 31, 32], "\u304a\u307e\u3058": 1, "\u304a\u3088\u3073": [8, 9], "\u304a\u3089": 11, "\u304a\u308a": [5, 7, 9, 11, 17, 20, 21, 26, 29, 30], "\u304a\u308f\u308c": 9, "\u304b\u304b\u308a": [6, 9], "\u304b\u304b\u308b": [6, 9], "\u304b\u304b\u308f\u3089": 8, "\u304b\u304d\u304f\u3051": 11, "\u304b\u304d\u304f\u3051\u3053": 11, "\u304b\u304e": 6, "\u304b\u3055": 11, "\u304b\u305f\u3061": 11, "\u304b\u3064": [3, 7, 30], "\u304b\u3064\u3044": 11, "\u304b\u3069": [6, 8, 30], "\u304b\u3069\u3046": [2, 6, 8, 9, 16, 30], "\u304b\u306b\u95a2\u308f\u3089": 19, "\u304b\u3082": [2, 10, 30], "\u304b\u3089": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32], "\u304b\u308f": 8, "\u304b\u308f\u308a": 1, "\u304b\u6708": [26, 29], "\u304c\u3042\u308a": [19, 30], "\u304c\u3042\u308c": 27, "\u304c\u3044\u305a\u308c": 7, "\u304c\u304f\u7247": 20, "\u304c\u3061": 11, "\u304c\u3063": [1, 3, 6, 7, 12, 18, 31], "\u304c\u3064\u3051": 20, "\u304c\u306a\u3044": 30, "\u304c\u3088\u308a": 1, "\u304c\u3089\u3093": 11, "\u304c\u308b": [6, 31, 32], "\u304c\u308f\u304b\u308a": [2, 7, 9, 16, 18, 19, 21, 27, 29], "\u304d\u305f": 30, "\u304d\u3061\u3093": 4, "\u304d\u307e\u3063": 6, "\u304f\u3060": [0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 26, 27, 28, 29, 30, 31], "\u304f\u308b": [7, 24], "\u304f\u308c": [2, 4, 11], "\u3053\u3046\u3057\u3066": 5, "\u3053\u3048\u308c": 9, "\u3053\u3053": [0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 16, 17, 19, 20, 21, 25, 26, 28, 29, 30], "\u3053\u3053\u3067": [1, 2, 3, 6, 7, 12, 19, 25, 26, 27], "\u3053\u3053\u306b": 17, "\u3053\u3053\u306e": 7, "\u3053\u3053\u307e\u3067": [4, 10, 18, 30], "\u3053\u3061\u3089": [1, 11, 19], "\u3053\u3068": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30], "\u3053\u306e": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 25, 26, 27, 28, 30], "\u3053\u3080": 4, "\u3053\u308c": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 22, 26, 27, 28, 30], "\u3053\u308c\u3089": [0, 1, 2, 3, 4, 5, 8, 10, 14, 16, 19, 20, 30], "\u3053\u3093\u306a": 11, "\u3054\u3068": [6, 14, 19, 20, 21, 23, 26, 29], "\u3055\u3044": [0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 26, 27, 28, 29, 30, 31], "\u3055\u304c": 9, "\u3055\u3066": [4, 9, 12, 13, 18, 28, 30], "\u3055\u3089": [7, 8], "\u3055\u3089\u306b": [3, 6, 7, 9, 11, 17, 18, 19, 25, 26], "\u3057\u304b": [9, 11, 30], "\u3057\u304b\u3057": [1, 4, 5, 6, 10, 11, 12, 18, 19, 28, 30], "\u3057\u304b\u3082": 16, "\u3057\u304f": 30, "\u3057\u305d\u306e": 21, "\u3057\u3064\u3064": 29, "\u3057\u3066": [1, 5, 6, 9, 10, 11, 14, 18, 19, 20, 21, 22, 24, 26, 28, 30], "\u3057\u3070\u3057\u3070": [4, 6], "\u3057\u307e\u3044": [2, 6, 7, 8, 11, 22], "\u3057\u307e\u3046": [5, 30], "\u3057\u307e\u3057\u3087": [1, 2, 4, 10, 19, 22, 26, 28], "\u3057\u307e\u3059": [6, 8, 9, 17, 21, 30], "\u3057\u307e\u305b": [19, 24, 25, 26, 30], "\u3057\u307e\u3063": 2, "\u3057\u3084\u3059\u304f": 28, "\u3057\u3088": [1, 3, 4, 6, 11, 24, 28], "\u3057\u308c": [2, 10, 30], "\u3059\u3050": 6, "\u3059\u3064\u304b\u308a": 11, "\u3059\u306a\u308f\u3061": [1, 3, 6, 7, 8, 16, 18, 23, 26, 30], "\u3059\u3079\u304d": 4, "\u3059\u308b": [0, 1, 2, 3, 4, 5, 7, 9, 10, 11, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32], "\u3059\u308c": [0, 2, 5, 6, 7, 27, 28], "\u305a\u3063\u3068": [2, 19], "\u305a\u3064": [6, 9, 13, 24, 26, 29, 30], "\u305a\u306b": [1, 11], "\u305a\u308c": [5, 18, 20, 30], "\u305a\u3090\u3076\u3093": 11, "\u305b\u305a": 28, "\u305b\u308b": [1, 3, 4, 6, 8, 9, 12, 13, 16, 19, 20, 21, 23, 25, 27, 29, 30], "\u305c\u3093\u305f\u3044": 11, "\u305d\u3046": [3, 5, 14, 15, 18, 19, 21, 24, 30], "\u305d\u3046\u3044\u3046": 16, "\u305d\u3046\u3057": 1, "\u305d\u3053": [3, 4, 10, 19, 29, 30], "\u305d\u3053\u3067": [19, 27], "\u305d\u3057": [2, 3, 7], "\u305d\u3057\u3066": [2, 4, 6, 7, 9, 12, 19, 21], "\u305d\u306e": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 31, 32], "\u305d\u306e\u307e\u307e": [5, 26], "\u305d\u306e\u3088\u3046": 2, "\u305d\u306e\u4e0a": [0, 9, 29], "\u305d\u306e\u4e0b": 0, "\u305d\u306e\u5024": 19, "\u305d\u306e\u5f8c": [9, 12], "\u305d\u306e\u969b": 10, "\u305d\u3082": 4, "\u305d\u308c": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 16, 17, 19, 22, 24, 26, 27, 28, 30], "\u305d\u308c\u305e\u308c": [1, 4, 5, 6, 7, 8, 9, 10, 16, 17, 20, 21, 26, 27, 29], "\u305d\u308c\u3089": [3, 6, 9, 10, 17, 19], "\u305e\u308c": [10, 17, 24], "\u305f\u3044": [1, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 20, 26, 27, 29, 30], "\u305f\u304b": 0, "\u305f\u304c\u3063": [3, 4, 5, 6, 9, 11, 12, 16, 17, 18, 19, 25, 28, 30], "\u305f\u3060": [11, 30], "\u305f\u3060\u3057": [2, 3, 4, 5, 6, 8, 9, 11, 14, 15, 16, 17, 22, 27, 29, 30], "\u305f\u3060\u3061": 9, "\u305f\u3063": [0, 6, 9], "\u305f\u3064": 11, "\u305f\u3068\u3048": [1, 4, 5, 6, 9, 10, 11, 13, 14, 18, 23, 24, 28, 30], "\u305f\u306a": [2, 19], "\u305f\u3073": [0, 2, 6, 18], "\u305f\u3081": [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 19, 20, 21, 25, 26, 27, 28, 29], "\u305f\u3082\u306e": [14, 18], "\u305f\u3088\u3046": [6, 12, 19], "\u305f\u3089": [1, 2, 3, 4, 10, 11, 12, 21, 26, 28], "\u305f\u308a": [0, 1, 5, 8, 16, 18, 19, 28], "\u3060\u3044\u3076": 11, "\u3060\u304b\u3089": 13, "\u3060\u3051": [1, 2, 3, 4, 5, 6, 9, 12, 13, 14, 15, 16, 17, 19, 21, 25, 27, 30], "\u3060\u3055\u3044": [0, 1, 2, 5, 6, 7, 9, 11, 17, 18, 20, 21, 22, 28, 29, 30], "\u3060\u3063": 30, "\u3060\u3068": [6, 30], "\u3060\u3089": 11, "\u3060\u308a": 11, "\u3064\u3044": [6, 28], "\u3064\u3051": [16, 20, 29], "\u3064\u306a\u304e": [27, 29], "\u3064\u306a\u3052\u308b": 20, "\u3064\u307e\u308a": [1, 4, 6, 12, 16, 28, 30], "\u3064\u3082\u308a": 4, "\u3065\u3051\u308b": 8, "\u3066\u304f": [6, 18, 22, 29], "\u3066\u307f\u307e\u3057\u3087": 6, "\u3066\u308b": [6, 8], "\u3067\u3042\u3063": 28, "\u3067\u3042\u308a": [23, 30], "\u3067\u3042\u308c": 16, "\u3067\u3044": 9, "\u3067\u304d": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30], "\u3067\u304d\u308b": [4, 7, 12, 14, 16, 17, 18, 19, 24, 25, 27, 28, 30], "\u3067\u304f": 17, "\u3067\u3057": [1, 4, 6, 11, 13, 27], "\u3067\u3057\u3070\u3057\u3070": [6, 8], "\u3067\u3057\u3087": [0, 1, 2, 5, 8, 9, 12, 15, 16, 17, 19, 21, 28, 30], "\u3067\u3059": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30], "\u3067\u305d\u308c\u305e\u308c": 8, "\u3067\u305f\u3060\u3061": 9, "\u3067\u3064": 29, "\u3067\u306a\u304f": [6, 9], "\u3067\u306f": 23, "\u3067\u307f\u307e\u3057\u3087": [11, 26], "\u3067\u3082": [0, 2, 5, 6, 7, 9, 10, 11, 12, 16, 17, 18, 22, 27, 30], "\u3067\u3082\u53ef": 30, "\u3068list": 9, "\u3068\u3044\u3046": [0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 26, 27, 28, 29, 30], "\u3068\u3044\u3048": 21, "\u3068\u3044\u3063": [9, 11, 25], "\u3068\u3048": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 16, 22, 26, 28, 29, 30], "\u3068\u304a\u304f": 3, "\u3068\u304a\u308a": 9, "\u3068\u304b": 30, "\u3068\u304d": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 23, 24, 26, 27, 28, 29, 30, 31], "\u3068\u3053": 11, "\u3068\u3053\u306e": 9, "\u3068\u3053\u308d": [0, 2, 5, 7, 9, 24], "\u3068\u3053\u308d\u3069\u3053\u308d": 3, "\u3068\u3053\u3093\u306a": 26, "\u3068\u3057": [2, 4, 5, 6, 7, 8, 9, 11, 24, 26, 27, 28, 29, 30], "\u3068\u3057\u3066": [1, 2, 4, 5, 6, 7, 8, 9, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31], "\u3068\u3059\u308b": [9, 16, 30], "\u3068\u3059\u308c": 11, "\u3068\u3063": 7, "\u3068\u3066": 16, "\u3068\u3068\u3082": [1, 2], "\u3068\u3068\u3082\u306b": [24, 29], "\u3068\u3069": 6, "\u3068\u306a\u3063": 9, "\u3068\u306a\u308a": [1, 5, 9, 11, 16, 17], "\u3068\u306a\u308b": [7, 9], "\u3068\u306e": 5, "\u3068\u306f": [6, 9], "\u3068\u3073\u3068\u3073": 5, "\u3068\u307f": 3, "\u3068\u3082": [1, 2, 9, 10, 12, 13, 19, 23], "\u3068\u308a": 16, "\u3068\u308b": 3, "\u3068\u308f\u304b\u308a": 17, "\u3068\u308f\u304b\u308b": [4, 28], "\u3068\u540c\u3058": [6, 29], "\u3068\u547c\u3070": [2, 5, 10, 16, 19, 28, 30], "\u3068\u547c\u3070\u308c\u308b": [5, 9, 30], "\u3068\u547c\u3073": [2, 4, 5, 11, 13, 21, 25, 28], "\u3068\u8a00\u3044": [1, 2, 3, 19], "\u3069\u3046": [1, 3, 5, 6, 8, 9, 10, 12, 17, 18, 23, 26, 28, 30], "\u3069\u304a\u308a": 7, "\u3069\u3053": [10, 19], "\u3069\u3053\u304b": 13, "\u3069\u3061\u3089": [6, 7, 16], "\u3069\u306e": [11, 12, 18], "\u306a\u3042": 11, "\u306a\u3044": [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 26, 28, 30, 31, 32], "\u306a\u304a": [0, 1, 2, 3, 5, 6, 7, 9, 11, 13, 14, 16, 17, 18, 19, 20, 23, 28, 29, 30], "\u306a\u304b\u3063": [1, 2, 4, 9, 11], "\u306a\u304c\u3089": [0, 1, 9, 11, 12, 24], "\u306a\u304e": 29, "\u306a\u304f": [1, 2, 3, 4, 5, 6, 7, 11, 12, 14, 16, 17, 18, 19, 23, 26, 30, 31], "\u306a\u3051\u308c": [1, 3, 4, 5, 6, 9, 13, 14, 16, 18, 19, 24, 25, 30], "\u306a\u3053": 26, "\u306a\u3055": [1, 3, 30], "\u306a\u3057": [6, 30, 31, 32], "\u306a\u305b\u308b": 30, "\u306a\u3063": [0, 1, 2, 5, 6, 7, 9, 11, 13, 16, 17, 20, 21, 24, 26, 28, 29, 30, 31], "\u306a\u3068\u304d": 18, "\u306a\u3069": [0, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 26, 30, 31], "\u306a\u306b": 9, "\u306a\u3082\u306e": [1, 3, 5, 8, 11, 19, 30], "\u306a\u3089": [0, 1, 3, 4, 5, 9, 10, 11, 14, 18, 19, 24, 28], "\u306a\u3089\u3070": [19, 30], "\u306a\u308a": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30], "\u306a\u308b": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 20, 21, 23, 26, 27, 28, 29, 30], "\u306a\u308f\u3061": [5, 6, 9, 18, 30], "\u306a\u3093": 11, "\u306b\u3044": 6, "\u306b\u3044\u304f\u3064": 5, "\u306b\u304a\u3044": [1, 4, 6, 7, 9, 12, 13, 14, 21], "\u306b\u304a\u3051\u308b": [4, 8, 15, 19, 31, 32], "\u306b\u304f\u3044": 4, "\u306b\u304f\u304f": 4, "\u306b\u3057": 20, "\u306b\u3059\u3050": 6, "\u306b\u3059\u308b": [7, 17, 20], "\u306b\u305d\u306e": 26, "\u306b\u305d\u308c\u305e\u308c": 25, "\u306b\u3064\u3044\u3066": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32], "\u306b\u3064\u3051": 30, "\u306b\u3064\u3051\u3066": 10, "\u306b\u307e\u3068\u3081\u308b": 23, "\u306b\u3082": [16, 19], "\u306b\u3088\u304f": [6, 31, 32], "\u306b\u3088\u3063": [0, 2, 4, 5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 22, 26, 30], "\u306b\u3088\u3063\u3066": [1, 3, 5, 7, 12, 22, 28, 30], "\u306b\u3088\u308a": [0, 2, 5, 19, 20, 21, 26, 28, 29], "\u306b\u3088\u308b": [0, 1, 2, 4, 5, 17, 20, 24, 26, 30, 31, 32], "\u306b\u308f": [6, 9], "\u306b\u308f\u305f\u3063": 9, "\u306b\u308f\u305f\u308b": 5, "\u306b\u5bfe\u3057": [2, 5, 6, 9, 10, 11, 12, 16, 17, 18, 19, 21, 23, 27, 28, 29, 30], "\u306b\u5bfe\u3059\u308b": [0, 4, 5, 8, 9, 10, 12, 16, 18, 25, 31, 32], "\u306b\u5bfe\u5fdc": [8, 9, 13, 16, 18, 21, 26, 30], "\u306b\u5bfe\u5fdc\u4ed8\u3051": 8, "\u306b\u95a2\u3057": [2, 11], "\u306b\u95a2\u3059\u308b": [0, 1, 4, 16, 21, 31], "\u306d\u3048": 11, "\u306e\u3044": 30, "\u306e\u3044\u305a\u308c": 5, "\u306e\u3044\u305a\u308c\u304b": [4, 30], "\u306e\u3046\u3061": [7, 19], "\u306e\u3061": [7, 8], "\u306e\u3064\u3051": 4, "\u306e\u3067": [1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31], "\u306e\u3067\u3059": [2, 30], "\u306e\u3068\u3053\u308d": [0, 5, 6, 7, 8, 9, 17, 23, 29, 30], "\u306e\u3069\u3053": 5, "\u306e\u3069\u3061\u3089\u304b": 3, "\u306e\u306b": [2, 6, 9, 23], "\u306e\u307f": [1, 2, 3, 6, 7, 8, 10, 15, 28], "\u306e\u3088\u3046": [0, 1, 2, 6, 8, 11, 13, 14, 18, 20, 25, 30], "\u306f\u3044\u3051": [2, 9, 30], "\u306f\u3044\u305a\u308c": 30, "\u306f\u3053\u308c": 6, "\u306f\u3058\u3081": 5, "\u306f\u3058\u3081\u3066": [26, 29], "\u306f\u305a": [0, 1, 11, 16, 26], "\u306f\u305d\u306e": 4, "\u306f\u305d\u308c\u305e\u308c": 30, "\u306f\u306a\u3053": 26, "\u306f\u307f": 1, "\u3070\u305d\u306e\u3044": 18, "\u3070\u3088\u304f": 6, "\u3070\u3089": 6, "\u3072\u304d\u3059\u3046": 2, "\u3072\u3068": [2, 28], "\u3072\u3068\u3064": 6, "\u3074\u304b": 11, "\u3078\u306e": [2, 13], "\u3079\u304d": [4, 6, 30, 31, 32], "\u307b\u3068\u3093\u3069": 30, "\u307e\u3046": 11, "\u307e\u3057": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 14, 16, 17, 18, 19, 23, 25, 28], "\u307e\u3057\u3087": [2, 4, 13, 24, 26], "\u307e\u3059": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], "\u307e\u305a": [1, 2, 6, 7, 9, 10, 11, 16, 19, 20, 29], "\u307e\u305b": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 19, 23, 24, 25, 26, 27, 28, 30, 31], "\u307e\u305f": [1, 3, 4, 5, 6, 8, 9, 10, 11, 13, 16, 17, 20, 21, 22, 23, 26, 27, 28, 30, 31, 32], "\u307e\u3060": 11, "\u307e\u3067": [1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 17, 21, 24, 25, 26, 27, 29, 30], "\u307e\u3068": 2, "\u307e\u3068\u3081": [10, 12, 14, 16, 28, 31], "\u307e\u3068\u3081\u3066": [6, 11, 16, 27, 29, 30], "\u307e\u3068\u3081\u308b": [5, 7, 13, 18, 20], "\u307e\u306f\u3064": 11, "\u307e\u307e": [0, 6, 12, 14, 15, 22, 26], "\u307e\u307e\u3067": 22, "\u307e\u308a": 2, "\u307e\u308c": 30, "\u307e\u308c\u308b": 5, "\u307f\u304b": 5, "\u307f\u304b\u3089": [2, 6, 18, 26], "\u307f\u3066": [0, 1, 6, 9, 11, 18, 21, 22, 28, 29, 30], "\u307f\u306a\u3055": [2, 3], "\u307f\u306a\u3055\u3093": [25, 26], "\u307f\u306a\u3057": 30, "\u307f\u306a\u3059": 20, "\u307f\u307e\u3057\u3087": [1, 2, 4, 6, 7, 9, 10, 16, 18, 19, 21, 26], "\u307f\u308b": [2, 21, 30], "\u3082\u3042\u308a": 5, "\u3082\u3046": [1, 2, 5, 6, 7, 9, 11, 12, 21], "\u3082\u304b\u307e\u3044": [2, 6], "\u3082\u3057": [9, 28], "\u3082\u3057\u304f": [0, 2, 5, 6, 9, 11, 13, 16, 29, 30, 31], "\u3082\u3058\u308c\u3064": 5, "\u3082\u305b": 12, "\u3082\u3061\u308d\u3093": [1, 6, 30], "\u3082\u3063": 1, "\u3082\u3063\u3071\u3089": 19, "\u3082\u3068": [6, 7, 8, 9, 19, 30], "\u3082\u3069\u3061\u3089": 0, "\u3082\u306e": [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 27, 29, 30, 31], "\u3082\u3082\u3046": 8, "\u3082\u3088": 19, "\u3082\u3088\u3044": [2, 16, 30], "\u3082\u3088\u304f": 24, "\u3082\u3089\u3057\u3044": 4, "\u3082\u3089\u3063": [2, 12, 18], "\u3082\u308a": 9, "\u3082\u308b": 9, "\u3082\u308f\u304b\u308a": 30, "\u3082\u308f\u304b\u308b": 2, "\u3082\u3093": 11, "\u3084\u3046": 11, "\u3084\u3059\u3044": [6, 12, 16, 17, 24, 30], "\u3084\u3059\u304f": [4, 9, 17], "\u3084\u3063": 11, "\u3084\u3064\u3066": 11, "\u3084\u308a": [3, 9], "\u3084\u308b": 30, "\u3088\u3044": [0, 2, 6, 9, 16, 17, 18, 27, 30], "\u3088\u3046": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], "\u3088\u304f": [1, 4, 9, 11, 21, 31], "\u3088\u304f\u308f": 18, "\u3088\u306d": 26, "\u3088\u308a": [2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 17, 18, 20, 21, 24, 29, 30], "\u3089\u3048": 17, "\u3089\u308c": [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 23, 24, 26, 28, 29, 30], "\u3089\u308c\u308b": [5, 6, 9, 10, 17, 19, 28, 30], "\u308c\u305a": 10, "\u308c\u307e\u305b": [0, 3, 7, 9, 12, 16, 28], "\u308c\u308b": [0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 18, 19, 21, 23, 26, 27, 28, 30, 31], "\u308c\u308c": 6, "\u308f\u304b\u308a": 12, "\u308f\u304b\u308b": [4, 16], "\u308f\u3051": [12, 15, 18, 28], "\u3092\u304a\u3051\u3070": 1, "\u3092\u305d\u306e": 10, "\u3092\u3064\u3051": [29, 30], "\u3092\u307e\u305c": 1, "\u3092\u307e\u305f": 6, "\u3092\u308a": 11, "\u3093\u304b": 18, "\u3093\u306d": 11, "\u309d\u3089": 11, "\u30a2\u30a4\u30b3\u30f3": [0, 22], "\u30a2\u30a4\u30ea\u30b9\u30c7\u30fc\u30bf\u30bb\u30c3\u30c8": 21, "\u30a2\u30ab\u30a6\u30f3\u30c8": [0, 30], "\u30a2\u30af\u30bb\u30b9": 13, "\u30a2\u30c9\u30ec\u30b9": 6, "\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3": [13, 28], "\u30a2\u30e4\u30e1": 20, "\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0": [9, 24], "\u30a2\u30eb\u30d5\u30a1\u30d9\u30c3\u30c8": [5, 30], "\u30a2\u30ec\u30a4": 6, "\u30a2\u30f3\u30c0\u30fc\u30b9\u30b3\u30a2": [2, 14], "\u30a4\u30ae\u30ea\u30b9": [11, 30], "\u30a4\u30c1\u30ed\u30fc": 26, "\u30a4\u30c6\u30e9\u30d6\u30eb": [31, 32], "\u30a4\u30c6\u30ec\u30fc\u30bf": [17, 18, 26, 31, 32], "\u30a4\u30e1\u30fc\u30b8": 11, "\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9": [19, 21, 32], "\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb": 28, "\u30a4\u30f3\u30bf\u30d5\u30a7\u30fc\u30b9": 0, "\u30a4\u30f3\u30bf\u30d7\u30ea\u30bf": 28, "\u30a4\u30f3\u30bf\u30fc\u30d7\u30ea\u30bf": 22, "\u30a4\u30f3\u30c1": 2, "\u30a4\u30f3\u30c7\u30c3\u30af\u30b9": [8, 9, 16, 20, 23, 24, 27, 29, 30, 31, 32], "\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30a2\u30af\u30bb\u30b9": [20, 31, 32], "\u30a4\u30f3\u30c7\u30f3\u30c8": [2, 3, 4, 9, 10, 31, 32], "\u30a4\u30f3\u30c7\u30f3\u30c8\u30ec\u30d9\u30eb": 7, "\u30a4\u30f3\u30d7\u30ec\u30fc\u30b9": [16, 24, 31, 32], "\u30a4\u30f3\u30dd\u30fc\u30c8": [16, 20, 21, 27, 28, 29, 30, 31, 32], "\u30a6\u30a4\u30f3\u30c9\u30a6": 28, "\u30a8\u30af\u30b9\u30c6\u30f3\u30b7\u30e7\u30f3": [0, 22], "\u30a8\u30af\u30b9\u30d7\u30ed\u30fc\u30e9": 11, "\u30a8\u30b9\u30b1\u30fc\u30d7": 30, "\u30a8\u30b9\u30b1\u30fc\u30d7\u30b7\u30fc\u30b1\u30f3\u30b9": [11, 31, 32], "\u30a8\u30e9\u30fc": [2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 16, 19, 23, 26, 27, 28, 30, 31, 32], "\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8": 4, "\u30a8\u30eb": 2, "\u30a8\u30f3\u30b3\u30fc\u30c9": [11, 15], "\u30aa\u30d6\u30b8\u30a7\u30af\u30c8": [11, 12, 16, 17, 18, 19, 20, 26, 27, 29, 30, 31, 32], "\u30aa\u30d6\u30b8\u30a7\u30af\u30c8greeting": 10, "\u30aa\u30d7\u30b7\u30e7\u30ca\u30eb": 30, "\u30aa\u30d7\u30b7\u30e7\u30f3": 6, "\u30aa\u30da\u30ec\u30fc\u30c6\u30a3\u30f3\u30b0\u30b7\u30b9\u30c6\u30e0": 28, "\u30aa\u30f3\u30e9\u30a4\u30f3\u30b5\u30fc\u30d3\u30b9": 4, "\u30aa\u30fc\u30c0\u30fc": [9, 32], "\u30aa\u30fc\u30c8\u30bb\u30fc\u30d6": [0, 22], "\u30aa\u30fc\u30d7\u30f3": [12, 18, 26, 31, 32], "\u30aa\u30fc\u30d7\u30f3\u30c7\u30fc\u30bf": [26, 29], "\u30ab\u30e9\u30fc\u30d0\u30fc": 27, "\u30ab\u30ec\u30f3\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea": [13, 15, 32], "\u30ab\u30ec\u30f3\u30c8\u30ef\u30fc\u30ad\u30f3\u30b0\u30c7\u30a3\u30ec\u30af\u30c8\u30ea": [31, 32], "\u30ab\u30fc\u30bd\u30eb": [0, 22], "\u30ab\u30fc\u30d6": [27, 29], "\u30ac\u30a6\u30b9": 9, "\u30ad\u30e3\u30d7\u30c1\u30e3": [30, 32], "\u30ad\u30e3\u30ec\u30c3\u30c8": 30, "\u30ad\u30fc": [4, 5, 9, 10, 18, 20, 23, 25, 30, 32], "\u30ad\u30fcapple": 8, "\u30ad\u30fcorange": 8, "\u30ad\u30fc\u30dc\u30fc\u30c9": 5, "\u30ad\u30fc\u30ef\u30fc\u30c9": [6, 11, 18, 26, 27, 31, 32], "\u30af\u30a9\u30fc\u30c8": [4, 5], "\u30af\u30e9\u30b9": [14, 21, 27, 31, 32], "\u30af\u30e9\u30b9\u30bf": 21, "\u30af\u30e9\u30b9\u30bf\u30ea\u30f3\u30b0": [21, 32], "\u30af\u30ea\u30c3\u30af": [0, 13, 22, 27, 28], "\u30af\u30ed\u30fc\u30ba": [26, 31, 32], "\u30b0\u30e9\u30d5": [31, 32], "\u30b0\u30ea\u30c3\u30c9": 29, "\u30b0\u30eb\u30fc\u30d7": [7, 9, 21, 31, 32], "\u30b0\u30ed\u30fc\u30d0\u30eb": [4, 10, 14, 31, 32], "\u30b0\u30fc\u30ea\u30f3\u30c0\u30a4": 18, "\u30b3\u30d4\u30fc": [0, 11, 16, 24], "\u30b3\u30d4\u30fc\u30da\u30fc\u30b9\u30c8": 0, "\u30b3\u30de\u30f3\u30c9": [0, 22, 28], "\u30b3\u30de\u30f3\u30c9\u30e2\u30fc\u30c9": [2, 31], "\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3": [31, 32], "\u30b3\u30e1\u30f3\u30c8": [5, 31, 32], "\u30b3\u30e1\u30f3\u30c8\u30a2\u30a6\u30c8": [1, 5, 15], "\u30b3\u30ed\u30f3": [4, 5], "\u30b3\u30f3\u30b9\u30c8\u30e9\u30af\u30bf": [19, 32], "\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf": [1, 6], "\u30b3\u30f3\u30de": [2, 5, 6, 9, 10, 14, 17, 26], "\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u30b9\u30bf\u30a4\u30eb": [5, 7, 31, 32], "\u30b3\u30fc\u30c9": [0, 1, 2, 4, 9, 10, 15, 20, 21, 22, 24, 26, 29, 31, 32], "\u30b3\u30fc\u30c9\u30bb\u30eb": [0, 2, 12, 15, 28], "\u30b3\u30fc\u30c9\u30d6\u30ed\u30c3\u30af": 9, "\u30b3\u30fc\u30d1\u30b9": 30, "\u30b5\u30a4\u30ba": 16, "\u30b5\u30fc\u30af\u30eb": 26, "\u30b7\u30a7\u30eb": 28, "\u30b7\u30ca\u30ea\u30aa": 4, "\u30b7\u30ea\u30fc\u30ba": [21, 31, 32], "\u30b7\u30ea\u30fc\u30ba\u30aa\u30d6\u30b8\u30a7\u30af\u30c8": 20, "\u30b7\u30f3\u30b0\u30eb": 5, "\u30b7\u30f3\u30b0\u30eb\u30af\u30a9\u30fc\u30c8": 5, "\u30b8\u30a7\u30cd\u30ec\u30fc\u30bf": [31, 32], "\u30b9\u30a4\u30c3\u30c1": [2, 22], "\u30b9\u30ab\u30e9": 32, "\u30b9\u30af\u30ea\u30d7\u30c8": [31, 32], "\u30b9\u30af\u30ea\u30d7\u30c8\u30d5\u30a1\u30a4\u30eb": 28, "\u30b9\u30b3\u30fc\u30d7": [31, 32], "\u30b9\u30bf\u30a4\u30eb": 4, "\u30b9\u30bf\u30a4\u30eb\u30ac\u30a4\u30c9": [4, 5, 7], "\u30b9\u30c6\u30c3\u30d7": [17, 26], "\u30b9\u30c8\u30c3\u30d7\u30dc\u30bf\u30f3": [0, 9], "\u30b9\u30d1\u30e0": 30, "\u30b9\u30da\u30fc\u30b9": [4, 5, 6, 7, 9, 23, 28, 30], "\u30b9\u30e9\u30a4\u30b9": [6, 20, 31, 32], "\u30bb\u30c3\u30c8": [31, 32], "\u30bb\u30df\u30b3\u30ed\u30f3": 29, "\u30bb\u30eb": [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 14, 15, 16, 17, 18, 19, 23, 26, 28, 29, 30, 31], "\u30bb\u30f3\u30c1\u30e1\u30fc\u30c8\u30eb": 2, "\u30bb\u30fc\u30d6": [0, 15, 22], "\u30bc\u30ed": [1, 2, 3, 4], "\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9": [15, 28], "\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb": 31, "\u30bd\u30fc\u30c8": [6, 16, 18, 20, 24], "\u30bf\u30a4\u30c8\u30eb": [0, 22, 27, 29], "\u30bf\u30a4\u30df\u30f3\u30b0": [0, 22], "\u30bf\u30b0": 30, "\u30bf\u30b9\u30af": 4, "\u30bf\u30d6": [11, 28, 30], "\u30bf\u30d7\u30eb": [8, 9, 10, 16, 17, 18, 23, 29, 31, 32], "\u30bf\u30f3\u30bf\u30a2\u30fc\u30f3": 11, "\u30bf\u30fc\u30df\u30ca\u30eb": 28, "\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9": [15, 26, 29, 31], "\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u30d5\u30a9\u30eb\u30c0": [15, 28], "\u30c0\u30d6\u30eb\u30af\u30a9\u30fc\u30c8": [5, 30], "\u30c0\u30d6\u30eb\u30af\u30ea\u30c3\u30af": 22, "\u30c1\u30a7\u30c3\u30af": 30, "\u30c1\u30e5\u30fc\u30c8\u30ea\u30a2\u30eb": 12, "\u30c1\u30e9": 30, "\u30c6\u30ad\u30b9\u30c8": [0, 16], "\u30c6\u30ad\u30b9\u30c8\u30bb\u30eb": 0, "\u30c6\u30ad\u30b9\u30c8\u30e2\u30fc\u30c9": 11, "\u30c6\u30b9\u30c8": [7, 9, 26, 28, 31, 32], "\u30c6\u30b9\u30c8\u30b1\u30fc\u30b9": [4, 32], "\u30c6\u30b9\u30c8\u30b3\u30fc\u30c9": 28, "\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf": 21, "\u30c7\u30a3\u30ec\u30af\u30c8\u30ea": [11, 15, 22, 28, 31, 32], "\u30c7\u30d0\u30c3\u30b0": [2, 31, 32], "\u30c7\u30d5\u30a9\u30eb\u30c8": [11, 16, 20, 27, 28], "\u30c7\u30ea\u30df\u30bf": 30, "\u30c7\u30fc\u30bf": [3, 5, 6, 8, 9, 11, 12, 18, 19, 23, 26, 27, 29, 30, 31, 32], "\u30c7\u30fc\u30bf\u30bb\u30c3\u30c8": 21, "\u30c7\u30fc\u30bf\u30d5\u30ec\u30fc\u30e0": [21, 31, 32], "\u30c7\u30fc\u30bf\u30d5\u30ec\u30fc\u30e0\u30aa\u30d6\u30b8\u30a7\u30af\u30c8": 20, "\u30c7\u30fc\u30bf\u30dd\u30a4\u30f3\u30c8": 29, "\u30c8\u30a4\u30ec": 11, "\u30c8\u30c3\u30d7\u30ec\u30d9\u30eb": [2, 32], "\u30c8\u30ea\u30d7\u30eb\u30af\u30a9\u30fc\u30c8": 5, "\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8": 11, "\u30c9\u30c3\u30c8": 16, "\u30c9\u30e1\u30a4\u30f3": 6, "\u30c9\u30e9\u30a4\u30d6": 0, "\u30c9\u30eb": 30, "\u30cb\u30c3\u30af\u30cd\u30fc\u30e0": 26, "\u30cd\u30a4\u30d4\u30a2": 14, "\u30cd\u30b9\u30c8": [7, 9, 17, 32], "\u30ce\u30eb\u30e0": 16, "\u30ce\u30fc\u30c8\u30d6\u30c3\u30af": [5, 11, 15, 19, 22, 25, 27, 29, 31], "\u30ce\u30fc\u30c9": [13, 32], "\u30ce\u30fc\u30c9\u30d6\u30c3\u30af": 0, "\u30cf\u30a4\u30d1\u30fc\u30d1\u30e9\u30e1\u30fc\u30bf": 21, "\u30cf\u30a4\u30d5\u30f3": 30, "\u30cf\u30a4\u30e9\u30a4\u30c8": 2, "\u30d0\u30a4\u30ca\u30ea\u30e2\u30fc\u30c9": 11, "\u30d0\u30b0": [2, 4, 32], "\u30d0\u30c3\u30af\u30b9\u30b9\u30e9\u30c3\u30b7\u30e5": 30, "\u30d0\u30c3\u30af\u30b9\u30e9\u30c3\u30b7\u30e5": [7, 30, 31], "\u30d0\u30c3\u30af\u30b9\u30e9\u30c3\u30b7\u30e5\u30ad\u30fc": 5, "\u30d0\u30fc": [27, 29], "\u30d1\u30a4": 14, "\u30d1\u30b9": [11, 28, 31, 32], "\u30d1\u30bd\u30b3\u30f3": 0, "\u30d1\u30bf\u30fc\u30f3": [21, 30, 32], "\u30d1\u30e9\u30e1\u30fc\u30bf": 21, "\u30d1\u30ec\u30c3\u30c8": 27, "\u30d2\u30b9\u30c8\u30b0\u30e9\u30e0": [31, 32], "\u30d2\u30f3\u30c8": [6, 18], "\u30d2\u30fc\u30c8\u30de\u30c3\u30d7": [31, 32], "\u30d3\u30c3\u30c8": [1, 26], "\u30d3\u30f3": 27, "\u30d4\u30ea\u30aa\u30c9": 30, "\u30d5\u30a1\u30a4\u30eb": [0, 4, 12, 13, 15, 16, 18, 19, 22, 28, 30, 31, 32], "\u30d5\u30a1\u30a4\u30eb\u30aa\u30d6\u30b8\u30a7\u30af\u30c8": [11, 18, 19, 26, 31, 32], "\u30d5\u30a1\u30a4\u30eb\u30b5\u30a4\u30ba": 16, "\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0": 15, "\u30d5\u30a1\u30a4\u30eb\u30c7\u30fc\u30bf": 13, "\u30d5\u30a1\u30a4\u30eb\u30de\u30cd\u30fc\u30b8\u30e3": 28, "\u30d5\u30a1\u30a4\u30eb\u30e1\u30cb\u30e5\u30fc": 0, "\u30d5\u30a3\u30c3\u30c6\u30a3\u30f3\u30b0": 26, "\u30d5\u30a3\u30dc\u30ca\u30c3\u30c1": 3, "\u30d5\u30a3\u30fc\u30c8": 2, "\u30d5\u30a3\u30fc\u30eb\u30c9": 22, "\u30d5\u30a9\u30eb\u30c0": [13, 28, 32], "\u30d5\u30a9\u30f3\u30c8": 5, "\u30d5\u30a9\u30fc\u30de\u30c3\u30c8": 22, "\u30d5\u30e9\u30c3\u30c8": 17, "\u30d6\u30e9\u30a6\u30b6": [0, 15, 27], "\u30d6\u30ed\u30c3\u30af": 9, "\u30d6\u30fc\u30eb": 20, "\u30d7\u30ec\u30a4\u30dc\u30bf\u30f3": [0, 1], "\u30d7\u30ed\u30b0\u30e9\u30de": 7, "\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0": [2, 4, 5, 6, 16, 19, 24, 32], "\u30d7\u30ed\u30b0\u30e9\u30e0": [1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 17, 25, 28], "\u30d7\u30ed\u30b0\u30e9\u30e0\u30b3\u30fc\u30c9": [4, 28], "\u30d7\u30ed\u30c3\u30c8": [27, 29], "\u30d7\u30ed\u30f3\u30d7\u30c8": 28, "\u30d8\u30c3\u30c0": 10, "\u30d8\u30ed\u30f3": 2, "\u30d9\u30af\u30bf\u30fc": 6, "\u30d9\u30af\u30c8\u30eb": 16, "\u30da\u30a2": [4, 8], "\u30da\u30fc\u30b8": [22, 27], "\u30dc\u30bf\u30f3": [0, 27], "\u30dc\u30c7\u30a3\u30de\u30b9": 2, "\u30dd\u30a4\u30f3\u30c8": 4, "\u30dd\u30f3\u30dd\u30b3\u30ca\u30fc": 18, "\u30dd\u30f3\u30dd\u30b3\u30d4\u30fc": 18, "\u30de\u30a6\u30b9\u30ab\u30fc\u30bd\u30eb": [0, 22], "\u30de\u30b7\u30f3": 13, "\u30de\u30b8\u30c3\u30af\u30b3\u30de\u30f3\u30c9": [25, 32], "\u30de\u30b8\u30c3\u30af\u30ca\u30f3\u30d0\u30fc": 4, "\u30de\u30b9": 27, "\u30de\u30c3\u30c1": [9, 30, 32], "\u30de\u30fc\u30ab": [27, 29], "\u30de\u30fc\u30b8": 24, "\u30de\u30fc\u30b8\u30bd\u30fc\u30c8": 31, "\u30df\u30b9": 4, "\u30e1\u30bd\u30c3\u30c9": [2, 9, 11, 12, 16, 17, 20, 21, 26, 27, 31, 32], "\u30e1\u30bf": 31, "\u30e1\u30c3\u30bb\u30fc\u30b8": [9, 11, 18], "\u30e1\u30cb\u30e5\u30fc": [0, 15, 22, 28], "\u30e1\u30e2\u30ea": [1, 17], "\u30e1\u30ea\u30c3\u30c8": 30, "\u30e1\u30f3\u30d0\u30fc": 26, "\u30e1\u30f3\u30d0\u30fc\u30c7\u30fc\u30bf": 26, "\u30e2\u30b8\u30e5\u30fc\u30eb": [9, 16, 19, 20, 21, 25, 26, 27, 29, 30, 31, 32], "\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb": [28, 31], "\u30e2\u30b8\u30e5\u30fc\u30eb\u30ec\u30d9\u30eb": [2, 32], "\u30e2\u30c1\u30d9\u30fc\u30b7\u30e7\u30f3": 25, "\u30e2\u30c7\u30eb": 31, "\u30e2\u30fc\u30c9": [11, 26, 31, 32], "\u30e6\u30cb\u30d0\u30fc\u30b5\u30eb": 32, "\u30e6\u30fc\u30af\u30ea\u30c3\u30c9\u30ce\u30eb\u30e0": 16, "\u30e6\u30fc\u30b6\u30fc\u30a2\u30ab\u30a6\u30f3\u30c8": 28, "\u30e6\u30fc\u30c6\u30a3\u30ea\u30c6\u30a3": 28, "\u30e9\u30a4\u30bf\u30fc": [26, 32], "\u30e9\u30a4\u30d6\u30e9\u30ea": [1, 14, 28, 31, 32], "\u30e9\u30a4\u30d6\u30e9\u30ea\u30e2\u30b8\u30e5\u30fc\u30eb": 28, "\u30e9\u30d9\u30eb": [20, 21, 25, 27, 29], "\u30e9\u30d9\u30eb\u30c7\u30fc\u30bf": 21, "\u30e9\u30e0\u30c0": [31, 32], "\u30e9\u30f3\u30c0\u30e0": [23, 27, 29], "\u30ea\u30b9\u30c8": [3, 7, 10, 12, 16, 20, 23, 25, 26, 27, 28, 29, 30, 31, 32], "\u30ea\u30b9\u30c8a": 29, "\u30ea\u30b9\u30c8x": 29, "\u30ea\u30b9\u30c8y": 29, "\u30ea\u30bb\u30c3\u30c8": 27, "\u30ea\u30f3\u30af": 30, "\u30ea\u30fc\u30c0": [26, 29, 32], "\u30eb\u30fc\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea": 13, "\u30eb\u30fc\u30d7": [8, 9, 10, 32], "\u30eb\u30fc\u30eb": 11, "\u30ec\u30d9\u30eb": [4, 7], "\u30ed\u30b0\u30a4\u30f3": 0, "\u30ed\u30b8\u30b9\u30c6\u30a3\u30c3\u30af": [21, 32], "\u30ed\u30fc\u30ab\u30eb": [4, 9, 10, 31, 32], "\u30ef\u30a4\u30eb\u30c9\u30ab\u30fc\u30c9": [14, 15, 32], "\u30ef\u30fc\u30ad\u30f3\u30b0\u30c7\u30a3\u30ec\u30af\u30c8\u30ea": [13, 32], "\u30fblinux": 13, "\u30fbmacos": 13, "\u30fb\u30af\u30e9\u30b9\u30bf\u30ea\u30f3\u30b0": [31, 32], "\u30fb\u30bf\u30d6": 5, "\u30fb\u30bf\u30d7\u30eb": [8, 12, 31, 32], "\u30fb\u30c6\u30b9\u30c8": [31, 32], "\u30fb\u30dd\u30a2\u30bd\u30f3": 16, "\u30fb\u30e1\u30bd\u30c3\u30c9": [4, 31], "\u30fb\u30e9\u30d9\u30eb": 20, "\u30fb\u30e9\u30d9\u30eb\u30c7\u30fc\u30bf": 21, "\u30fb\u30ea\u30b9\u30c8": 9, "\u30fb\u5168\u89d2": 5, "\u30fb\u523b\u307f\u5e45": 16, "\u30fb\u6539\u884c": 5, "\u30fb\u6700\u5927\u5024": 16, "\u30fb\u7b97\u8853": 16, "\u30fb\u7d42\u4e86\u5024": 16, "\u30fb\u95a2\u6570\u540d": 4, "\u4e00\u5b9a": 9, "\u4e00\u5ea6": [1, 2, 6, 9, 11, 12, 15], "\u4e00\u5ea6for": 9, "\u4e00\u6027": [31, 32], "\u4e00\u62ec": 11, "\u4e00\u6587": 30, "\u4e00\u6587\u5b57": [6, 9, 22, 30], "\u4e00\u65b9": [6, 8, 9, 10, 12, 13, 15, 16, 28], "\u4e00\u65e6": 6, "\u4e00\u6642": 17, "\u4e00\u6bb5\u4e0a": 13, "\u4e00\u6bb5\u4e0b": 13, "\u4e00\u756a": [5, 6, 9, 29], "\u4e00\u756a\u4e0a": 14, "\u4e00\u756a\u5f8c\u308d": 9, "\u4e00\u758b": 11, "\u4e00\u77ac": 9, "\u4e00\u7a2e": [2, 11, 18, 19], "\u4e00\u81f4": [9, 20], "\u4e00\u81f4\u3057": 9, "\u4e00\u822c": [0, 1, 3, 4, 5, 6, 7, 9, 10, 12, 13, 15, 18, 19, 20, 24, 28, 30], "\u4e00\u822c\u5f62": 10, "\u4e00\u884c": [7, 17, 30], "\u4e00\u884c\u305a\u3064": 12, "\u4e00\u898b": 16, "\u4e00\u89a7": [9, 10, 16, 32], "\u4e00\u9023": 8, "\u4e00\u90ce": 26, "\u4e00\u90e8": [5, 10], "\u4e00\u91cd": 9, "\u4e09\u89d2\u5f62": 2, "\u4e09\u8fba": 2, "\u4e0a\u3052\u308b": 4, "\u4e0a\u3068": 5, "\u4e0a\u624b": 16, "\u4e0a\u65b9": [0, 22], "\u4e0a\u66f8\u304d": [11, 14, 16], "\u4e0a\u8a18": [2, 3, 5, 6, 10, 21, 24, 27, 28, 29, 30], "\u4e0a\u8ff0": 6, "\u4e0b\u3055\u3044": 11, "\u4e0b\u6841": 9, "\u4e0b\u7e70\u308a": 30, "\u4e0b\u8a18": [5, 9, 28, 30], "\u4e0b\u90e8": 0, "\u4e0d\u4fbf": 30, "\u4e0d\u53ef\u80fd": [5, 6, 8], "\u4e0d\u53ef\u907f": 1, "\u4e0d\u601d\u8b70": 30, "\u4e0d\u6210\u7acb": 4, "\u4e0d\u6b63": 4, "\u4e0d\u7279\u5b9a": 27, "\u4e0d\u8981": [4, 7], "\u4e0e\u3048": [2, 4, 5, 6, 8, 9, 10, 11, 12, 16, 17, 18, 19, 23, 24, 25, 26, 28, 29], "\u4e0e\u3048\u308b": [4, 5, 7, 8, 9, 12, 16, 18, 19, 28, 29], "\u4e0e\u3048\u308c": 30, "\u4e21\u65b9": [1, 28, 29], "\u4e21\u8005": [1, 6, 16], "\u4e21\u8fba": 12, "\u4e26\u3073": [5, 6, 16, 30, 31, 32], "\u4e26\u3076": [27, 29], "\u4e26\u3079": [5, 6, 14, 16], "\u4e26\u3079\u66ff\u3048": [30, 32], "\u4e2d\u592e": 4, "\u4e2d\u65ad": 9, "\u4e2d\u8eab": [26, 28, 29, 30], "\u4e38\u3081": 29, "\u4e38\u62ec": [6, 7, 30], "\u4e38\u62ec\u5f27": 30, "\u4e3b\u6210": 21, "\u4e57\u7b97": 16, "\u4e57\u8a08": 24, "\u4e71\u6570": [16, 27], "\u4e88\u60f3": 7, "\u4e88\u6e2c": 21, "\u4e88\u7d04": 32, "\u4e88\u9632": 4, "\u4e8b\u524d": 10, "\u4e8b\u5b9f": 16, "\u4e8b\u60c5": 28, "\u4e8b\u67c4": 4, "\u4e8c\u4e57": [4, 21], "\u4e8c\u4eba": 11, "\u4e8c\u6b21": 2, "\u4e8c\u6b21\u65b9\u7a0b\u5f0f": 2, "\u4e8c\u756a\u76ee": 7, "\u4e8c\u758b\u3064\u308c": 11, "\u4e8c\u91cd": [6, 9], "\u4e8c\u91cd\u30eb\u30fc\u30d7": 9, "\u4e8c\u9805": 16, "\u4e91\u3072": 11, "\u4e9b\u7d30": 4, "\u4eca\u5f8c": 3, "\u4ed5\u69d8": [31, 32], "\u4ed5\u7d44": [2, 25, 31], "\u4ed5\u7d44\u307f": 4, "\u4ed8\u3044": [0, 31], "\u4ed8\u304b": [0, 6, 22], "\u4ed8\u304d": [2, 6, 10, 18, 22, 27, 31, 32], "\u4ed8\u304f": [3, 22], "\u4ed8\u3051": [2, 4, 6, 8, 10, 14, 19, 20, 23, 28, 30], "\u4ed8\u3051\u308b": [2, 14, 27], "\u4ed8\u4e0e": [16, 19], "\u4ed8\u52a0": 2, "\u4ed8\u9332": 9, "\u4ed8\u968f": 4, "\u4ee3\u308f\u308a": [1, 4, 5, 9, 10, 16, 17, 20, 29], "\u4ee3\u5165": [3, 4, 5, 8, 9, 10, 12, 14, 16, 19, 20, 23, 31, 32], "\u4ee3\u5165\u6587": 32, "\u4ee3\u6570": [31, 32], "\u4ee3\u8868": [4, 16], "\u4ee5\u4e0a": [1, 2, 3, 5, 9, 16, 17, 18, 24, 27, 29, 30], "\u4ee5\u4e0b": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], "\u4ee5\u524d": 11, "\u4ee5\u5916": [2, 6, 7, 11, 13, 16, 26, 30], "\u4ee5\u964d": [1, 2, 6, 7, 9, 11, 29], "\u4eee\u5b9a": [2, 4, 15, 26], "\u4eee\u5f15": 10, "\u4eee\u5f15\u6570": [2, 10, 32], "\u4eee\u60f3": 13, "\u4efb\u610f": [2, 5, 10, 16, 20, 21, 27, 28, 29], "\u4f1d\u3048\u308b": 0, "\u4f3c\u305f": 17, "\u4f4d\u7f6e": [2, 4, 5, 6, 7, 10, 16, 20, 27, 29], "\u4f4e\u3044": [4, 21], "\u4f53\u611f": 2, "\u4f53\u91cd": 2, "\u4f55\u3089\u304b": [10, 13, 30], "\u4f55\u5ea6": 12, "\u4f55\u6545": 10, "\u4f55\u756a": 0, "\u4f59\u308a": [1, 3, 32], "\u4f5c\u3063": [6, 19, 26], "\u4f5c\u3089": 19, "\u4f5c\u3089\u308c": [0, 5, 6, 16, 17, 19, 22, 30], "\u4f5c\u308a": [6, 12, 19, 26], "\u4f5c\u308a\u65b9": [31, 32], "\u4f5c\u308b": [6, 8, 9, 15, 17, 19, 26, 30], "\u4f5c\u6210": [5, 6, 8, 9, 11, 16, 17, 18, 19, 21, 22, 23, 26, 27, 28, 29, 30, 31, 32], "\u4f5c\u696d": [9, 13, 20, 24, 32], "\u4f75\u305b": [20, 27, 29], "\u4f75\u5408": 24, "\u4f75\u7528": 16, "\u4f7f\u3044": [0, 1, 5, 6, 11, 12, 14, 15, 19, 22, 26, 27], "\u4f7f\u3044\u65b9": [6, 20, 21, 25, 31, 32], "\u4f7f\u3046": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 23, 26, 28, 30], "\u4f7f\u3048": [0, 1, 5, 6, 9, 11, 18, 22, 27], "\u4f7f\u3048\u308b": 16, "\u4f7f\u304a": [10, 30], "\u4f7f\u3063": [1, 2, 6, 7, 9, 10, 11, 12, 14, 16, 18, 21, 24, 25, 26, 27, 28, 29, 30], "\u4f7f\u308f": [2, 4, 6, 8, 9, 11, 19, 28, 31], "\u4f7f\u308f\u305a": [3, 5], "\u4f7f\u7528": [0, 5, 8, 11, 14, 20, 21, 26, 27, 29], "\u4f8b\u3048": 1, "\u4f8b\u3068\u3057\u3066": [6, 18, 21], "\u4f8b\u306b": 7, "\u4f8b\u5916": [4, 12], "\u4fbf\u5229": [2, 7, 15, 20, 27, 30], "\u4fc3\u3059": 28, "\u4fdd\u3061": 24, "\u4fdd\u5b58": [0, 15, 27, 28, 29, 30, 31, 32], "\u4fdd\u5b88": [15, 28], "\u4fdd\u6301": [16, 20], "\u4fee\u6b63": [1, 2, 7], "\u500b\u3005": [14, 19, 21, 24], "\u500b\u4eba": 0, "\u500b\u542b": 30, "\u500b\u5ba4": 11, "\u500b\u6240": 6, "\u500b\u6570": [10, 18], "\u500d\u6570": 9, "\u5012\u308c\u308b": 11, "\u5024\u3068": [1, 3, 5, 6, 7, 9, 19, 20, 25, 26, 27, 29, 30], "\u5024\u3068\u3057": 8, "\u5024\u3068\u3057\u3066": [2, 3, 8, 26, 27, 29], "\u5024\u5217": 20, "\u5024\u540c": 1, "\u5024\u6f14": 1, "\u5024\u8aa4": 32, "\u5024\u914d": [20, 31, 32], "\u504f\u5dee": 20, "\u505c\u6b62": [4, 8, 9, 12, 22], "\u5074\u9762": 4, "\u5076\u6570": [6, 9, 16], "\u507d\u3068": 3, "\u50cd\u304d": [6, 11], "\u512a\u5148": [31, 32], "\u5143\u3005": 2, "\u5143\u8868": 16, "\u5143\u914d": [20, 21, 32], "\u5144\u5f1f": [13, 32], "\u5145\u5206": 27, "\u5148url": 30, "\u5148\u982d": [5, 7, 9, 11, 13, 16, 20, 30, 31], "\u5165\u3063": [9, 11, 19, 22, 26, 29], "\u5165\u308a": [0, 11], "\u5165\u308b": [2, 12], "\u5165\u308c": [4, 5, 6, 9, 30], "\u5165\u308c\u308b": [1, 2, 4, 7, 9], "\u5165\u308c\u5b50": [2, 7, 13, 16, 31, 32], "\u5165\u308c\u5b50\u30ea\u30b9\u30c8": 16, "\u5165\u51fa": [4, 31], "\u5165\u529b": [0, 1, 2, 7, 10, 21, 22, 24, 28, 31], "\u5165\u53e3": 4, "\u5165\u624b": 30, "\u5168\u304f": [15, 16, 28], "\u5168\u3066": [5, 6, 9, 11, 14, 15, 17, 19, 21, 23, 30], "\u5168\u4f53": [0, 6, 9, 10, 13, 24, 26, 30, 31, 32], "\u5168\u822c": 4, "\u5168\u8981": [16, 17], "\u5168\u89d2": [4, 26], "\u5168\u90e8": 21, "\u516c\u5f0f": [2, 4, 11, 12, 15, 28], "\u516c\u5f0ffaq": 10, "\u516c\u6bd4": 9, "\u5171\u306b": [7, 9, 17], "\u5171\u6709": [0, 16], "\u5171\u901a": [11, 13], "\u5175\u968a": 11, "\u5177\u4f53": [5, 6, 8, 9, 12, 14, 16, 29, 30, 31], "\u5177\u4f53\u4f8b": 7, "\u5177\u5408": 30, "\u5178\u578b": [1, 4, 6, 19, 24, 30], "\u5185\u3069": 10, "\u5185\u5074": [9, 16, 30], "\u5185\u5305": [6, 9, 18, 31, 32], "\u5185\u5bb9": [4, 6, 7, 8, 9, 11, 13, 15, 16, 26, 28, 30], "\u5185\u7a4d": 16, "\u5185\u7dda": 30, "\u5185\u90e8": [11, 15, 16], "\u518d\u3073": 7, "\u518d\u5165": 2, "\u518d\u5229": [10, 15], "\u518d\u5b9a": [2, 19], "\u518d\u5b9f\u884c": 11, "\u518d\u5e30": [31, 32], "\u518d\u5e30\u547c": 24, "\u518d\u5ea6": [9, 11, 12], "\u5192\u982d": [8, 11, 25], "\u51aa\u6307\u6570": 24, "\u51e1\u4f8b": [27, 29], "\u51e6\u7406": [2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 21, 24, 25, 30, 31], "\u51fa\u3057": [24, 28, 32], "\u51fa\u305f\u308a": [5, 11], "\u51fa\u3066": 2, "\u51fa\u307e\u305b": 11, "\u51fa\u308c": 6, "\u51fa\u529b": [2, 6, 7, 15, 18, 25, 31, 32], "\u51fa\u7248": 9, "\u51fa\u73fe": [1, 2, 5, 6, 9, 30], "\u51fa\u8eab\u5730": 26, "\u5206\u304b\u308a": 4, "\u5206\u304b\u308b": 11, "\u5206\u3051": [4, 21, 27], "\u5206\u3051\u308b": 21, "\u5206\u5148": 12, "\u5206\u5206": 21, "\u5206\u5272": [7, 15, 16, 21, 24, 27, 30, 32], "\u5206\u5c90": [28, 30, 31, 32], "\u5206\u5e03": [9, 16, 21, 27, 29], "\u5206\u6563": [9, 17], "\u5206\u6790": [4, 20], "\u5206\u89e3": [16, 30], "\u5206\u90e8": 30, "\u5206\u91ce": 16, "\u5206\u96e2": 21, "\u5206\u985e": [5, 27, 31, 32], "\u5207\u308a": [9, 12], "\u5207\u308a\u51fa\u3057": [15, 30], "\u5207\u308a\u6368\u3066": 1, "\u5217a": [5, 30], "\u5217b": [5, 30], "\u5217it": 30, "\u5217\u3068\u3057\u3066": 21, "\u5217\u4e0a": 30, "\u5217\u4e2d": 5, "\u5217\u5024": 16, "\u5217\u5168": [6, 30], "\u5217\u51e6": 6, "\u5217\u540c": 5, "\u5217\u540d": 20, "\u5217\u578b": 28, "\u5217\u5909": 5, "\u5217\u6319": 16, "\u5217\u6570": 16, "\u5217\u65b9": 20, "\u5217\u7248": 16, "\u5217\u76ee": [20, 21, 26, 29], "\u5217\u7d50\u5408": 28, "\u521d\u5fc3\u8005": [31, 32], "\u521d\u671f": [31, 32], "\u521d\u671f\u5024": [31, 32], "\u521d\u671f\u5316": [9, 19, 30, 32], "\u521d\u671f\u6642": 19, "\u521d\u9805": 9, "\u5224\u5225\u5f0f": 2, "\u5224\u5b9a": [6, 9, 23, 24, 30], "\u5224\u65ad": [6, 7, 16], "\u5224\u660e": 4, "\u5225\u3005": 6, "\u5225\u3082\u306e": 2, "\u5225\u540d": [16, 20, 29], "\u5225\u89e3": [9, 30], "\u5229\u7528": [2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 25, 28, 30], "\u5230\u9054": [2, 12], "\u5236\u5fa1": [2, 3, 7, 31, 32], "\u523b\u307f": [1, 9, 16, 27, 29], "\u523b\u307f\u5e45": 16, "\u524a\u6e1b": [31, 32], "\u524a\u9664": [0, 2, 4, 22, 23, 30, 31, 32], "\u524d\u51e6": 21, "\u524d\u534a": [5, 30], "\u524d\u5f8c": [4, 5, 16], "\u524d\u63d0": 4, "\u524d\u8005": 9, "\u524d\u8ff0": 2, "\u5270\u4f59": [1, 16, 32], "\u5272\u3063": [1, 2, 3], "\u5272\u308a": [2, 20, 29], "\u5272\u308a\u5f53\u3066": [2, 27], "\u5272\u308a\u5f53\u3066\u308b": 2, "\u5272\u308a\u7b97": [1, 32], "\u5272\u308a\u8fbc\u307f": 12, "\u52a0\u3048": [1, 5, 6, 8, 9, 11, 17, 28, 29], "\u52a0\u3048\u308b": [11, 30], "\u52a0\u5de5": 5, "\u52a0\u7b97": [16, 28], "\u52b9\u679c": [19, 27], "\u52b9\u7387": [6, 16, 17, 24], "\u52d5\u3044": 13, "\u52d5\u304b": 17, "\u52d5\u304b\u3057": 17, "\u52d5\u304d": 4, "\u52d5\u304f": [9, 18], "\u52d5\u4f5c": [4, 7, 9, 13, 25, 31], "\u52d5\u7684": 8, "\u52d8\u9055\u3044": 4, "\u52ff\u8ad6": 30, "\u5305\u542b": [13, 23], "\u5316\u3051": [11, 26], "\u5316\u624b": 21, "\u533a\u5207": [6, 16, 17, 26], "\u533a\u5207\u3063": [6, 11, 13, 14, 26, 28], "\u533a\u5207\u308a": [2, 6, 9, 10, 11, 13, 16, 30], "\u533a\u5207\u308b": 30, "\u533a\u5225": [23, 28, 30], "\u5341\u5206": 16, "\u5341\u5b57": 27, "\u534a\u5206": [2, 24], "\u534a\u89d2": [1, 4, 5, 7, 11, 26, 32], "\u5358\u306a\u308b": [16, 30], "\u5358\u4f4d": [6, 15, 16], "\u5358\u72ec": [27, 28], "\u5358\u7d14": [2, 24], "\u5358\u8a9e": [2, 9, 23, 30], "\u5358\u9805": 32, "\u5370\u5b57": [2, 4, 9, 10, 11, 16, 28, 30, 32], "\u5373\u5ea7": [3, 12, 19], "\u539f\u5247": [10, 11, 15], "\u539f\u56e0": 4, "\u539f\u59cb": 11, "\u53b3\u5bc6": 29, "\u53c2\u7167": [1, 3, 4, 5, 6, 8, 9, 10, 11, 12, 14, 15, 16, 18, 19, 27, 28, 29, 30, 31, 32], "\u53c2\u7167\u304f": 9, "\u53c2\u8003": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 28, 29, 30], "\u53ca\u3073\u4ed6": 27, "\u53ca\u307c": 16, "\u53ca\u307c\u3059": 10, "\u53cd\u3057": 4, "\u53cd\u5fa9": [16, 31, 32], "\u53cd\u5fa9\u5b50": 12, "\u53cd\u5fdc": 31, "\u53cd\u6620": 4, "\u53d6\u3063": [6, 18], "\u53d6\u308a": [6, 9, 10, 12, 16, 18, 29, 30], "\u53d6\u308a\u4e0a\u3052\u308b": 25, "\u53d6\u308a\u51fa\u3055": [6, 9, 12], "\u53d6\u308a\u51fa\u3057": [6, 9, 12, 16, 23, 30, 31, 32], "\u53d6\u308a\u51fa\u3059": [6, 8, 9, 12, 16, 23, 26], "\u53d6\u308a\u51fa\u305b": [6, 8, 12], "\u53d6\u308a\u6271\u3046": 6, "\u53d6\u308a\u6271\u3048": 5, "\u53d6\u308a\u9664\u304f": [4, 5], "\u53d6\u308b": [2, 4, 5, 10, 18, 26], "\u53d6\u308c\u308b": 17, "\u53d6\u5f97": [4, 5, 8, 11, 20, 21, 30, 32], "\u53d7\u3051": [2, 6, 8, 10, 12, 18, 26], "\u53d7\u3051\u308b": 6, "\u53d7\u3051\u53d6\u3063": [10, 18], "\u53d7\u3051\u53d6\u308a": 10, "\u53e5\u8aad": [5, 9, 23, 30], "\u53e5\u8aad\u70b9": 23, "\u53ef\u5426": 8, "\u53ef\u5909": [31, 32], "\u53ef\u5909\u9577": 10, "\u53ef\u80fd": [0, 2, 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 17, 19, 21, 22, 23, 26, 28, 29, 30], "\u53ef\u8996": [21, 27, 29, 31], "\u53ef\u8aad": 4, "\u53f3\u4e0a": [0, 22], "\u53f3\u5074": [1, 5, 6], "\u53f3\u56de\u308a": 22, "\u53f3\u8fba": [2, 16, 19], "\u5404\u5217": [16, 20, 21], "\u5404\u5834\u5408": 9, "\u5404\u5869": 6, "\u5404\u5b50": 9, "\u5404\u624b": 21, "\u5404\u6570": 20, "\u5404\u6587": 5, "\u5404\u6708": 29, "\u5404\u6b21": [16, 21], "\u5404\u70b9": 29, "\u5404\u7a2e": [0, 1, 17, 25], "\u5404\u7dda": 29, "\u5404\u82b1": 21, "\u5404\u884c": [12, 16, 18, 20, 21, 26, 29], "\u5404\u8981": [6, 8, 9, 16, 17, 18, 27, 29], "\u5404\u8981\u7d20": [16, 18], "\u5404\u8ef8": 29, "\u5408\u308f": [27, 29], "\u5408\u308f\u305b": 10, "\u5408\u6210": 24, "\u5408\u8a08": 2, "\u540c\u3058": [2, 3, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 19, 21, 22, 23, 25, 26, 27, 28, 29, 30], "\u540c\u3058\u304f": [11, 16], "\u540c\u3058\u5024": [6, 16, 19, 20], "\u540c\u3058\u5f62": 19, "\u540c\u3058\u6570": 1, "\u540c\u3058\u6df1\u3055": 2, "\u540c\u3058\u9577\u3055": 6, "\u540c\u540d": 10, "\u540c\u58eb": [1, 32], "\u540c\u6642": [8, 10, 14, 29], "\u540c\u69d8": [1, 2, 3, 5, 6, 8, 9, 10, 11, 12, 14, 16, 18, 19, 20, 23, 26, 29, 30], "\u540c\u7b49": 9, "\u540c\u7fa9": [3, 12], "\u540c\u8272": 27, "\u540d\u524d": [2, 4, 6, 10, 11, 14, 15, 16, 19, 26, 28], "\u540d\u53e4\u5c4b": 26, "\u540d\u79f0": [6, 14], "\u5411\u304b\u3063": 9, "\u5411\u304d": 29, "\u5426\u5b9a": [3, 6, 30, 32], "\u542b\u307e": [1, 3, 5, 6, 8, 9, 13, 20, 21, 23, 24, 29, 30], "\u542b\u307e\u308c": [4, 5, 6, 9, 24, 30], "\u542b\u307e\u308c\u3044": 30, "\u542b\u307e\u308c\u308b": [5, 6, 9, 23, 30], "\u542b\u3080": [5, 6, 9, 10, 12, 16, 23, 24, 26, 28, 30], "\u542b\u3080\u5f0f": 6, "\u542b\u3081": [2, 13, 18, 30], "\u542b\u3081\u308b": 2, "\u542b\u3093": [9, 15], "\u5468\u308a": 0, "\u5468\u7387": 1, "\u5468\u8fba": 30, "\u547c\u3070": [4, 6, 10, 11, 12, 13, 18, 21, 24, 28], "\u547c\u3073": [2, 9, 12, 13, 16], "\u547c\u3073\u51fa\u3055": [19, 26, 27], "\u547c\u3073\u51fa\u3055\u305a": 11, "\u547c\u3073\u51fa\u3057": [2, 5, 6, 10, 11, 19, 24], "\u547c\u3073\u51fa\u3057\u5143": 2, "\u547c\u3073\u51fa\u3059": [2, 6, 10, 11, 19, 24, 26], "\u547c\u3073\u51fa\u3059\u6bce\u306b": 12, "\u547c\u3073\u51fa\u3059\u969b": 10, "\u547c\u3073\u51fa\u3059\u969b\u306b": 10, "\u547c\u3076": [5, 10, 11, 13, 29], "\u547c\u3093": [9, 11, 18, 27], "\u548c\u3084": 30, "\u548c\u3088\u308a": 30, "\u548c\u6f14": 30, "\u548c\u7d00": 9, "\u548c\u96c6\u5408": [23, 32], "\u5531\u3048": 1, "\u554f\u984c": [2, 4, 6, 11, 21, 24], "\u554f\u984c\u6587": 30, "\u56db\u89d2": 0, "\u56de\u3060\u3051": 10, "\u56de\u3084\u3063": 19, "\u56de\u308a\u7d9a\u3051": 0, "\u56de\u4ee5": 30, "\u56de\u542b": 5, "\u56de\u547c\u3073\u51fa\u3057": 24, "\u56de\u5b9f\u884c": 9, "\u56de\u5e30": [26, 31, 32], "\u56de\u6570": [5, 6, 9, 19, 24], "\u56de\u73fe": 6, "\u56de\u76ee": 8, "\u56de\u7e70\u308a\u8fd4\u3055": 6, "\u56de\u907f": [8, 30], "\u56f2\u307e": [0, 5, 30], "\u56f2\u307f": [6, 23], "\u56f2\u3080": 5, "\u56f2\u308f": 26, "\u56f2\u3093": 5, "\u56f3\u5f62": 27, "\u5727\u7e2e": 16, "\u5730\u4f4d": 16, "\u5782\u76f4": 25, "\u578b\u3068": 19, "\u578b\u540d": 16, "\u57fa\u3065\u3044": [4, 20], "\u57fa\u3065\u304d": 21, "\u57fa\u3065\u304f": [20, 27, 29], "\u57fa\u672c": [2, 3, 10, 16, 20, 21, 24, 27, 29, 31, 32], "\u57fa\u6e96": 5, "\u57fa\u790e": 31, "\u5834\u5408": [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 23, 24, 26, 27, 28, 29, 30, 32], "\u5834\u6240": [4, 10, 13, 19, 28], "\u5857\u3063": 27, "\u5869\u57fa": 5, "\u5883\u754c": [21, 27], "\u5897\u3048": [0, 9, 12], "\u5897\u3048\u308b": 0, "\u5897\u3084": [9, 28], "\u5897\u3084\u3059": [2, 9, 27, 29], "\u58ca\u7684": [31, 32], "\u5909\u3048\u308b": [0, 2, 7, 10, 28, 29], "\u5909\u308f\u3063": 30, "\u5909\u308f\u308a": [2, 4, 8], "\u5909\u308f\u308b": [2, 5, 28], "\u5909\u5316": [2, 5, 6, 10, 13, 27, 30], "\u5909\u63db": [2, 4, 5, 9, 11, 16, 17, 18, 23, 26, 29, 30, 31, 32], "\u5909\u6570": [1, 3, 4, 6, 8, 9, 11, 12, 14, 17, 19, 26, 28, 30, 31, 32], "\u5909\u66f4": [0, 2, 5, 6, 7, 8, 9, 10, 13, 14, 19, 20, 22, 28, 29], "\u5909\u66f4\u5f8c": 2, "\u5916\u5074": [6, 9, 16, 17], "\u591a\u3044": [5, 11, 24, 27, 29], "\u591a\u304f": [4, 5, 6, 20], "\u591a\u6570": [16, 19], "\u591a\u6b21": [20, 32], "\u591a\u6b21\u5143": 16, "\u591a\u7528": 16, "\u591a\u8a00": 5, "\u591a\u91cd": [9, 23, 31, 32], "\u5927\u304d": [1, 9], "\u5927\u304d\u3044": [3, 5, 6, 9, 17, 18], "\u5927\u304d\u304f": [2, 4, 5, 9, 15, 16, 20], "\u5927\u304d\u3051\u308c": [3, 6], "\u5927\u304d\u3055": [9, 17, 27, 29], "\u5927\u4e08\u592b": 30, "\u5927\u4f53": 2, "\u5927\u5206": 0, "\u5927\u5207": 4, "\u5927\u5b66": 9, "\u5927\u5c0f": [5, 6], "\u5927\u62b5": [4, 14, 17], "\u5927\u6587\u5b57": [2, 6, 9, 11, 23, 30, 32], "\u5927\u898f\u6a21": 16, "\u5929\u4e0b\u308a": 6, "\u592a\u5b57": [2, 9], "\u5931\u6557": [4, 30], "\u5947\u6570": 9, "\u59cb\u307e\u308a": [2, 6, 7, 12, 19, 20], "\u59cb\u307e\u308b": [1, 3, 5, 6, 7, 13, 14, 16, 20, 25, 30, 31], "\u59cb\u3081\u308b": [1, 2, 30], "\u5b50\u30ea\u30b9\u30c8": 9, "\u5b50\u5b6b": [13, 32], "\u5b50\u6271\u3044": 30, "\u5b57\u3057": 11, "\u5b57\u4e0b\u3052": 7, "\u5b57\u4ee5": [9, 30], "\u5b57\u5206": 30, "\u5b57\u5217": [3, 9, 11, 19, 30, 31, 32], "\u5b58\u5728": [4, 5, 8, 11, 13, 15, 21, 23, 28, 30], "\u5b66\u3073": 25, "\u5b66\u3076": 25, "\u5b66\u3093": [5, 9, 25], "\u5b66\u7fd2": [2, 14, 16, 30, 31, 32], "\u5b89\u5168": 11, "\u5b8c\u4e86": [9, 12], "\u5b8c\u6210": [6, 21], "\u5b8c\u7d50": 28, "\u5b9a\u307e\u308a": [6, 15], "\u5b9a\u3081": 5, "\u5b9a\u6570": [3, 32], "\u5b9a\u7fa9": [1, 3, 7, 9, 11, 13, 14, 15, 16, 17, 18, 24, 26, 30, 31, 32], "\u5b9f\u5f15": [4, 10], "\u5b9f\u5f15\u6570": [10, 32], "\u5b9f\u6570": [2, 5, 16, 29, 31, 32], "\u5b9f\u73fe": [4, 12, 16, 27, 29, 30], "\u5b9f\u884c": [1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 21, 22, 23, 25, 26, 29, 30, 31, 32], "\u5b9f\u884c\u5f8c": 8, "\u5b9f\u884c\u6587": [6, 9], "\u5b9f\u88c5": [6, 21, 24, 28], "\u5b9f\u90e8": 16, "\u5b9f\u969b": [3, 4, 5, 17, 18, 19, 21, 28], "\u5ba3\u8a00": [4, 31, 32], "\u5bb9\u6613": [24, 25], "\u5bfe\u51e6": 4, "\u5bfe\u5fdc": [5, 8, 9, 16, 17, 18, 21, 23, 25, 27, 29, 31, 32], "\u5bfe\u6570": 14, "\u5bfe\u79f0": 23, "\u5bfe\u79f0\u5dee": [23, 32], "\u5bfe\u8c61": [4, 6, 11, 23], "\u5c0e\u5165": [2, 4], "\u5c0f\u3055": [1, 24], "\u5c0f\u3055\u3044": [3, 5, 9, 20, 24, 29], "\u5c0f\u3055\u304f": [1, 2, 3], "\u5c0f\u6570": [1, 16, 26, 32], "\u5c0f\u6587\u5b57": [2, 11, 23, 30, 32], "\u5c11\u3057": 30, "\u5c11\u3057\u4f8b": 1, "\u5c11\u3057\u8a73\u3057\u3044": 11, "\u5c11\u306a\u304f": [27, 29], "\u5c11\u6570": 9, "\u5c3a\u5ea6": 9, "\u5c45\u3084": 11, "\u5c55\u958b": [9, 13], "\u5c5e\u3057": 7, "\u5c5e\u3059\u308b": 19, "\u5c5e\u6027": [20, 21, 27, 30, 31, 32], "\u5c5e\u6027\u540d": 19, "\u5c71\u53e3": 9, "\u5c71\u5965": 11, "\u5c71\u7530": 26, "\u5d29\u308c": 4, "\u5de6\u304b\u3089": 17, "\u5de6\u5074": [5, 16], "\u5de6\u53f3": [5, 30], "\u5de6\u7aef": 0, "\u5de6\u8fba": [2, 6, 9, 19], "\u5dee\u3057": 3, "\u5dee\u96c6\u5408": [23, 32], "\u5e30\u547c": [24, 32], "\u5e30\u95a2": [31, 32], "\u5e73\u5747": [9, 10, 16, 20, 21, 26, 29], "\u5e73\u65b9\u6839": [1, 14], "\u5e73\u9762": 6, "\u5e74\u4ee5\u964d": 29, "\u5e74\u6708": 29, "\u5e7e\u3064\u304b": [16, 30], "\u5e83\u304f": [7, 13, 25], "\u5e83\u5cf6": 26, "\u5e95base": 24, "\u5e95\u3068": 14, "\u5ea6\u540c": 9, "\u5ea7\u6a19": [6, 25], "\u5f0f\u304c": 10, "\u5f0f\u306a": 2, "\u5f0f\u306a\u3057": 10, "\u5f0f\u5168": 7, "\u5f15\u304d\u7b97": [1, 32], "\u5f15\u304d\u7b97\u3088\u308a": 1, "\u5f15\u304d\u8d77\u3053\u3057": 4, "\u5f15\u6570": [2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 16, 17, 18, 19, 20, 21, 23, 26, 27, 29, 30, 31, 32], "\u5f15\u7528": 9, "\u5f31\u304f": 1, "\u5f37\u3044": 1, "\u5f37\u304f": [1, 4, 30], "\u5f37\u3055": 30, "\u5f37\u5236": [0, 19], "\u5f37\u8abf": 2, "\u5f53\u3066": [20, 29], "\u5f53\u3066\u308b": 2, "\u5f62\u5f0f": [1, 2, 12, 16, 27, 30, 31, 32], "\u5f62\u72b6": 29, "\u5f6b\u308a": 4, "\u5f71\u97ff": [2, 6, 7, 8, 16], "\u5f79\u5272": [2, 30], "\u5f8c\u304b\u3089": 6, "\u5f8c\u3060": 11, "\u5f8c\u308d": [5, 9, 28, 30], "\u5f8c\u534a": [5, 30], "\u5f8c\u7d9a": 12, "\u5f8c\u8005": [6, 9], "\u5f8c\u8ff0": [1, 6, 11], "\u5f93\u3044": 2, "\u5f93\u3063": [5, 10, 28], "\u5f97\u305f\u3044": 5, "\u5f97\u3089": 9, "\u5f97\u3089\u308c": 6, "\u5f97\u308b": [1, 5, 32], "\u5f97\u610f": 6, "\u5fa9\u5143": [31, 32], "\u5fa9\u5e30": 11, "\u5fc5\u305a": [1, 2, 3, 13], "\u5fc5\u305a\u3057": [2, 4, 11, 20], "\u5fc5\u305a\u65b0\u3057\u3044": 6, "\u5fc5\u305a\u7570": 9, "\u5fc5\u8981": [0, 1, 4, 5, 6, 7, 9, 10, 11, 14, 15, 16, 18, 23, 25, 27, 28, 29, 30], "\u5fd8\u308c": [2, 4, 11, 26], "\u5fdc\u3058": [2, 4, 5, 6, 7, 12, 27, 29], "\u5fdc\u7528": 27, "\u601d\u3044": [18, 26, 30], "\u601d\u3046": 30, "\u601d\u3063": 3, "\u601d\u308f": 25, "\u602a\u3057": 11, "\u60c5\u5831": [6, 9, 16, 20, 21, 30], "\u60f3\u5b9a": [11, 16, 28], "\u610f\u5473": [0, 1, 2, 4, 5, 6, 11, 12, 13, 16, 19, 26, 28, 30], "\u610f\u56f3": [4, 6, 7, 30], "\u6163\u4f8b": [19, 20, 29], "\u6163\u7fd2": 16, "\u6210\u3059": 13, "\u6210\u308a\u7acb\u305f": 3, "\u6210\u308a\u7acb\u3061": [1, 3], "\u6210\u308a\u7acb\u3063": [0, 3, 22], "\u6210\u308a\u7acb\u3064": 3, "\u6210\u308b": [1, 2, 5, 6, 9, 30], "\u6210\u529f": 12, "\u6210\u7acb": [9, 30], "\u623b\u3055": 7, "\u623b\u3057": [9, 24], "\u623b\u3059": [7, 16], "\u623b\u3063": 9, "\u623b\u308b": [7, 13], "\u6240\u5b9a": 16, "\u6240\u5c5e": 21, "\u624b\u7d9a\u304d": [6, 8, 9, 10, 21], "\u624b\u9806": [9, 21], "\u6253\u3061": 29, "\u6253\u3061\u5207\u3089\u308c": 9, "\u6271\u3044": [2, 3, 19, 31], "\u6271\u3046": [1, 3, 5, 6, 8, 9, 16, 30], "\u6271\u3048": 26, "\u6271\u3048\u308b": [12, 16], "\u6271\u3063": [4, 15], "\u6271\u308f": [1, 2, 3, 5, 7, 10, 13, 26, 30], "\u6280\u8853": 16, "\u628a\u63e1": 9, "\u6291\u5236": [7, 29], "\u6295\u3052": 19, "\u6298\u308c": 31, "\u629c\u304d\u51fa\u3057": 6, "\u629c\u304d\u51fa\u3059": 30, "\u629c\u3051": 9, "\u629c\u3051\u308b": [9, 10], "\u62bc\u3057": [0, 1, 22], "\u62bc\u3059": [0, 1], "\u62bc\u305b": 0, "\u62bd\u51fa": 20, "\u62e1\u5f35": [5, 6], "\u62e1\u5f35\u5b50": [0, 15, 16, 22, 28], "\u62ec\u3089": 7, "\u62ec\u308b": 7, "\u62ec\u5f27": [2, 4, 5, 6, 8, 10, 19, 30, 31, 32], "\u6301\u3061": [2, 3, 7, 9, 15, 17, 19, 21], "\u6301\u3063": [0, 27], "\u6301\u3064": [2, 5, 6, 9, 10, 12, 13, 16, 17, 18, 19, 21, 29, 30], "\u6301\u3064\u5b50\u30ea\u30b9\u30c8": 9, "\u6301\u3064\u7d44\u307f\u8fbc\u307f": 17, "\u6301\u3064\u884c": 20, "\u6307\u3057": [4, 11, 13, 24, 28], "\u6307\u3057\u793a\u3057": 2, "\u6307\u3057\u793a\u3059": 2, "\u6307\u3057\u793a\u3059\u5024": 2, "\u6307\u3059": 19, "\u6307\u5411": [19, 32], "\u6307\u5b9a": [0, 1, 3, 5, 9, 10, 12, 13, 14, 16, 18, 19, 20, 21, 23, 26, 27, 28, 29, 30, 31, 32], "\u6307\u6570": 2, "\u6307\u6a19": 9, "\u6319\u3052": 4, "\u631f\u3093": 30, "\u632f\u3089": 22, "\u632f\u308b": [2, 22], "\u632f\u821e": [19, 28], "\u632f\u821e\u3044": [4, 9, 12, 16, 28, 31], "\u633f\u5165": [1, 7, 22, 31, 32], "\u6349\u3048": [12, 13], "\u6355\u307e\u3048": 19, "\u6368\u3066\u308b": 9, "\u6388\u696d": 31, "\u639b\u3051": 2, "\u639b\u3051\u7b97": [1, 10, 32], "\u639b\u3051\u7b97\u3084\u5272\u308a": 1, "\u63a2\u3057": [9, 11, 28], "\u63a2\u7d22": 19, "\u63a5\u5408\u70b9": 6, "\u63a5\u5c3e": 31, "\u63a5\u982d": 31, "\u63a8\u5968": [4, 7, 11, 14, 15, 28, 30], "\u63a8\u5bdf": 4, "\u63a8\u79fb": 13, "\u63cf\u3051": 27, "\u63cf\u753b": [27, 29], "\u63d0\u4f9b": [1, 14, 16, 20, 27], "\u63db\u3048": [5, 21, 30], "\u63db\u3048\u308b": [6, 8, 9, 17, 30], "\u63db\u3048\u308c": 17, "\u63db\u308f\u308a": [1, 30], "\u64cd\u4f5c": [2, 5, 9, 12, 20, 24, 30, 31, 32], "\u652f\u3048": 3, "\u652f\u63f4": 20, "\u6539\u3081": [2, 4, 10, 12], "\u6539\u3081\u3066": 11, "\u6539\u5909": 31, "\u6539\u884c": [2, 5, 12, 18, 26, 30, 31], "\u653e\u7f6e": 11, "\u6559\u54e1": 0, "\u6559\u5e2b": [31, 32], "\u6559\u6750": [11, 13, 28, 31], "\u6559\u6750\u7b49": 22, "\u6563\u5e03": [21, 27, 29, 32], "\u6563\u5e03\u56f3": [31, 32], "\u6570\u3048": [5, 23, 29, 32], "\u6570\u3048\u4e0a\u3052": [1, 32], "\u6570\u5024": [3, 5, 6, 8, 10, 16, 21, 23, 26, 27, 29, 31, 32], "\u6570\u5217": [3, 9], "\u6570\u5b57": [2, 8, 10, 30], "\u6570\u5b66": [2, 6, 14, 16, 30, 31, 32], "\u6570\u5f0f": 1, "\u6574\u5217": 18, "\u6574\u6570": [5, 6, 7, 8, 9, 14, 16, 17, 18, 25, 26, 28, 29, 30, 31, 32], "\u6587\u540c": 9, "\u6587\u5b57": [0, 1, 2, 3, 9, 10, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 26, 29, 31, 32], "\u6587\u5b57\u5217": [3, 4, 8, 9, 10, 11, 12, 14, 17, 18, 19, 23, 25, 26, 28, 29, 30, 31, 32], "\u6587\u5b57\u5217a": [5, 30], "\u6587\u5b57\u5217b": [5, 30], "\u6587\u5b57\u6570": 11, "\u6587\u66f8": [5, 15, 30], "\u6587\u6cd5": 9, "\u6587\u732e": 0, "\u6587\u7ae0": [5, 9, 23], "\u65ad\u308a": 16, "\u65b0\u3057\u3044": [5, 6, 9, 11, 16, 19, 20, 30], "\u65b0\u3057\u304f": 19, "\u65b0\u305f": [0, 5, 6, 8, 11, 12, 19, 20, 22, 23], "\u65b9\u5411": 1, "\u65b9\u6cd5": [0, 2, 5, 6, 7, 8, 9, 14, 15, 18, 19, 24, 27], "\u65e2\u5b58": [10, 11, 15, 19, 22], "\u65e2\u5b9a": 9, "\u65e5\u672c": [4, 26, 30], "\u65e5\u672c\u8a9e": [1, 5, 11, 28], "\u65e9\u304f": 11, "\u6607\u9806": [6, 16, 20, 30], "\u660e\u3089\u304b": [7, 9], "\u660e\u5feb": 24, "\u660e\u793a": [2, 9, 10, 13, 14, 16], "\u660e\u8a18": [1, 30], "\u6613\u304f": 4, "\u6642\u523b": 30, "\u6642\u70b9": 18, "\u6642\u7cfb": 31, "\u6642\u90e8": 30, "\u6642\u9593": [6, 9, 30], "\u66f2\u7dda": [27, 29], "\u66f4\u65b0": [8, 10, 16, 20], "\u66f8\u3044": [2, 4, 30], "\u66f8\u304b": [0, 1, 2, 3, 4, 6, 9, 18, 22, 26], "\u66f8\u304d": [6, 8, 9, 15, 17, 26, 31, 32], "\u66f8\u304d\u51fa\u3057": 26, "\u66f8\u304d\u63db\u3048": [1, 5, 6, 7, 8, 9, 17, 23, 29, 30], "\u66f8\u304d\u65b9": [4, 6, 31], "\u66f8\u304d\u76f4\u3057": 9, "\u66f8\u304d\u8fbc\u307e": 26, "\u66f8\u304d\u8fbc\u307f": [31, 32], "\u66f8\u304d\u8fbc\u3080": [11, 26, 28], "\u66f8\u304d\u8fbc\u3080\u969b": 11, "\u66f8\u304d\u8fbc\u3093": 11, "\u66f8\u304f": [1, 3, 4, 6, 7, 9, 11, 14, 15, 17, 18, 24, 26, 30], "\u66f8\u3051": [6, 9, 17, 19], "\u66f8\u5f0f": 7, "\u66ff\u3048": [5, 6, 9, 31, 32], "\u66ff\u3048\u308b": [4, 6], "\u6700\u3082": [1, 6, 18, 25], "\u6700\u4e0a": 13, "\u6700\u521d": [2, 4, 5, 6, 7, 9, 10, 12, 18, 19, 27, 28, 29, 30], "\u6700\u5916": 16, "\u6700\u5927": [6, 14, 18, 20], "\u6700\u5c0f\u5024": [6, 16, 20], "\u6700\u5f8c": [1, 2, 4, 5, 6, 7, 9, 10, 11, 12, 16, 24, 27, 29, 30], "\u6700\u7d42": 20, "\u6700\u7d42\u884c": 20, "\u6700\u9069": 21, "\u6709\u52b9": [15, 17, 22], "\u6709\u7121": [6, 9], "\u6709\u7528": [4, 16], "\u6709\u9650": 1, "\u671b\u307e\u3057\u3044": 28, "\u671f\u5024": [10, 32], "\u671f\u5316": [31, 32], "\u671f\u5f85": [2, 4, 10], "\u671f\u5f85\u901a\u308a": 4, "\u6728\u69cb": [31, 32], "\u6728\u69cb\u9020": [31, 32], "\u672a\u5b9a": [2, 4, 7, 10], "\u672a\u5b9a\u7fa9": 2, "\u672a\u6e80": [16, 27], "\u672a\u77e5": [14, 15], "\u672b\u5c3e": [11, 12], "\u672b\u7aef": 13, "\u672c\u4f53": [2, 10, 19], "\u672c\u5f53": 1, "\u672c\u6388\u696d": [11, 15], "\u672c\u6559\u6750": 7, "\u672c\u683c": 3, "\u672c\u90f7": 30, "\u6761\u4ef6": [4, 6, 9, 16, 18, 28, 30, 31, 32], "\u6761\u4ef6\u5f0f": 9, "\u6765\u305f": 11, "\u6765\u3066": [0, 2], "\u6765\u308b": [3, 18, 30], "\u6771\u4eac": [9, 29, 32], "\u679c\u305f": 30, "\u67d4\u8edf": 13, "\u683c\u6bb5": 16, "\u683c\u7d0d": [5, 6, 9, 11, 21, 23, 28, 29, 30], "\u6841\u6bce": 9, "\u68d2\u30b0\u30e9\u30d5": 25, "\u691c\u67fb": [4, 6, 9], "\u691c\u77e5": 19, "\u691c\u7d22": [31, 32], "\u691c\u8a3c": 4, "\u6982\u5ff5": [2, 13], "\u69cb\u3044": [6, 9, 18], "\u69cb\u6210": [5, 6, 9, 12, 16, 20, 23, 30], "\u69cb\u6587": [1, 2, 12, 19, 30, 31, 32], "\u69cb\u6587\u4e0a": 2, "\u69cb\u7bc9": [17, 27, 31, 32], "\u69cb\u9020": [3, 7, 8, 21, 31, 32], "\u69d8\u3005": [4, 5, 6, 7, 12, 16, 23, 25, 30, 31, 32], "\u6a19\u6e96": [5, 16, 20, 28], "\u6a2a\u3064\u8179\u306a\u3093\u305e": 11, "\u6a5f\u68b0": [16, 31, 32], "\u6a5f\u80fd": [4, 5, 7, 9, 14, 16, 17, 19, 20], "\u6b20\u640d": 31, "\u6b20\u640d\u5024": 20, "\u6b21\u3005": [6, 18, 19], "\u6b21\u3044": 8, "\u6b21\u306e": 30, "\u6b21\u5143": [16, 25, 31, 32], "\u6b32\u3057\u3044": 9, "\u6b62\u307e\u3089": 31, "\u6b62\u307e\u308a": 28, "\u6b62\u3081\u308b": 19, "\u6b63\u3057\u3044": [3, 4], "\u6b63\u3057\u304f": [4, 28, 30], "\u6b63\u306a\u3089": [3, 18], "\u6b63\u5e38": 9, "\u6b63\u5f0f": 30, "\u6b63\u78ba": [3, 5, 11, 16, 19], "\u6b63\u898f": [9, 16, 27, 29, 31, 32], "\u6b63\u8ca0": 5, "\u6b74\u53f2": 28, "\u6b8b\u308a": 7, "\u6bb5\u4e0a": 11, "\u6bb5\u4e0b": 13, "\u6bb5\u968e": [25, 30], "\u6bce\u56de": 12, "\u6bd4\u3079": 9, "\u6bd4\u4f8b": [6, 9], "\u6bd4\u8f03": [1, 4, 16, 21, 24, 31, 32], "\u6c0f\u540d": 26, "\u6c17\u306b": 28, "\u6c17\u4ed8\u3044": 12, "\u6c17\u6e29": [29, 32], "\u6c17\u8c61\u5e81": [26, 29], "\u6c34\u5e73": 25, "\u6c34\u5e73\u8ef8": 25, "\u6c38\u4e45": 9, "\u6c42\u307e\u308a": [1, 3], "\u6c42\u3081": [1, 2, 4, 5, 9, 17, 18, 29], "\u6c42\u3081\u308b": [2, 3, 6, 9, 14, 17, 18, 20, 23, 29], "\u6c7a\u3057": 9, "\u6c7a\u3081": [5, 6], "\u6c7a\u3081\u308b": 27, "\u6c7a\u5b9a": 21, "\u6cbf\u3063": 4, "\u6ce2\u62ec": 23, "\u6ce8\u610f": [0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 18, 20, 27, 28, 30, 31], "\u6d3b\u7528": [4, 8], "\u6d41\u308c": 10, "\u6d45\u304f": 7, "\u6d6e\u304d": 4, "\u6d6e\u52d5": [1, 26, 32], "\u6d88\u3048": 4, "\u6d88\u3057": [4, 29, 30], "\u6d88\u3059": 27, "\u6d88\u8cbb": [11, 12, 17], "\u6df1\u304f": [7, 9], "\u6df1\u3055": 7, "\u6df7\u3056\u3063": 1, "\u6df7\u4e71": [31, 32], "\u6df7\u540c": 19, "\u6df7\u5728": [6, 16], "\u6dfb\u5b57": 20, "\u6e08\u307f": [5, 10], "\u6e1b\u3063": 2, "\u6e1b\u3089": [2, 19, 24, 28], "\u6e1b\u3089\u3059": 2, "\u6e1b\u7b97": 16, "\u6e21\u3055": [7, 10, 12, 18, 19], "\u6e21\u3057": [10, 24, 26, 27, 29], "\u6e21\u3059": [6, 10, 11, 13, 16, 17, 29], "\u6e21\u305b": 17, "\u6e29\u5ea6": [2, 27], "\u6e7f\u5ea6": 2, "\u6e80\u305f": [3, 4, 6, 7, 16, 30], "\u6e96\u5099": [21, 27, 29], "\u6f14\u7b97": [2, 20, 31, 32], "\u6f14\u7b97\u5b50": [2, 3, 4, 5, 8, 9, 12, 23, 30, 31, 32], "\u6f38\u5316": 3, "\u6fc3\u6de1": 29, "\u6feb\u7528": 10, "\u70b9\u3068\u3057\u3066": [27, 29], "\u70b9\u4ee5\u4e0b": 9, "\u70b9\u6570": [1, 7, 26, 32], "\u7121\u3044": 16, "\u7121\u304b\u3063": 28, "\u7121\u52b9": [5, 30], "\u7121\u540d": [18, 32], "\u7121\u5f15": [6, 11], "\u7121\u7406": 3, "\u7121\u8996": 1, "\u7121\u9650": 1, "\u7121\u99c4": 9, "\u7247\u65b9": [5, 6], "\u7279\u306b": [3, 4, 7, 11, 13, 19, 28, 30], "\u7279\u5225": [2, 13, 14, 16], "\u7279\u5b9a": [6, 9, 11, 16], "\u7279\u5fb4": [10, 21], "\u7279\u5fb4\u91cf": [21, 32], "\u7279\u6b8a": [5, 30, 31, 32], "\u7279\u6bb5": 3, "\u72b6\u614b": 27, "\u72b6\u6cc1": [2, 4, 6], "\u72ec\u7acb": 26, "\u7363\u3082": 11, "\u73fe\u308c": 27, "\u73fe\u308c\u308b": [2, 9], "\u73fe\u5728": [0, 13], "\u7406\u7531": [14, 15], "\u7406\u89e3": [6, 9], "\u74b0\u5883": [5, 15, 28], "\u751f\u3058": [1, 2, 4, 10, 13, 19], "\u751f\u3058\u308b": [4, 26], "\u751f\u6210": [9, 12, 19, 20, 27, 28, 29, 31, 32], "\u7528\u3044": [1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 20, 21, 23, 24, 26, 27, 28, 29, 30], "\u7528\u3044\u308b": [1, 2, 3, 5, 6, 9, 10, 14, 16, 17, 18, 20, 21, 27, 29, 30], "\u7528\u3044\u308c": [5, 18], "\u7528\u53ef": 10, "\u7528\u610f": [1, 2, 3, 5, 9, 11, 21, 25, 27, 28, 29], "\u7528\u8a9e": [3, 19], "\u7528\u9014": 2, "\u7531\u6765": 13, "\u753b\u50cf": [27, 28, 31, 32], "\u753b\u9762": 28, "\u7565\u79f0": 14, "\u756a\u53f7": [0, 6, 9, 20, 22, 30], "\u756a\u76ee": [3, 4, 5, 6, 8, 9, 12, 16, 18, 28, 29, 30], "\u7570\u306a\u308a": [2, 5, 6, 16, 17, 23], "\u7570\u306a\u308b": [1, 2, 7, 9, 10, 11, 16, 21, 29], "\u7570\u5e38": 4, "\u7591\u308f\u3057\u3044": 4, "\u75db\u5feb": 11, "\u767a\u751f": [4, 12, 19], "\u767b\u5834": 3, "\u767b\u9332": [4, 9, 23, 32], "\u767d\u718a": 11, "\u76c6\u4f8b": 29, "\u76ee\u7684": 9, "\u76ee\u76db\u308a": 27, "\u76f4\u3057": [1, 22], "\u76f4\u3059": [1, 9], "\u76f4\u524d": 1, "\u76f4\u5f8c": 7, "\u76f4\u611f": 30, "\u76f4\u63a5": [0, 3, 6, 8, 17, 24, 28], "\u76f4\u7dda": [27, 29], "\u76f4\u9762": 4, "\u76f8\u4e92": [31, 32], "\u76f8\u5bfe": [11, 13], "\u76f8\u5bfe\u30d1\u30b9": [13, 32], "\u76f8\u5f53": [6, 9], "\u76f8\u7570": 4, "\u7701\u304b": 7, "\u7701\u3051": 2, "\u7701\u7565": [5, 7, 9, 17, 20, 29], "\u771f\u3068": 30, "\u771f\u3093\u4e2d": 4, "\u771f\u7406": [3, 18, 20, 31, 32], "\u771f\u7406\u5024": [4, 16, 31, 32], "\u77e2\u5370": 22, "\u77e5\u3063": 16, "\u77e5\u308b": 25, "\u77ed\u3044": 14, "\u77ed\u7e2e": [31, 32], "\u7834\u58ca": [9, 10, 16, 23, 30, 31, 32], "\u78ba\u304b": 5, "\u78ba\u304b\u3081": [0, 2, 6, 30], "\u78ba\u7acb": 16, "\u78ba\u8a8d": [2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 16, 17, 18, 19, 20, 23, 25, 26, 28, 29, 30], "\u793a\u3055": [6, 19], "\u793a\u3057": [3, 4, 6, 7, 9, 12, 13, 21, 27, 28, 29], "\u793a\u3059": [0, 4, 11, 24, 27, 28], "\u793a\u3059\u4f8b": 7, "\u793a\u7684": 10, "\u7956\u5148": [13, 32], "\u79d1\u5b66": 16, "\u79fb\u52d5": [0, 22, 28], "\u79fb\u884c": 22, "\u7a2e\u985e": [0, 3, 5, 6, 8, 11, 12, 18, 19, 20, 21, 22, 23, 27, 29, 30], "\u7a4d\u5c02": 16, "\u7a4d\u96c6\u5408": [23, 32], "\u7a7a\u3068": 8, "\u7a7a\u30bf\u30d7\u30eb": [6, 32], "\u7a7a\u30ea\u30b9\u30c8": [6, 32], "\u7a7a\u5217": [5, 30, 32], "\u7a7a\u6587": [3, 9, 11, 19, 30, 31, 32], "\u7a7a\u6587\u5b57": 5, "\u7a7a\u6587\u5b57\u5217": 5, "\u7a7a\u767d": [2, 6, 7, 9, 11, 16, 30, 31, 32], "\u7a7a\u884c": [31, 32], "\u7a7a\u9593": 21, "\u7acb\u3061\u4e0a\u3052": 31, "\u7b26\u53f7": [5, 26], "\u7b49\u3057\u3044": [1, 3, 9, 16, 30], "\u7b49\u3057\u304f": [3, 16], "\u7b49\u4fa1": [7, 12, 31, 32], "\u7b49\u5206": 16, "\u7b49\u53f7": 2, "\u7b49\u6bd4": 9, "\u7b49\u9593": 25, "\u7b87\u6240": [6, 9], "\u7b97\u5b50": [1, 7, 31, 32], "\u7b97\u8853": [16, 31, 32], "\u7ba1\u7406": [13, 20], "\u7bc4\u56f2": [5, 6, 16, 27, 29, 30], "\u7c21\u5358": [2, 4, 6, 9, 15, 16, 18, 19, 26, 31, 32], "\u7c21\u6f54": [2, 6, 7, 16, 21, 30], "\u7c92\u5ea6": 24, "\u7cbe\u5ea6": 21, "\u7d0d\u307e\u308b": 1, "\u7d1a\u6570": 9, "\u7d22\u5f15": 31, "\u7d2f\u7a4d": 32, "\u7d2f\u7b97": [2, 32], "\u7d30\u304b\u3044": 30, "\u7d30\u304b\u304f": 7, "\u7d33\u58eb": 11, "\u7d39\u4ecb": [1, 3, 5, 6, 7, 8, 11, 12, 16, 28, 30], "\u7d42\u3048": 9, "\u7d42\u308f": 6, "\u7d42\u308f\u3063": [9, 11, 26], "\u7d42\u308f\u3089": 11, "\u7d42\u308f\u308a": [1, 3, 9, 11, 19, 26], "\u7d42\u308f\u308b": [6, 9], "\u7d42\u4e86": [0, 2, 3, 6, 7, 9, 10, 12, 16, 19], "\u7d42\u4e86\u5f8c": 9, "\u7d42\u7aef": [11, 12, 20], "\u7d44\u307f": [10, 27], "\u7d44\u307f\u5408\u308f": [3, 13, 30], "\u7d44\u307f\u5408\u308f\u305b": [6, 8, 9, 10, 30], "\u7d44\u307f\u5408\u308f\u305b\u308b": 30, "\u7d44\u307f\u8fbc\u307f": [2, 3, 5, 8, 9, 10, 12, 16, 17, 28, 31, 32], "\u7d44\u3081": 6, "\u7d4c\u7531": [1, 12, 24], "\u7d4c\u8def": 13, "\u7d50\u5408": [1, 2, 5, 30, 31, 32], "\u7d50\u679c": [0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 15, 16, 17, 18, 19, 21, 23, 24, 27, 28, 29, 30], "\u7d5e\u308a": 4, "\u7d71\u4e00": 12, "\u7d71\u6cbb": [24, 32], "\u7d71\u8a08": [16, 31, 32], "\u7d76\u5bfe": [3, 11, 18, 28], "\u7d76\u5bfe\u30d1\u30b9": [13, 32], "\u7d99\u627f": [31, 32], "\u7d9a\u3044": 3, "\u7d9a\u304d": [2, 7], "\u7d9a\u304f": [2, 7, 28], "\u7d9a\u304f\u5f0f": 2, "\u7d9a\u3051": [0, 1, 7, 12], "\u7d9a\u884c": 9, "\u7dad\u6301": 25, "\u7dca\u6025": 12, "\u7dcf\u4e57": 16, "\u7dcf\u548c": [6, 9, 16, 17, 18], "\u7dcf\u6570": 21, "\u7dcf\u79f0": [3, 5, 6, 12], "\u7dd1\u8272": [2, 22], "\u7dda\u3054\u3068": 29, "\u7dda\u5f62": [21, 26, 31, 32], "\u7de8\u96c6": 31, "\u7df4\u7fd2": [31, 32], "\u7e4b\u3052": [9, 30], "\u7e70\u308a": [10, 12], "\u7e70\u308a\u8fd4\u3055": [6, 9, 12, 30], "\u7e70\u308a\u8fd4\u3057": [5, 8, 10, 19, 24, 25, 26, 30, 31, 32], "\u7e70\u308a\u8fd4\u3057\u884c\u3046": 6, "\u7e70\u308a\u8fd4\u3057\u8fd4\u3059": 19, "\u7e70\u308a\u8fd4\u3059": [4, 6, 9, 12], "\u7f6e\u3044": 30, "\u7f6e\u304b": [11, 13], "\u7f6e\u304d": [1, 5, 6, 17, 21, 30], "\u7f6e\u304d\u63db\u3048": 30, "\u7f6e\u304d\u63db\u308f\u3089": 22, "\u7f6e\u304f": [2, 7], "\u7f6e\u63db": [2, 9, 30, 32], "\u8003\u3048": [2, 3, 5, 7, 12, 13, 19, 26, 28], "\u8003\u3048\u308b": [2, 9, 12], "\u8003\u3048\u65b9": 24, "\u8003\u5bdf": 18, "\u8003\u616e": 30, "\u809d\u8981": 4, "\u81ea\u3089": 4, "\u81ea\u4e57": [6, 17], "\u81ea\u4f53": [2, 12, 28], "\u81ea\u4f5c": [31, 32], "\u81ea\u5206": [0, 1, 24, 27], "\u81ea\u52d5": [4, 7, 9, 11, 13, 16, 19, 20, 29], "\u81ea\u5df1": [4, 28], "\u81ea\u5df1\u8aac\u660e": 4, "\u81ea\u660e": [4, 7], "\u81ea\u7136": [6, 17], "\u81ea\u7531": [1, 2], "\u81ea\u8eab": [0, 3, 12, 19, 22, 24], "\u8208\u5473": 31, "\u826f\u304f": 11, "\u826f\u304f\u4f7f\u3046": 30, "\u826f\u304f\u4f7f\u308f": 27, "\u8272\u3005": [0, 1, 2, 6, 30], "\u8272\u3084\u7dda": 27, "\u8272\u9078": 27, "\u8272\u968e": 27, "\u82b1\u5b50": 26, "\u82b1\u5f01": 20, "\u82e5\u3044": 11, "\u82f1\u5358": [9, 30], "\u82f1\u5c0f": 9, "\u82f1\u6570": [1, 11, 26], "\u82f1\u6587": [11, 30], "\u82f1\u6587\u5b57": [5, 11], "\u82f1\u8a9e": [5, 9, 23, 27, 30], "\u865a\u90e8": 16, "\u884c\u3044": [4, 5, 6, 10, 19, 21, 24, 25, 29, 30], "\u884c\u3046": [0, 1, 5, 6, 7, 9, 16, 18, 21, 24, 25, 27, 32], "\u884c\u3048": [5, 6, 11], "\u884c\u304f": 13, "\u884c\u3063": [0, 1, 2, 9, 19, 24, 26], "\u884c\u3068\u3057\u3066": 16, "\u884c\u306a\u3063": 21, "\u884c\u308f": [1, 2, 6, 7, 9, 18], "\u884c\u30a4\u30f3\u30c7\u30c3\u30af\u30b9": 16, "\u884c\u5168": 1, "\u884c\u5206": 20, "\u884c\u5217": [14, 16, 21, 27, 29], "\u884c\u5358": 11, "\u884c\u540d": 10, "\u884c\u6570": [16, 20, 21], "\u884c\u672b": [7, 30], "\u884c\u756a": [2, 12, 29], "\u884c\u756a\u53f7": [2, 32], "\u884c\u76ee": [7, 9, 12, 20, 29], "\u884c\u81ea\u4f53": 1, "\u884c\u982d": [1, 2, 7], "\u885d\u7a81": [10, 14, 15], "\u8868\u3055": [1, 13, 26, 30], "\u8868\u3057": [1, 3, 11, 18, 19, 21, 30], "\u8868\u3059": [1, 2, 3, 5, 11, 13, 16, 18, 21, 26, 30], "\u8868\u3059\u578b": 16, "\u8868\u3059\u5f0f": 30, "\u8868\u305d": 6, "\u8868\u73fe": [1, 2, 8, 9, 12, 21, 31, 32], "\u8868\u793a": [0, 3, 7, 8, 10, 14, 16, 18, 19, 20, 21, 22, 25, 27, 28, 29, 30, 31, 32], "\u8868\u8a18": [6, 9, 13, 16, 18, 30, 31, 32], "\u88dc\u308f": 13, "\u8907\u5408": [2, 4], "\u8907\u6570": [1, 2, 5, 6, 9, 11, 12, 14, 15, 18, 20, 23, 25, 26, 27, 29, 30, 31, 32], "\u8907\u7d20": 26, "\u8907\u7d20\u6570": 16, "\u8907\u88fd": [4, 6, 32], "\u8907\u96d1": [2, 7, 16, 24, 27, 30], "\u897f\u66a6": 26, "\u897f\u66a6\u5e74": 26, "\u8981\u7d04": 20, "\u8981\u7d20": [4, 5, 7, 8, 9, 10, 12, 13, 17, 18, 23, 24, 25, 26, 27, 28, 29, 31, 32], "\u8981\u7d20x": 9, "\u8981\u7d20\u6bce": 31, "\u898b\u3048": [4, 16, 19], "\u898b\u3048\u308b": 5, "\u898b\u3048\u65b9": 5, "\u898b\u304b\u3051": 9, "\u898b\u305b\u308b": 0, "\u898b\u3064": 9, "\u898b\u3064\u304b\u3063": 9, "\u898b\u3064\u304b\u308a": 27, "\u898b\u3064\u3051": [2, 4], "\u898b\u3066": [3, 9, 16, 19, 30], "\u898b\u307e\u3057\u3087": [6, 12, 18], "\u898b\u3084\u3059\u3044": 7, "\u898b\u3084\u3059\u304f": 27, "\u898b\u308b": [6, 28], "\u898b\u505a": [6, 13, 16], "\u898b\u505a\u3059": 4, "\u898b\u7a4d": 9, "\u898b\u821e": 11, "\u898b\u901a\u3057": 24, "\u898f\u5247": 4, "\u8996\u899a": 9, "\u899a\u3048": [2, 30], "\u89aa\u5b50": 13, "\u89aa\u621a": 2, "\u89b3\u5bdf": [2, 4, 21], "\u89b3\u6e2c": 21, "\u89b3\u70b9": 13, "\u89d2\u62ec": 30, "\u89e3\u3044": 24, "\u89e3\u304f": 24, "\u89e3\u3051\u308b": 24, "\u89e3\u51cd": 16, "\u89e3\u7b54": 31, "\u89e3\u8aac": [0, 11, 31], "\u89e3\u91c8": [2, 4, 11, 16, 30], "\u89e6\u308c": 25, "\u8a00\u3044": [2, 3, 30], "\u8a00\u3046": [1, 18], "\u8a00\u3048": [4, 7], "\u8a00\u3063": [4, 16, 30], "\u8a00\u53ca": 4, "\u8a00\u8a9e": [2, 4, 5, 6], "\u8a08\u7b97": [2, 3, 6, 7, 10, 14, 16, 17, 18, 26, 27, 28, 31, 32], "\u8a08\u7b97\u5f0f": 30, "\u8a08\u7b97\u91cf": [9, 31, 32], "\u8a13\u7df4": 21, "\u8a18\u53f7": [2, 4, 5, 13, 28, 30], "\u8a18\u61b6": 1, "\u8a18\u6cd5": [2, 5, 16, 31, 32], "\u8a18\u8ff0": [2, 4, 5, 6, 7, 10, 12, 13, 14, 15, 16, 17, 24, 28, 30], "\u8a18\u9332": [6, 11, 19, 26, 30], "\u8a2a\u554f": 17, "\u8a2d\u5b9a": [0, 5, 6, 19, 21, 26, 27], "\u8a31\u3055": 9, "\u8a55\u4fa1": [1, 2, 3, 6, 16, 19, 21, 29, 31, 32], "\u8a55\u5b9a": 7, "\u8a66\u3057": [1, 9, 29], "\u8a72\u5f53": 7, "\u8a73\u3057\u3044": 25, "\u8a73\u3057\u304f": [6, 9, 16, 18, 19, 26], "\u8a73\u7d30": [11, 12, 20, 21, 27], "\u8a8d\u8b58": 11, "\u8a9e\u6587": 26, "\u8a9e\u8a33": 4, "\u8aa4\u308a": 2, "\u8aa4\u5dee": [1, 21, 32], "\u8aa4\u690d": 4, "\u8aa4\u89e3": [31, 32], "\u8aac\u660e": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30], "\u8aad\u307f": [4, 6, 9, 12, 17, 24, 26, 31, 32], "\u8aad\u307f\u51fa\u3057": [11, 16], "\u8aad\u307f\u7d42\u308f\u308b": 11, "\u8aad\u307f\u8fbc\u307e": [1, 11, 14, 15], "\u8aad\u307f\u8fbc\u307f": [4, 14, 15, 20, 29, 30, 31, 32], "\u8aad\u307f\u8fbc\u3080": [15, 25, 26], "\u8aad\u307f\u8fbc\u3093": [11, 14, 20, 26], "\u8aad\u3080": [17, 26], "\u8aad\u3093": [2, 4, 11, 12, 17, 27], "\u8abf\u3079": [5, 16, 18, 28, 30], "\u8abf\u3079\u308b": [1, 5, 6, 8, 9, 12, 30], "\u8abf\u6574": 21, "\u8ad6\u7406": [6, 7, 31, 32], "\u8ca0\u6570": 5, "\u8ce2\u660e": 16, "\u8d70\u67fb": 17, "\u8d77\u304d": [4, 27], "\u8d77\u3053\u3063": 1, "\u8d77\u3053\u308b": [1, 6], "\u8d77\u52d5": [0, 13, 22, 28], "\u8d85\u3048\u308c": 9, "\u8db3\u3057": [2, 18], "\u8db3\u3057\u5408\u305b": [9, 17, 30], "\u8db3\u3057\u7b97": [1, 32], "\u8db3\u3057\u7b97\u3084": 1, "\u8db3\u308a": 1, "\u8eab\u9577": 2, "\u8ee2\u7f6e": 16, "\u8ef8\u4e0a": [27, 29], "\u8f9e\u66f8": [4, 5, 6, 12, 13, 18, 20, 23, 25, 30, 31, 32], "\u8f9e\u66f8\u578b": [10, 32], "\u8fd4\u3055": [2, 3, 5, 6, 9, 10, 12, 16, 19, 26, 30], "\u8fd4\u3057": [1, 2, 3, 5, 6, 8, 9, 11, 12, 16, 17, 18, 19, 23, 24, 26, 30], "\u8fd4\u3057\u7d9a\u3051\u308b": 19, "\u8fd4\u3059": [2, 4, 5, 6, 7, 8, 9, 10, 11, 15, 16, 17, 18, 19, 23, 24, 26, 27, 28, 29, 30, 31, 32], "\u8fd4\u3059\u5f0f": 6, "\u8fd4\u3063": [5, 18, 26], "\u8fd4\u3089": 30, "\u8fd4\u308a": [2, 3, 5, 16, 18, 19], "\u8fd4\u308b": [11, 18, 30], "\u8fd4\u5024": [6, 9, 18, 30, 31, 32], "\u8ff0\u3079": [5, 6, 8, 21, 28, 30], "\u8ffd\u52a0": [1, 8, 9, 21, 23, 27, 30, 31, 32], "\u8ffd\u8a18": 11, "\u9001\u51fa": 4, "\u9006\u3055": 13, "\u9006\u306b": 17, "\u9006\u5411\u304d": 5, "\u9006\u9806": 32, "\u900f\u660e": [27, 29], "\u9014\u4e2d": [1, 2, 6, 10, 17], "\u901a\u3058": 19, "\u901a\u308a": [2, 4, 6, 7, 10, 21, 24, 28, 30], "\u901a\u4f8b": [13, 15, 27], "\u901a\u5e38": [8, 10, 11, 21, 29], "\u901a\u79f0": 0, "\u9023\u63a5": [30, 32], "\u9023\u756a": 16, "\u9023\u7d50": [6, 31, 32], "\u9023\u7d9a": [3, 5, 6, 9, 21, 30], "\u9032\u307f": 7, "\u9032\u3080": [7, 13], "\u9032\u3081\u308b": 12, "\u9032\u6570": 17, "\u904e\u8a00": 16, "\u9054\u3057": 26, "\u9054\u3059\u308b": 11, "\u9055\u3044": [5, 7, 10, 16, 28], "\u9055\u3046": 8, "\u9055\u3063": [6, 16, 27], "\u9055\u53cd": [1, 4], "\u9069\u3057": [11, 24], "\u9069\u5207": [5, 12], "\u9069\u5408": [4, 21, 30], "\u9069\u5b9c": 4, "\u9069\u5f53": [0, 1, 22, 28], "\u9069\u7528": [6, 8, 11, 12, 16, 17, 18, 19, 20, 23, 27], "\u9078\u3076": 9, "\u9078\u629e": [0, 15, 21, 22, 28, 30, 32], "\u907f\u3051\u308b": 5, "\u90e8\u5206": [2, 3, 4, 5, 6, 9, 15, 17, 19, 22, 24, 30, 31], "\u90f5\u4fbf": 30, "\u914d\u5217": [5, 6, 10, 20, 21, 24, 26, 27, 29, 31, 32], "\u914d\u5217x": 29, "\u914d\u5217y": 29, "\u914d\u7f6e": 27, "\u91cd\u306d": 27, "\u91cd\u8907": [9, 10, 17, 23, 30], "\u91cd\u8981": [4, 11], "\u91cf\u8a08": 20, "\u9234\u6728": 26, "\u9244\u7832": 11, "\u9577\u3044": [2, 18], "\u9577\u3044\u884c": 18, "\u9577\u3055": [2, 5, 6, 7, 8, 9, 16, 17, 18, 20, 21, 23, 30], "\u9577\u3059\u304e\u308b": [14, 15], "\u9577\u5f15": [31, 32], "\u9589\u3058": [4, 11], "\u9589\u3058\u308b": 11, "\u9589\u3058\u5fd8\u308c": 4, "\u9589\u5305": [13, 30, 32], "\u958b\u3044": [0, 11, 13, 28], "\u958b\u304b": 28, "\u958b\u304d": [4, 11], "\u958b\u304f": [11, 13, 22, 27], "\u958b\u3051": 13, "\u958b\u3051\u308b": 13, "\u958b\u3053": [11, 13], "\u958b\u59cb": [7, 9, 16], "\u958b\u767a": 15, "\u9593\u5206": 26, "\u9593\u63a5": [19, 24], "\u9593\u9055\u3044": [10, 16], "\u9593\u9055\u3063": [3, 4, 6], "\u95a2\u308f\u3089": 30, "\u95a2\u308f\u308b": 4, "\u95a2\u4fc2": [1, 5, 7, 13, 14, 21, 23], "\u95a2\u6570": [4, 5, 7, 8, 9, 11, 12, 14, 15, 17, 19, 20, 21, 24, 26, 27, 28, 29, 31, 32], "\u95a2\u9023": [4, 16], "\u963b\u5bb3": 11, "\u964d\u9806": [6, 18, 20], "\u9650\u3063": 5, "\u9650\u3089": [2, 11, 13, 24], "\u9650\u308a": [1, 9, 19], "\u9650\u5b9a": [11, 16], "\u9664\u3044": [7, 14, 15, 17], "\u9664\u304b": 17, "\u9664\u304d": 30, "\u9664\u304f": 30, "\u9664\u7b97": [1, 4, 9, 16, 32], "\u968e\u4e57": [14, 15, 28], "\u968e\u4e57n": 28, "\u968e\u5c64": [31, 32], "\u968e\u8abf": 27, "\u96c6\u5408": [13, 17, 21, 31, 32], "\u96c6\u8a08": 16, "\u96e2\u6563": [1, 21], "\u96e3\u3057\u3044": 25, "\u96fb\u5353": 1, "\u96fb\u8a71": 30, "\u9752\u8272": 22, "\u975e\u516c\u5f0f": 4, "\u975e\u5e38": [1, 9], "\u975e\u660e": 10, "\u975e\u7834": [31, 32], "\u975e\u7834\u58ca": [6, 32], "\u9762\u5012": [2, 18, 27], "\u9762\u7a4d": 2, "\u9805\u6f14": [1, 7, 31, 32], "\u9805\u76ee": [15, 31], "\u9806\u4e0d": 10, "\u9806\u4f4d": [31, 32], "\u9806\u5e8f": [1, 5, 6, 9, 23, 24, 30], "\u9806\u6b21": 12, "\u9806\u756a": [1, 2, 6, 7, 9, 20, 23, 31], "\u983b\u5ea6": 9, "\u983b\u7e41": 13, "\u9854\u6587\u5b57": 30, "\u98db\u3070": 6, "\u99c4\u76ee": 2, "\u9ad8\u3005": [11, 30], "\u9ad8\u3044": [1, 4, 16], "\u9ad8\u3055": 25, "\u9ad8\u3081\u308b": 4, "\u9ad8\u6b21": 16, "\u9ad8\u901f": 24, "\u9ad8\u968e": [31, 32], "\u9ec4\u3044\u308d": 11, "\u9ec4\u91d1": 1, "\uff01\uff09": 22, "\uff08accuracy": 21, "\uff08ancestor": 13, "\uff08cf": 4, "\uff08child": 13, "\uff08cm": 2, "\uff08descendant": 13, "\uff08kg": 2, "\uff08leaf": 13, "\uff08logic": 4, "\uff08mac": [0, 22], "\uff08macos": 28, "\uff08node": 13, "\uff08parent": 13, "\uff08python": 22, "\uff08root": 13, "\uff08runtime": 4, "\uff08sibling": 13, "\uff08sort": 32, "\uff08sorted": 32, "\uff08syntax": 4, "\uff08tex": 14, "\uff08tree": 13, "\uff08unicode": 5, "\uff08utf": 26, "\uff08word": 30, "\uff08x": 3, "\uff08\u304b\u308a": 2, "\uff08\u304f\u3046": 5, "\uff08\u304f\u3046\u308c\u3064": 5, "\uff08\u3059": 5, "\uff08\u3064\u307e\u308a": 4, "\uff08\u307e\u305f": 18, "\uff08\u30ad\u30fc": 9, "\uff08\u30d3\u30f3": 29, "\uff08\u4f8b": 4, "\uff08\u512a": 7, "\uff08\u5217": [16, 20], "\uff08\uff09": 30, "\uff08\uff0b": 30, "\uff09#": 9, "\uff09<": 30, "\uff09>": 30, "\uff09greeting": 10, "\uff09search": 30, "\uff09shift": 31, "\uff09\u3001": [1, 2, 12], "\uff09\u3002": [5, 6, 8, 9, 11, 14, 16, 23, 30], "\uff09\u300d": 11, "\uff09\u3057\u3066": 9, "\uff09\u30c1\u30e9": 30, "\uff09\u5024": 9, "\uff09\u5207\u308a\u4e0b\u3052": 1, "\uff09\uff09": [5, 21], "\uff09\uff1a": 0, "\uff0f\uff3c": 11, "\uff1a'": 30}, "titles": ["1-0. Colaboratory (Colab) \u306e\u4f7f\u3044\u65b9", "1-1. \u6570\u5024\u6f14\u7b97", "1-2. \u5909\u6570\u3068\u95a2\u6570\u306e\u57fa\u790e", "1-3. \u8ad6\u7406\u30fb\u6bd4\u8f03\u6f14\u7b97\u3068\u6761\u4ef6\u5206\u5c90\u306e\u57fa\u790e", "1-4. \u30c6\u30b9\u30c8\u3068\u30c7\u30d0\u30c3\u30b0", "2-1. \u6587\u5b57\u5217 (string)", "2-2. \u30ea\u30b9\u30c8 (list)", "2-3. \u6761\u4ef6\u5206\u5c90", "3-1. \u8f9e\u66f8 (dictionary)", "3-2. \u7e70\u308a\u8fd4\u3057", "3-3. \u95a2\u6570", "4-1. \u30d5\u30a1\u30a4\u30eb\u5165\u51fa\u529b\u306e\u57fa\u672c", "4-2. \u30a4\u30c6\u30e9\u30d6\u30eb\u3068\u30a4\u30c6\u30ec\u30fc\u30bf", "4-3. \u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3068\u6728\u69cb\u9020", "5-1. \u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u4f7f\u3044\u65b9", "5-2. \u30e2\u30b8\u30e5\u30fc\u30eb\u306e\u4f5c\u308a\u65b9", "5-3. NumPy\u30e9\u30a4\u30d6\u30e9\u30ea", "6-1. \u5185\u5305\u8868\u8a18", "6-2. \u9ad8\u968e\u95a2\u6570", "6-3. \u30af\u30e9\u30b9", "7-1. pandas\u30e9\u30a4\u30d6\u30e9\u30ea", "7-2. scikit-learn\u30e9\u30a4\u30d6\u30e9\u30ea", "\u25b2Jupyter Notebook \u306e\u4f7f\u3044\u65b9", "\u25b2\u30bb\u30c3\u30c8 (set)", "\u25b2\u518d\u5e30", "\u25b2\u7c21\u5358\u306a\u30c7\u30fc\u30bf\u306e\u53ef\u8996\u5316", "\u25b2CSV\u30d5\u30a1\u30a4\u30eb\u306e\u5165\u51fa\u529b", "\u25b2Bokeh\u30e9\u30a4\u30d6\u30e9\u30ea", "\u25b2Python\u30b9\u30af\u30ea\u30d7\u30c8\u3068\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5b9f\u884c", "\u25b2Matplotlib\u30e9\u30a4\u30d6\u30e9\u30ea", "\u25b2\u6b63\u898f\u8868\u73fe", "Python\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0\u5165\u9580", "\u7d22\u5f15"], "titleterms": {"-enter": 22, "-learn": 21, ".rand": 16, ".split": 30, "7\u6708": 26, "_cm": 2, "_disc": 2, "_solution": 2, "_to": 2, "absolute": 3, "add": 23, "and": 7, "arange": 16, "as": 14, "assert": 4, "break": 9, "clear": 23, "colab": 0, "colaboratory": 0, "continue": 9, "copy": 6, "csv": [20, 26], "dataframe": 20, "dictionary": 8, "difference": 23, "discard": 23, "dot": 16, "elif": 7, "else": [7, 9], "enumerate": [9, 12], "filter": 18, "findall": 30, "finditer": 30, "for": [6, 9, 12, 16, 26], "from": 14, "ft": 2, "global": 10, "group": 30, "if": [3, 7], "iloc": 20, "in": 9, "intersection": 23, "items": 8, "iter": 12, "jupyter": 28, "keys": 8, "linspace": 16, "list": 6, "loc": 20, "macos": 28, "map": 18, "matplotlib": 25, "max": [6, 16, 18], "mean": 16, "min": [6, 16], "next": 12, "none": 3, "notebook": [22, 28], "numpy": 16, "ones": 16, "or": 7, "pandas": 20, "pass": 9, "pop": 23, "print": 2, "python": 31, "qe": 2, "quadratic": 2, "random": 16, "range": 9, "re": 30, "remove": 23, "return": [2, 9], "scikit": 21, "series": 20, "set": 23, "shebang": 28, "sign": 3, "sort": 16, "sorted": 18, "string": 5, "sub": 30, "sum": [6, 16], "tuple": 6, "union": 23, "values": 8, "while": 9, "windows": 28, "with": [11, 26], "zeros": 16, "\u25b2bokeh": 27, "\u25b2csv": 26, "\u25b2for": 9, "\u25b2jupyter": 22, "\u25b2matplotlib": 29, "\u25b2python": 28, "\u25b2with": 19, "\u25b2\u30ad\u30fc": 8, "\u3042\u3052": 6, "\u3042\u308a": 21, "\u3042\u308b": [5, 28], "\u3044\u304f\u3089": 1, "\u304a\u3051\u308b": [11, 27, 29], "\u304b\u3089": [6, 18, 20], "\u304c\u308b": 7, "\u3059\u308b": [6, 8, 15, 16], "\u305d\u306e": 30, "\u3067\u3082": 1, "\u3068\u304d": [0, 22], "\u3068\u3057\u3066": [3, 10, 13], "\u306a\u3044": [0, 8, 12], "\u306a\u304f": 22, "\u306a\u3057": 21, "\u306a\u3063": 22, "\u306a\u3069": 6, "\u306a\u308b": 1, "\u306b\u304a\u3051\u308b": [7, 9], "\u306b\u3064\u3044\u3066": 21, "\u306b\u3088\u304f": 5, "\u306b\u3088\u308b": [3, 6, 7, 9, 12, 16, 19], "\u306b\u5bfe\u3059\u308b": [6, 11, 26], "\u306b\u95a2\u3059\u308b": 30, "\u3079\u304d": [1, 24], "\u307e\u305f": 7, "\u307e\u3068\u3081": 1, "\u3082\u3057\u304f": 7, "\u3088\u304f": 16, "\u308c\u308b": [3, 16], "\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9": 15, "\u30a4\u30c6\u30e9\u30d6\u30eb": [12, 18], "\u30a4\u30c6\u30ec\u30fc\u30bf": 12, "\u30a4\u30f3\u30c7\u30c3\u30af\u30b9": [5, 6], "\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30a2\u30af\u30bb\u30b9": 16, "\u30a4\u30f3\u30c7\u30f3\u30c8": 7, "\u30a4\u30f3\u30d7\u30ec\u30fc\u30b9": 6, "\u30a4\u30f3\u30dd\u30fc\u30c8": [1, 14], "\u30a8\u30b9\u30b1\u30fc\u30d7\u30b7\u30fc\u30b1\u30f3\u30b9": [5, 30], "\u30a8\u30e9\u30fc": [1, 4], "\u30aa\u30d6\u30b8\u30a7\u30af\u30c8": [3, 6], "\u30aa\u30fc\u30d7\u30f3": [0, 11], "\u30ab\u30ec\u30f3\u30c8\u30ef\u30fc\u30ad\u30f3\u30b0\u30c7\u30a3\u30ec\u30af\u30c8\u30ea": 13, "\u30ad\u30fc": 8, "\u30ad\u30fc\u30ef\u30fc\u30c9": 10, "\u30af\u30e9\u30b9": [19, 30], "\u30af\u30ed\u30fc\u30ba": 11, "\u30b0\u30e9\u30d5": [25, 27, 29], "\u30b0\u30eb\u30fc\u30d7": 20, "\u30b0\u30ed\u30fc\u30d0\u30eb": 2, "\u30b3\u30de\u30f3\u30c9\u30e2\u30fc\u30c9": 22, "\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3": 28, "\u30b3\u30e1\u30f3\u30c8": [1, 2], "\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u30b9\u30bf\u30a4\u30eb": 4, "\u30b3\u30fc\u30c9": [11, 28], "\u30b7\u30ea\u30fc\u30ba": 20, "\u30b8\u30a7\u30cd\u30ec\u30fc\u30bf": 17, "\u30b9\u30ab\u30e9": 16, "\u30b9\u30af\u30ea\u30d7\u30c8": 28, "\u30b9\u30b3\u30fc\u30d7": 10, "\u30b9\u30e9\u30a4\u30b9": [5, 16], "\u30bb\u30c3\u30c8": [17, 23], "\u30bb\u30eb": [0, 22], "\u30bd\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb": 28, "\u30bd\u30fc\u30c8\u30a2\u30eb\u30b4\u30ea\u30ba\u30e0": [27, 29], "\u30bf\u30d7\u30eb": 6, "\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9": 0, "\u30c6\u30b9\u30c8": 4, "\u30c7\u30a3\u30ec\u30af\u30c8\u30ea": 13, "\u30c7\u30d0\u30c3\u30b0": 4, "\u30c7\u30fc\u30bf": [13, 16, 20, 21, 25], "\u30c7\u30fc\u30bf\u30d5\u30ec\u30fc\u30e0": 20, "\u30ce\u30fc\u30c8\u30d6\u30c3\u30af": 0, "\u30ce\u30fc\u30c8\u30d6\u30c3\u30af\u30d5\u30a1\u30a4\u30eb": 15, "\u30d0\u30c3\u30af\u30b9\u30e9\u30c3\u30b7\u30e5": 5, "\u30d1\u30b9": 13, "\u30d2\u30b9\u30c8\u30b0\u30e9\u30e0": [27, 29], "\u30d2\u30fc\u30c8\u30de\u30c3\u30d7": [27, 29], "\u30d5\u30a1\u30a4\u30eb": [11, 20, 26, 27, 29], "\u30d5\u30a1\u30a4\u30eb\u30aa\u30d6\u30b8\u30a7\u30af\u30c8": 12, "\u30d7\u30ed\u30b0\u30e9\u30df\u30f3\u30b0": 31, "\u30de\u30fc\u30b8\u30bd\u30fc\u30c8": 24, "\u30e1\u30bd\u30c3\u30c9": [5, 6, 8, 19, 23, 30], "\u30e1\u30bf": 30, "\u30e2\u30b8\u30e5\u30fc\u30eb": [1, 14, 15, 28], "\u30e2\u30b8\u30e5\u30fc\u30eb\u30d5\u30a1\u30a4\u30eb": 15, "\u30e2\u30c7\u30eb": 21, "\u30e2\u30fc\u30c9": 22, "\u30e6\u30cb\u30d0\u30fc\u30b5\u30eb": 16, "\u30e9\u30a4\u30d6\u30e9\u30ea": [16, 20, 21, 27, 29], "\u30e9\u30e0\u30c0": 18, "\u30ea\u30b9\u30c8": [6, 8, 9, 17, 18, 24], "\u30ed\u30fc\u30ab\u30eb": 2, "\u30fb\u30af\u30e9\u30b9\u30bf\u30ea\u30f3\u30b0": 21, "\u30fb\u30bf\u30d7\u30eb": 6, "\u30fb\u30c6\u30b9\u30c8": 4, "\u30fb\u30e1\u30bd\u30c3\u30c9": 6, "\u4e00\u6027": 6, "\u4e00\u89a7": 8, "\u4e26\u3073": 20, "\u4e26\u3079\u66ff\u3048": 6, "\u4e88\u7d04": 2, "\u4ed5\u69d8": 4, "\u4ed5\u7d44": 12, "\u4ed8\u304d": 17, "\u4ed8\u3051\u308b": 30, "\u4ee3\u5165": [2, 6], "\u4ee3\u5165\u6587": 2, "\u4ee3\u6570": 16, "\u4f5c\u308a\u65b9": 15, "\u4f5c\u6210": 20, "\u4f7f\u3044\u65b9": [0, 14, 15, 22], "\u4f7f\u308f": [3, 16], "\u4fdd\u5b58": 16, "\u5024\u8aa4": 1, "\u5024\u914d": 16, "\u512a\u5148": 1, "\u5143\u914d": 16, "\u5148\u982d": 28, "\u5165\u308c\u5b50": [9, 17], "\u5165\u51fa": [11, 26], "\u5165\u529b": 5, "\u5165\u9580": 31, "\u5168\u3066": 8, "\u5168\u4f53": 11, "\u5168\u89d2": 1, "\u5177\u4f53": [4, 28], "\u5185\u5305": 17, "\u518d\u5e30": [3, 24], "\u51e6\u7406": 20, "\u51fa\u529b": [27, 29], "\u5206\u5c90": [3, 7], "\u5206\u985e": [4, 21], "\u521d\u5fc3\u8005": 5, "\u521d\u671f": 6, "\u521d\u671f\u5024": 10, "\u5236\u5fa1": 9, "\u524a\u6e1b": 21, "\u524a\u9664": [5, 6, 8, 11, 20], "\u52d5\u4f5c": 11, "\u5358\u9805": 1, "\u53c2\u7167": [0, 2, 20], "\u53cd\u5fa9": 30, "\u53cd\u5fdc": 22, "\u53d6\u308a\u51fa\u3057": 20, "\u53d6\u5f97": 6, "\u53ef\u5909": 10, "\u53ef\u8996": 25, "\u540c\u58eb": 16, "\u56de\u5e30": 21, "\u56de\u6570": [27, 29], "\u57fa\u672c": [11, 30], "\u57fa\u790e": [2, 3, 21], "\u5834\u5408": 8, "\u58ca\u7684": 6, "\u5909\u63db": [1, 6, 15], "\u5909\u6570": [2, 5, 10], "\u591a\u6b21": 16, "\u591a\u91cd": 6, "\u5927\u304d\u304f": 1, "\u5927\u6587\u5b57": 5, "\u5b57\u5217": 5, "\u5b66\u7fd2": 21, "\u5b9a\u7fa9": [2, 10, 12, 19], "\u5b9f\u6570": 1, "\u5b9f\u884c": [0, 4, 28], "\u5ba3\u8a00": [10, 28], "\u5bfe\u5fdc": 19, "\u5c0f\u6587\u5b57": 5, "\u5c5e\u6027": [16, 19], "\u5e30\u95a2": 24, "\u5f15\u6570": [10, 28], "\u5f62\u5f0f": 26, "\u5f97\u308b": 8, "\u5fa9\u5143": 16, "\u6298\u308c": 25, "\u62ec\u5f27": 1, "\u6307\u5b9a": [6, 8, 11], "\u632f\u821e\u3044": 19, "\u633f\u5165": [0, 6], "\u63a5\u5c3e": 24, "\u63a5\u982d": 24, "\u64cd\u4f5c": [0, 6, 16], "\u6539\u5909": 19, "\u6539\u884c": 11, "\u6559\u5e2b": 21, "\u6559\u6750": 0, "\u6563\u5e03\u56f3": [25, 27, 29], "\u6570\u3048": 6, "\u6570\u3048\u4e0a\u3052": 5, "\u6570\u5024": 1, "\u6570\u5b66": 1, "\u6574\u6570": 1, "\u6587\u5b57": [5, 6, 11, 28, 30], "\u6587\u5b57\u5217": [5, 6], "\u65b9\u6cd5": 28, "\u6642\u7cfb": 20, "\u66f8\u304d": 11, "\u66f8\u304d\u65b9": 2, "\u66f8\u304d\u8fbc\u307f": [11, 26], "\u66ff\u3048": 20, "\u671f\u5316": 19, "\u6728\u69cb": 13, "\u6728\u69cb\u9020": 13, "\u6761\u4ef6": [3, 7, 17, 20], "\u6771\u4eac": 26, "\u691c\u7d22": 5, "\u69cb\u6587": [4, 7], "\u69cb\u7bc9": 16, "\u69cb\u9020": [9, 13], "\u69d8\u3005": 3, "\u6a5f\u68b0": 21, "\u6b20\u640d": 20, "\u6b21\u5143": 21, "\u6b62\u307e\u3089": 0, "\u6b63\u898f": 30, "\u6bd4\u8f03": [3, 5, 6, 23, 27, 29], "\u6c17\u6e29": 26, "\u6ce8\u610f": 22, "\u6df7\u4e71": 5, "\u6f14\u7b97": [1, 3, 5, 6, 16, 23, 30], "\u6f14\u7b97\u5b50": [1, 6, 7], "\u7279\u6b8a": [12, 19], "\u7406\u7531": 30, "\u751f\u6210": [6, 16], "\u753b\u50cf": 29, "\u767b\u9332": 8, "\u76f8\u4e92": 6, "\u771f\u7406": 16, "\u771f\u7406\u5024": 3, "\u77ed\u7e2e": 6, "\u7834\u58ca": 6, "\u7a7a\u6587": 5, "\u7a7a\u767d": [1, 5], "\u7a7a\u884c": 2, "\u7acb\u3061\u4e0a\u3052": 0, "\u7b49\u4fa1": 6, "\u7b97\u8853": 1, "\u7c21\u5358": [1, 25], "\u7d22\u5f15": 32, "\u7d2f\u7a4d": 2, "\u7d44\u307f\u8fbc\u307f": [6, 23], "\u7d50\u5408": [7, 20], "\u7d71\u8a08": 20, "\u7d99\u627f": 19, "\u7dda\u5f62": 16, "\u7de8\u96c6": [0, 11, 22], "\u7df4\u7fd2": [0, 1, 2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 16, 17, 18, 19, 21, 22, 23, 26, 28, 29, 30], "\u7e70\u308a\u8fd4\u3057": [6, 9, 12], "\u7f6e\u63db": 5, "\u81ea\u4f5c": 15, "\u884c\u3046": 8, "\u8868\u73fe": [13, 30], "\u8868\u793a": [1, 5], "\u8868\u8a18": 17, "\u8907\u6570": [7, 10], "\u8907\u88fd": 8, "\u8981\u7d20": [6, 16], "\u8981\u7d20\u578b": 16, "\u8981\u7d20\u6bce": 16, "\u89e3\u7b54": [2, 3, 5, 6, 7, 8, 9, 11, 12, 14, 16, 17, 18, 19, 21, 23, 26, 28, 29, 30], "\u89e3\u8aac": [7, 9], "\u8a08\u7b97": [1, 9, 24], "\u8a18\u6cd5": 6, "\u8a55\u4fa1": 7, "\u8aa4\u89e3": 5, "\u8aad\u307f": 11, "\u8aad\u307f\u8fbc\u307f": [11, 26], "\u8ad6\u7406": [3, 4], "\u8f9e\u66f8": [8, 9, 10, 17], "\u8fd4\u3059": [3, 12], "\u8fd4\u5024": [2, 8, 10], "\u8ffd\u52a0": [6, 20], "\u9006\u9806": 6, "\u9023\u7d50": [5, 20], "\u90e8\u5206": 28, "\u914d\u5217": 16, "\u9577\u5f15": 10, "\u95a2\u6570": [1, 2, 3, 6, 10, 16, 18, 23, 30], "\u968e\u5c64": 13, "\u96c6\u5408": 23, "\u975e\u7834": 6, "\u9806\u4f4d": 1, "\u9806\u756a": 10, "\u9ad8\u968e": 18, "\uff08sort": 6, "\uff08sorted": 6, "\uff09shift": 22}}) ================================================ FILE: docs/toc.html ================================================ Pythonプログラミング入門 — Pythonプログラミング入門 documentation