Slide 1

Slide 1 text

Python3 無料トレーニング資料 (技術評論社公認) 内容 • 解説資料(1-2時間) x 8章 • 演習 x 8章 • おまけ(プログラミング上達法) オリジナルの書籍 副読本もしくは次のステップにご利⽤ください!! Amazon: たった1⽇で基本が⾝に付く! Python超⼊⾨

Slide 2

Slide 2 text

⽬次 はじめに Python3をWindowsとMacにインストールしよう Pythonでプログラミングを始めよう 制御構⽂を理解しよう 関数の使い⽅をマスターしよう オブジェクト指向を理解しよう クラスの使い⽅をマスターしよう モジュールを利⽤しよう ファイルの読み書きと例外処理を⾏おう アプリケーションを作成しよう おまけ。レベル別プログラミングスキル向上法など CHAPTER 1 CHAPTER 2 CHAPTER 3 CHAPTER 4 CHAPTER 5 CHAPTER 6 CHAPTER 7 CHAPTER 8

Slide 3

Slide 3 text

はじめに • この資料は技術評論社より出版されている「たった1⽇で基本 が⾝に付く! Python超⼊⾨(ISBN978-4-7741-9112-6)」を著者 (伊藤裕⼀)が出版社の許諾を得てトレーニング資料として公開 しております。 • 個⼈だけでなく企業や組織も利⽤できますが、本資料⾃体や改 変したものを営利⽬的(販売、有償トレーニング)で利⽤するこ とは禁⽌いたします。⼤学での講義や社内トレーニングでの利 ⽤は問題ありませんが、当資料を改変して出⾃を不明にするこ とはお控えください。 • 本資料内で利⽤している図などの著作権は技術評論社及び著者 に帰属します。本資料外で利⽤することはお控えください。

Slide 4

Slide 4 text

皆様へのお願い • 書籍を底本として当資料のみでPython3を学べる構成としてお りますが、書籍はトレーニング講師の解説に相当する丁寧で詳 細な説明がされています。 • 書籍及び当資料の制作にもコストがかかっていますので、オリ ジナルの書籍を副読本もしくは本資料を完遂した次の学習ス テップとして購⼊頂けると出版社及び著者としては幸いです。 • Amazon: たった1⽇で基本が⾝に付く! Python超⼊⾨

Slide 5

Slide 5 text

サンプルファイルのダウンロード • 以下のURLより書籍で利⽤しているサンプルファイルをダウン ロードできます。 • 書籍の内容が本スライドと100%同⼀ではないため、使わない ファイルやここにないファイルがあることにご留意ください。 • http://gihyo.jp/book/2017/978-4-7741-9112-6/support

Slide 6

Slide 6 text

広告(1): 技術評論社(書籍出版元) • DockerとKubernetesの書籍を2020年夏に販売 • コンテナの基礎に加えて開発技法やコンテナベースアプリケー ションのCI/CD環境の構築なども扱う 書籍表紙絵 (あとで更新) ⽬次 • Dockerを使ってみよう • イメージの利⽤と開発を体験しよう • ネットワークとストレージ • Dockerfileでイメージ作成しよう • Composeを使ってマルチコンテナアプリを作ろう • DockerアプリでCI/CDしよう • Kubernetes⼊⾨ • Kubernetesの利⽤

Slide 7

Slide 7 text

広告(2): Nutanix(トレーニング資料作成) • プライベートクラウドの構築ソフトウェア開発会社 • AWS類似のクラウドをオンプレミス(⾃社内)に数時間で構築可能 • ご相談は「https://www.nutanix.com/jp」へ • インフラ⾃動化やDevOps系は著者が⽀援可能 ネットワーク機器 (L2/L3スイッチ) サーバー サーバー サーバー サーバー クラスタ(冗⻑化と障害時の⾃動回復) 簡単な構築作業 1. サーバーをラックに設置 2. 物理スイッチにケーブル接続 3. 構築ツールで⾃動構築 構築ツール (VMアプライアンス) GUIでIP設定など (約10分) アプライアンスがサーバーを検出して インストール指⽰後は⾃動で構築(約1時間) • ブラウザ管理画⾯(⽇本語) • ハイパーバイザー • ファイルサーバー • ブロックストレージ • オブジェクトストレージ • バックアップ • マネージドKubernetes • マネージドデータベース • パブリッククラウド連携 • マイクロセグメンテーション • VDI(仮想デスクトップ基盤) • 監視、その他 ほぼフルスタックなクラウド機能 使いやすい操作画⾯(REST APIサポート)

Slide 8

Slide 8 text

著者について • Nutanix社のソリューションスペシャリスト(DevOps)。開発 + インフラ屋 • 得意領域 • ソフトウェア開発およびDevOps(CI/CD) • コンテナとオーケストレーション • モダンアプリケーション開発と⾃動化 • パブリック/プライベートクラウド • ネットワーク(L2/L3) • サーバー仮想化(VMWare, KVM) • サーバーOS(Linux) • 略歴(英語): LinkedIn(@yuichiito) • 副業で技術書や記事の執筆。企業や⼤学向け技術資料作成をしています • 仕事依頼はメールで[email protected]にお願いします 出版社様へ。中級者を想定したモダンなLinuxの使い⽅の本を書きたいです。 Twitter(@yuichi110)

Slide 9

Slide 9 text

WindowsにPython3をインストールする (1/3) • WindowsにはPythonはインストールされていない • 公式サイト(https://www.python.org/)にアクセスする • 「Python3」のインストーラーをダウンロードし起動

Slide 10

Slide 10 text

WindowsにPython3をインストールする (2/3) • インストーラーをブラウザもしくはダブルクリックで起動

Slide 11

Slide 11 text

WindowsにPython3をインストールする (3/3) • インストーラーのガイドにしたがってインストール • 「パスを通すにチェックをつける(4)」を忘れないこと

Slide 12

Slide 12 text

MacにPython3をインストールする • Macには標準でPythonがインストールされているが古い(2系) • 公式サイトからPython3系のインストーラーを⼊⼿しインス トールを実施。ガイドにそってインストール • Mac標準のPython2でPython3を想定した本トレーニングのプ ログラムは実⾏できない場合が多いのでご注意ください。

Slide 13

Slide 13 text

Pythonでプログラミングを始めよう CHAPTER 1 1. プログラミングとPythonについて知る 2. Pythonで電卓代わりに計算する 3. 値を格納する「変数」を理解する 4. データの種類を決める「型」を理解する

Slide 14

Slide 14 text

プログラミングとPythonについて知る • このセクションで学ぶこと • プログラムってなに? • プログラミング⾔語の存在意義 • なぜプログラミング⾔語としてPythonを選ぶか • コンパイル型とインタプリタ型の⾔語の違い SECTION 01

Slide 15

Slide 15 text

プログラムはコンピューターへの指令書 • 「プログラム」は機械に「こう動け」と命令する指令書 • PCのアプリだけでなく、ブラウザのサービス(検索エンジンや ウェブメールなど)も提供会社側でプログラムが動いている • プログラムを書くこと「プログラミング」という • プログラムのことを「コード」、プログラミングのことを 「コーディング」ともいう

Slide 16

Slide 16 text

プログラミング⾔語で機械への命令が簡単に • 機械は電気のON/OFF(01の2進数)で状態を管理している • 最終的に01で命令を機械に伝える必要があるが、⼈間が01を扱 うことは難しい • プログラミング⾔語は「01しか使えない機械」と「⾃然で曖昧 な⾔葉を使う⼈間」の間にある「厳格な⽂法の⼈⼯⾔語」 • ⼈間がプログラミング⾔語で命令を書き、機械がそれを01に変 換して解釈実⾏する ⼈間の領域 (曖昧) 機械の領域 (01) プログラミング⾔語

Slide 17

Slide 17 text

Pythonを選ぶ理由 • 「なにをやりたいか(⽬的)」に応じて使うプログラミング⾔語 は変わってくる • Pythonは「簡単である(すぐに覚えられる、同じプログラムを 他の⾔語より素早く書ける)」ことに加えて、「広範囲の開発作 業に使える」「インタプリタ型」という特徴があるのでおすす め

Slide 18

Slide 18 text

コンパイル型とインタプリタ型の⾔語の違い • コンパイル型: プログラミング⾔語から機械語(01)に事前変換 • インタプリタ型: 実⾏時にプログラミング⾔語から機械語に変換 • Pythonはインタプリタ型の⾔語 • インタプリタ型はコンパイルの⼿間(時間)がないので開発が楽

Slide 19

Slide 19 text

Pythonが苦⼿なこと • 超⾼速性が求められるシステムやデスクトップアプリケーション(⼀ 般ユーザー向けの再配布)、組み込み機器の開発が苦⼿。多くのスク リプト系⾔語も全く同じ領域が苦⼿ • ⾼速な処理(科学計算系はライブラリが⾼速なので問題なし)。⼀般 的にインタプリタ型はコンパイラ型に⽐べると実⾏時にコンパイル するので遅い。速度は⾔語より設計やアルゴリズムに起因すること が多いので、⾔語の速度はプログラミング上級者になってから気に すれば問題なし • Pythonがインストールされている環境でPythonアプリを利⽤するこ とは簡単だが、Pythonがインストールされていない環境(⼀般ユー ザーのPC)で動かすのは不可能ではないものの⼿間がかかる。 • 組み込み機器のような機械に近いレイアはPythonが使えないことが 多い 。基本は汎⽤OSの上でPythonを使う

Slide 20

Slide 20 text

汎⽤性の⾼さもPythonの魅⼒ • プログラミング⾔語には得意苦⼿がある • 様々なことが得意な⾔語を学べば何にでもその⾔語を使える • 利⽤⽬的が限られる⾔語は⽬的ごとに複数⾔語の習得が必要 • C⾔語: OSに近い領域や組み込み向けのプログラミングが得意 • Python • 使い捨ての短い簡単なスクリプトでも使える • ⼤規模なシステムの開発でも使える • ウェブサービスの開発でも使える • 科学計算(機械学習/ビッグデータ処理など)でも使える

Slide 21

Slide 21 text

プログラミング⾔語の分類とPython • プログラミング⾔語は以下の3種類に分類できる • ⼿続き型⾔語(オブジェクト指向型⾔語のベース) • オブジェクト指向型⾔語(現在の主流。Pythonも) • 関数型⾔語 • ただしPythonは⼿続き型のような書き⽅もできるし、関数型の ような書き⽅(中上級者向け)もできる ⼿続き型 ⾔語 オブジェクト 指向型⾔語 関数型 ⾔語 Python

Slide 22

Slide 22 text

• なぜプログラムの作成にアセンブリ⾔語ではなくモダンなプロ グラミング⾔語を使うべきか説明してください • コンパイル型とインタプリタ型のプログラミング⾔語の違いを 説明してください • スクリプトやウェブサービスの開発にC⾔語ではなくPythonを 使うべき理由を説明してください • Pythonが苦⼿な領域を説明してください 演習

Slide 23

Slide 23 text

Pythonで電卓代わりに計算する • このセクションで学ぶこと • Pythonの起動⽅法: Windows, Mac • Pythonのバージョン • インタラクティブシェルを操作して計算 • 値(あたい)とは SECTION 02

Slide 24

Slide 24 text

Windows: PowershellでPythonを起動する • 「インタラクティブシェル」は対話形式でPythonを利⽤する操 作法で「REPL(Read Eval Print Loop)」やとも呼ばれる • Windows左下の検索ボックスに「powershell」と⼊⼒して PowerShell(コマンドラインアプリ)を起動 • Powershellで半⾓にて「python」と⼊⼒することで起動する • インストール時にパスを通し忘れていると「pythonというコマ ンドは存在しない」といった旨のエラー。再インストール。

Slide 25

Slide 25 text

Mac: ターミナルでPythonを起動する(1/2) • ターミナルアプリケーションを開く

Slide 26

Slide 26 text

Mac: ターミナルでPythonを起動する(2/2) • ターミナルで「python3」と⼊⼒して起動 • 注意: Macでは「python」と⼊⼒するとPython3ではなくデフォル トでインストールされているPython2が起動する。両者とも Pythonだが仕様(⽂法など)が⼤きくことなるので注意 • 本資料ではWindowsを優先してpython表記とするが、python3と 読み替えること

Slide 27

Slide 27 text

コラム: Pythonとバージョン • バージョン: Python X.Y という形式。Xがメジャーバージョン (Windows7, 10などのレベル)でYがマイナーバージョン(リリー ス時期やパッチなどのレベル)。 • Python2: ⼀般普及した最初のメジャーバージョン。新規開発は 停⽌している。バージョン2で開発されたシステムのメンテ作 業は2020年代中盤あたりまでは継続することが予想される。⽇ 本語の扱いが苦⼿ • Python3: 現在普及しているメジャーバージョン。今から学ぶな らPython3をやるべき。新規開発も当然ながらPython3を使う • Python2と3は似ているが⽂法やライブラリが異なる別⾔語

Slide 28

Slide 28 text

インタラクティブシェルで⾜し算、引き算 • インタラクティブシェルの挙動 1. 「>>>」に続けて実⾏したいことを書く 2. Enter(Return)キーを押す 3. Pythonが書かれていることを解釈する 4. Pythonが実⾏結果を画⾯に表⽰する 5. ステップ1に戻る $ python Python 3.8.2 (v3.8.2:7b3ab5921f, Feb 24 2020, 17:52:18) [Clang 6.0 (clang-600.0.57)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> 5 + 3 8 >>> 7 - 2 5 注意: MacはPython3コマンドで起動

Slide 29

Slide 29 text

インタラクティブシェルで掛け算、割り算、剰余 • ⾜し算(+)引き算(-)は算数と同じ記号を使う • 掛け算には「*」記号を使う • 割り算には「/」記号を使う • 剰余(余り。たまに使う)では「%」記号を使う • 算数と同じく⼩カッコ「()」で計算順序を調整できる >>> 4 * 4 16 >>> 7 / 2 3.5 >>> 31 % 2 1 >>> 5 + 2 * 3 11 >>> (5 + 2) * 3 21

Slide 30

Slide 30 text

値(あたい)とは • 「値(あたい)」はPythonが扱うデータのこと。英語ではvalue • たとえば数字の4や5 • たとえばテキスト(⽂字列と呼ばれる)のHello • 今後学ぶ様々な種類のデータも値

Slide 31

Slide 31 text

• インタラクティブシェルを⽴ち上げて、「10 x 2」の計算を実 施してください • 「5 ÷ 2」の計算を実施してください • 「5 + 2 * 2」と「(5 + 2) * 2」の計算結果の違いを確認し、な ぜ結果が異なるか説明してください • Python2とPython3の違いについて説明してください 演習

Slide 32

Slide 32 text

値を格納する「変数」を理解する • このセクションで学ぶこと • 変数と代⼊ • 変数の名前のつけかた • 複合代⼊演算⼦ • 定数 SECTION 03

Slide 33

Slide 33 text

変数とは (1/3) • 「変数」は値を格納する容器 • 作成した変数に値をいれることを「代⼊」するという • 変数に代⼊された値は必要なときに⾃動で取り出される • 変数から値が取り出されてもなくならない

Slide 34

Slide 34 text

変数とは (2/3) • 変数を作成することを「宣⾔」するという • 「変数 = 値」という⽂法で変数の宣⾔と代⼊を同時におこなう。 (他のプログラミング⾔語では変数の宣⾔のみできるものもある が、Pythonでは宣⾔時に代⼊もおこなう) >>> abc = 51 >>> abc 51 >>> abc + 5 56 >>> abc + 10 61 変数abcを宣⾔し、51を代⼊ 変数abcから51が取り出されている 値が変数から取得されても中⾝はなくならない

Slide 35

Slide 35 text

変数とは (3/3) • 変数に新しい値を代⼊(「再代⼊」とよばれる)すると、古い値 は上書きされてなくなる • 変数Aに変数A(⾃分⾃⾝)や変数Bの値を代⼊することもできる >>> abc = 51 >>> abc + 5 56 >>> abc = 8 >>> abc 8 >>> abc = abc + 3 >>> abc 11 すでに存在している変数に新しい値を代⼊(再代⼊) 変数が持つ値は新しい値で上書きされる 変数に変数の値を代⼊することもできる。 左は「abc = 8 + 3」と同じ意味

Slide 36

Slide 36 text

変数の⽤語 • 変数を作成すること => 「宣⾔」する • 変数に値をいれること => 「代⼊」する • すでに変数を持つ変数に値をいれること => 「再代⼊」する • 変数に値を代⼊する記号 => 「代⼊演算⼦」。「=」のこと • 変数から値を取り出すこと => 変数が値を「返す」 • これらの⽤語はプログラマの常識なので、知っていないと専⾨ 書籍を読んだりプログラマと会話する際に困ります。覚えて⾃ 分も使うことをおすすめします。

Slide 37

Slide 37 text

変数名の規則 • 変数に使える記号は「アルファベットと数字及びアンダーバー (_)」が基本。⽇本語も使えるがおすすめしない。 • 「必ずアルファベットから始まる」というルールがある • Pythonでは変数に⼤⽂字を使わないのが⼀般的 • 特別な意味を持つ予約後(たとえばforなど)は使えない • 変数名にはなにが⼊っているか分かりやすいものを使う >>> abc = 3 >>> 5ab = 3 File "", line 1 5ab = 3 ^ SyntaxError: invalid syntax >>> price = 100 >>> text_length = 10 問題のある変数名はエラーとなる 上記のような分かりやすい名前が望ましい。 意味を持つ⼩⽂字英数字で単語の区切りを アンダーバーとするのが⼀般的なPythonの 変数の名付けかた。 この命名規則は「スネークケース」と呼ばれる

Slide 38

Slide 38 text

複合代⼊演算⼦ • 代⼊と演算(+や-)を同時にやる特殊な演算⼦は「複合代⼊演算 ⼦」と呼ばれる • 代⼊演算⼦の前に演算記号がつく。たとえば「+=」 • すでに代⼊されている変数を加⼯するためによく使われる • 変数に1を加えることを「インクリメント」と呼び、Pythonは それを複合代⼊演算⼦で実現する。「a += 1」 >>> a = 10 >>> a += 1 >>> a 11 >>> a -= 5 >>> a 6 複合代⼊演算⼦の例 同⼀の意味を持つ命令 a += 1 a = a + 1 a -= 5 a = a - 5 a *= 10 a = a * 10 a /= 3 a = a / 3

Slide 39

Slide 39 text

値の変わらない定数 • ⽬的の分からない値のことを「マジックナンバー」と呼ぶ • マジックナンバーやプログラムのパラメーター(たとえば処理を 何秒おきに呼び出すか)などは「定数」で宣⾔するのが⼀般的 • 定数は「⼤⽂字英数字とアンダーバーを使う」のが⼀般的 • プログラムファイル内で定数を使っているとパラメーター変更 時のコード変更箇所を減らせる • 変数と異なり「定数は内部の値が変化しない」特徴がある >>> 100 * 1.08 108.0 >>> TAX_RATE = 1.08 >>> 100 * TAX_RATE 108.0 100に1.08をかけている理由が分からない。 これなに? 1.08が定数 TAX_RATE に代⼊されていると、 100に消費税 1.08 をかけていると⼀⽬瞭然。 宣⾔部を1.1に変えれば消費税率の変更にすぐ対応できる

Slide 40

Slide 40 text

コラム: Pythonの定数 • 多くのプログラミング⾔語では定数に値を再代⼊するとエラー が発⽣する • Pythonでは定数に再代⼊してもエラーが発⽣しない • 実はPythonには⽂法としての定数はなく、ただの変数に過ぎな い。ただし、「⼤⽂字で宣⾔された変数は定数として使われ る」というのはPythonプログラマの常識なので再代⼊をするこ とは避ける必要がある。⼤⽂字の変数を定数として使う。

Slide 41

Slide 41 text

• インタラクティブシェルを⽴ち上げて、変数abに5を代⼊し、 次に変数cdに10を代⼊し、最後に変数同⼠を⾜し算して結果を 確認してください • 変数aに10を代⼊し、それを複合代⼊演算⼦を使ったインクリ メントで11にしてください • 変数と定数の役割の違いについて説明してください • ⼀般的なPythonの変数名と定数名の命名ルールを説明してくだ さい 演習

Slide 42

Slide 42 text

データの種類を決める「型」を理解する • このセクションで学ぶこと • ⽂字列 • データの種類と型 • 概念としての型と、実データとしての値 • 関数(詳細は3章) • type関数で型を調べる⽅法 • キャストを使った型の変換⽅法 SECTION 04

Slide 43

Slide 43 text

⽂字列 • テキストデータは「⽂字列」と呼ばれる。⽂字が1つの字でそ れが列(複数)となるので⽂字列 • 1⽂字もない(空⽂字と呼ばれる)や1⽂字でも⽂字列と呼ばれる • ⽂字列は「シングルクオテーション(')」か「ダブルクオテー ション(")」でテキストを囲うことで宣⾔できる。Pythonではシ ングルクオテーションを使うのが⼀般的 >>> a = 'h' >>> b = 'hello' >>> c = 'hello world' >>> d = "hello 123" >>> e = '' これらはすべて⽂字列

Slide 44

Slide 44 text

⽂字列の演算 • ⽂字列も数値と同じように演算できる • ただし⾜し算(結合)はできるが、引き算はできない • 数値の「123」と⽂字列の「'123'」はデータの種類が異なるの で同じではない >>> 'abc' + '123' 'abc123' >>> '123' + '456' '123456' >>> 123 + 456 579 >>> a = '123' >>> a += '456' >>> a '123456' >>> 456 - 123 333 >>> '456' - '123' Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for -: 'str' and 'str' ⽂字列の123は数値計算されていない

Slide 45

Slide 45 text

⽇本語の⽂字列 • Python3では⽇本語の⽂字列も使える。Python2は⽇本語が苦⼿ • アルファベットと異なり「⽂字コード(Shift-JISやUTF-8など)」 に気を配る必要がある • Python3のデフォルト⽂字コードはUTF-8なので「Pythonでは常 にUTF-8を使う」とルール化するのが⼀般的 • Shift-JISなどを含んだ⽇本語の詳細は7章で扱う $ python3 >>> 'あいうえお' + 'かきくけこ' 'あいうえおかきくけこ' $ python2 >>> 'あいうえお' + 'かきくけこ' '\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81 \x88\xe3\x81\x8a\xe3\x81\x8b\xe3\x81\x8d\xe3\ x81\x8f\xe3\x81\x91\xe3\x81\x93' MacでのPython3とPython2の⽇本語の扱い

Slide 46

Slide 46 text

概念とデータ - 型が持つ2つの性格 • 「123」と「'123'」の演算は異なる動きとなった。 • これは両者の値の「型(データの種類)」が異なるため • 型が「データの概念レベル」で値が「実際のデータ」 • どの型がどういった処理をできるか覚えるのがプログラミング の最初の⼀歩

Slide 47

Slide 47 text

関数 • 「受け取った値」にたいして「決められた処理」をおこない、 「結果を返す」仕組みをプログラミングでは「関数」と呼ぶ • 「結果を受け取る変数 = 関数名(関数に与える値)」という書式 で使うのが⼀般的 • 関数に与える値のことを「引数」と呼び、関数から返される値 を「返り値」と呼ぶ • 関数の詳細は第3章で扱う >>> print(15) 15 >>> print('hello world') hello world print関数は与えられた値をコンソール出⼒する

Slide 48

Slide 48 text

type関数を使った型の確認 • Pythonは「あまり型にうるさくない⾔語」 • メリット: 気軽にコーディングをおこなえる • デメリット: 変数に⼊っている型が想定していたものと違う といったトラブルがある • 「type 関数」を使うことで変数の型を確認できる • 拘束性は⾼くないが変数名に型を宣⾔することも可能(割愛) >>> a = 10 >>> type(a) >>> a = 'hello' >>> type(a) 数値を代⼊した変数aに⽂字列を再代⼊できる。 型にうるさい⾔語(C⾔語やJava)ではできない。 type関数に変数(そのなかの値)を与えると型がわかる。 intは「整数型」のこと

Slide 49

Slide 49 text

キャストを使った型の変換(1/2) • プログラミングでは型を変換する場⾯が多々ある • たとえば「⽂字列型の値と整数型の値は結合できない」ので整 数型を⽂字列型に変換してから結合など • 型の変換のことを「キャスト」と呼ぶ >>> price = 100 >>> price + ' yen' Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for +: 'int' and 'str' 数値と⽂字列型の結合でエラーが発⽣

Slide 50

Slide 50 text

キャストを使った型の変換(2/2) • ⽂字列型への変換には「str 関数」を使う • 整数型への変換には「int 関数」を使う • ⽂字列から数値へのキャストは変換できれば成功し、変換でき ない場合は失敗する >>> price = 100 >>> str(price) + ' yen' '100 yen' >>> int('100') 100 >>> int('hello') Traceback (most recent call last): File "", line 1, in ValueError: invalid literal for int() with base 10: 'hello' 数値を⽂字列型にキャストしてから 別の⽂字列と結合 ⽂字列から数値へのキャストは失敗することがある

Slide 51

Slide 51 text

コラム: シングルクオートとダブルクオート • ダブルクオートの⽂字列内ではシングルクオートが使え、シン グルクオートの⽂字列内ではダブルクオートが使える。 • そのため、以下の使い分けがおすすめ • 通常時: シングルクオート(Pythonでは⼀般的なため) • ⽂字列内にシングルクオートを持つ場合: ダブルクオート • エスケープシーケンス(後述)を使うことでシングルクオートの ⽂字列内でシングルクオートを使うこともできる。ダブルク オートも同様 >>> 'hello I'm Taro' File "", line 1 'hello I'm Taro' ^ SyntaxError: invalid syntax >>> "hello I'm Taro" "hello I'm Taro" >>> 'hello I\'m Taro' "hello I'm Taro" >>>

Slide 52

Slide 52 text

• 値「123」と値「'123'」の違いを説明してください • 「'123' + '123'」の結果がどうなるか確認し、キャストを使っ て結果が246になるように式を変更してください • 数値「1.1」の型をtype関数で確認してください 演習

Slide 53

Slide 53 text

制御構⽂を理解しよう CHAPTER 2 1. プログラムファイルを作って実⾏する 2. 条件分岐の仕組みを理解する 3. ループ処理で繰り返しを記述する

Slide 54

Slide 54 text

プログラムファイルを作って実⾏する • このセクションで学ぶこと • IDLE(標準の統合開発環境)の起動⽅法 • 新規ファイルの作成と保存⽅法 • IDLEでのプログラムの実⾏⽅法 • わざとエラーを発⽣させてエラー内容を読む • コメント • コンソールからプログラムを実⾏ • コラム: 複数⾏にわたる⽂字列 SECTION 01

Slide 55

Slide 55 text

IDLE(統合開発環境)の起動 • Pythonをインストールするとには「IDLE」という統合開発環 境も同時にインストールされている • Windows: スタートメニューから選択(以下の図)して起動 • Mac: アプリケーションのディレクトリから起動

Slide 56

Slide 56 text

IDLEで新規ファイルを開く • IDLEのメニューは英語表記だが操作は単純 • プログラムを開発するために図の⼿順で新規ファイルを開く • 新規ファイルを開くとエディタの画⾯が現れる • 既存のファイルを開くこともできる。以下の図の「Open..」

Slide 57

Slide 57 text

IDLEでファイルを保存する • エディタに以下のプログラム(スライド5PめのURLより以後の プログラム全てをダウンロード可能)を記述する • メニューバーから保存操作(図を参照)する • 保存する場所は「デスクトップ上のpythonフォルダ」とし、そ こに「test_01.py」という名前で保存 print(1) print('2') a = 1 + 2 print(a) /chapter2/test_01.py

Slide 58

Slide 58 text

IDLEでプログラムを実⾏ • IDLEのプログラムのエディタを選択(クリックして前⾯に) • 以下のいずれかの⽅法で実⾏ • メニューバーの「 -> 」 • F5ボタン(MacだとFnボタンを押しながら)を押す • インタラクティブシェルと異なりprint関数などで意図的に出⼒ させないとどのような動きをしているか⾒えない

Slide 59

Slide 59 text

エラーを発⽣させて確認する • プログラムを開発していると、勘違いや⼊⼒ミスで必ずエラー は発⽣する • エラーを特定して問題箇所の修正を繰り返すことでプログラム はきちんと動作するようになる • わざとエラーを発⽣させてエラーの読み⽅を確認してみる print(1) print('2') a = 1 + 2 print(b) 1 2 Traceback (most recent call last): File "/Users/yuichi/Desktop/python/test_02.py", line 4, in print(b) NameError: name 'b' is not defined エラーメッセージから「どのファイル(test_02.py)」の 「どの⾏(line 4)」で 「どのような問題(NameError: name ʻbʼ is not defined)」が おきているかわかる /chapter2/test_02.py コンソール出⼒

Slide 60

Slide 60 text

コメント • 「コメント」: プログラム中の実⾏されない特別なテキスト • プログラムの説明(なにをしているか注釈)に利⽤したり、実⾏ してほしくない箇所をコメント化する使い⽅が⼀般的 • コメントの⽅法 • 「#(シャープではなくハッシュと読む)」の後ろ(1⾏) • 「'''」もしくは「"""」で囲まれた複数⾏のテキスト #print(1) print('2') ''' a = 1 + 2 print(b) ''' 2 /chapter2/test_03.py コンソール出⼒ コメントした箇所が実⾏されていないので、 コンソール出⼒されていないことがわかる。 さきほどのエラー箇所も無視されている。 プログラムをコメント化することを 「コメントアウト」という

Slide 61

Slide 61 text

コンソールからプログラムを実⾏ • Pythonのプログラムはコンソール(Powershellやターミナル)か ら実⾏できる。 • プログラムファイルを指定してpythonコマンドで呼び出す • 本格的な開発ではプログラミング⽤エディタ(VSCodeなど)で 開発してコンソール実⾏するか、IDLEより⾼度な IDE(PyCharmなど)の利⽤が⼀般的 PS C:\Users\yito> cd ~/Desktop/python PS C:\Users\yito\Desktop\python> python test_01.py 1 2 3 $ cd ~/Desktop/python $ python3 test_01.py 1 2 3 Windowsの例 Macの例 (python3コマンド)

Slide 62

Slide 62 text

コラム: 複数⾏にわたる⽂字列 • 「トリプルクオテーション(''')」を使った複数⾏のコメントア ウトは厳密には「囲んだ箇所を⽂字列化」している • 純粋な複数⾏のコメントアウトの⽂法はない • ⽂字列化でのコメントアウトに問題がある場合はすべての⾏に 「#」をつけてコメントアウトする text = '''hello world python''' print(text) $ python3 multi_line_string.py hello world python /chapter2/multi_line_string.py コンソール出⼒

Slide 63

Slide 63 text

コラム: エスケープシーケンス • 改⾏やタブといった特殊⽂字を使う場合は「エスケープシーケ ンス」を使う • エスケープシーケンスは半⾓バックスラッシュ「\」(⽇本語 キーボードだと半⾓「\」記号)に続けて特定の1⽂字を書く • よく使うエスケープシーケンス • 改⾏: \n • タブ: \t • シングルクオテーション: \' • ダブルクオテーション: \" >>> print('hello\nworld') hello world エスケープシーケンス「\n」で 改⾏されている

Slide 64

Slide 64 text

• IDLEを起動して以下のプログラム(1)を新規作成して実⾏ • プログラミング⽤エディタ(好みがなければVSCodeをインス トール)で以下のプログラム(1)を作成して、コンソールで実⾏ • インタプリタで以下の出⼒(2)をする • コメントの利⽤⽤途を2つ以上説明する 演習 print('I love Python') I will complete this training プログラム(1) 出⼒(2)

Slide 65

Slide 65 text

条件分岐の仕組みを理解する • このセクションで学ぶこと • 絶対値を求めるabs関数 • abs関数の条件分岐 • if⽂を使った条件分岐 • インデントによるコードブロック • Bool型 • ⽐較演算⼦ • Bool値を扱う演算⼦ • 複雑なif⽂ SECTION 02

Slide 66

Slide 66 text

絶対値を求めるabs関数 • 絶対値はある数値(マイナスも含む)の0からの距離 • 「変化の⼤きさ」を表現するのに使われる • Pythonでは「abs関数」を使うことで絶対値を求められる >>> abs(5) 5 >>> abs(-10) 10 >>> abs(0) 0 インタプリタでのabs関数の確認

Slide 67

Slide 67 text

abs関数の条件分岐 • 「条件分岐」は「ある特定の条件を満たす場合のみ、何かの処 理をする」という仕組み • 絶対値を得る条件分岐は 「値(変数aとする)が0より⼤きいとい う条件」を満たす場合のみ「値に-1をかけてプラスにする」と いう処理をする abs関数の条件分岐

Slide 68

Slide 68 text

if⽂を使った条件分岐 • Pythonで条件分岐を使うには「if」を使う • ifに続けて「条件式(TrueかFalseが得られる式)」を書く • 次の⾏以降でインデント(字下げ)して処理を書く • 注意: 他のプログラミング⾔語のようにifのあとに()で条件式を 囲んでも問題ないが、Pythonでは囲まないのが⼀般的 a = -5 if a < 0: a = a * -1 print(a) if 条件式: 条件式を満たす場合の処理 /chapter2/abs_01.py $ python3 abs_01.py 5 コンソール出⼒ If⽂の⽂法

Slide 69

Slide 69 text

インデントによるコードブロック • 「コードブロック」はプログラムの制御処理の対象範囲のこと • 何⾏⽬から何⾏⽬までをコードブロックとするかはインデント による字下げで表現する • Pythonでは半⾓4つが標準的なインデントでタブは⾮推奨(1つ のプログラム中で空⽩とタブの字下げを混在させるとエラー) • プログラミング⽤エディタはタブを半⾓に⾃動変換するものも ある a = -5 if a < 0: print(1) print(2) a = a * -1 print(3) print(a) $ python3 abs_02.py 1 2 3 5 /chapter2/abs_02.py コンソール出⼒ インデント (字下げ)は 半⾓4つが標準

Slide 70

Slide 70 text

Bool型 • 条件を満たす/満たさないを表現する型。条件分岐などに使う • 「True」と「False」の2値しかない • 「条件を満たす」は「条件式がTrueを返す」こと • 「条件を満たさない」は「条件式がFalseを返す」こと >>> 5 > 3 True >>> 5 < 3 False a = -5 if a < 0: a = a * -1 print(a) /chapter2/abs_01.py インタプリタでの確認

Slide 71

Slide 71 text

⽐較演算⼦ (1/2) • True/Falseを得るための演算⼦ • 制御構⽂の条件式などでよく利⽤される • 数字以外でも⽂字列などでも使える 演算⼦ 意味 使⽤例(Trueの場合) == 左辺と右辺が等しいときにTrueを返す 20 == 20 != 左辺と右辺が等しくないときにTrueを返す 20 != 30 > 左辺が右辺より⼤きいときにTrueを返す 30 > 20 >= 左辺が右辺以上のときにTrueを返す 30 >= 20, 30 >= 30 < 左辺が右辺より⼩さいときにTrueを返す 20 < 30 <= 左辺が右辺以下のときにTrueを返す 20 <= 30, 20 <= 20

Slide 72

Slide 72 text

⽐較演算⼦ (2/2) • 異なる型での⽐較などもできる • ⽂字列の⽐較などはCやJavaと挙動が異なるので注意(Pythonは ポインタではなく値で⽐較するので分かりやすい) >>> 4 == 4.0 True >>> 4 == '4' False >>> 'abc' > 'def' False >>> 'hello' == 'hello' True >>> 'hello' == ('hel' + 'lo') True コンソール出⼒ ⽂字列の⽐較はユニコードの 順番で決まっている。 aはdより前にあるので⼩さい

Slide 73

Slide 73 text

Bool値を扱う演算⼦ • 条件式ではBool値の反転や「かつ」「または」などもよく使う • 「and」演算⼦: 左辺と右辺の値がともにTrueの時にTrueを返す • 「or」演算⼦: 左辺と右辺の値のどちらかがTrueの時にTrueを返す • 「not」演算⼦: True/Falseを逆転させる >>> True and True True >>> True and False False >>> True or True True >>> True or False True >>> not True False >>> not False True and演算⼦の確認 or演算⼦の確認 not演算⼦の確認

Slide 74

Slide 74 text

複雑なif⽂ • 「elif」は 前⽅のifかelifに合致しなかったときに条件チェック される分岐。好きなだけ繰り返せる • 「else」は前⽅のifとelifの全てに合致しなかったときに呼び出 される処理を書く a = 15 if a % 2 == 0: print('2') elif a % 3 == 0: print('3') elif a % 5 == 0: print('5') else: print('nothing') $ python3 if_elif_else.py 3 /chapter2/if_elif_else.py コンソール出⼒

Slide 75

Slide 75 text

• 有名なFizzBuzz問題のプログラムを作成する • 変数 a に整数を任意の数を与える • 変数 a が3で割り切れれば「Fizz」と出⼒ • 変数 a が5で割り切れれば「Buzz」と出⼒ • 変数 a が3でも5でも割り切れれば「FizzBuzz」と出⼒ • ヒント: 「1章で学んだ剰余で余りが0になること」が「割り 切れる」ということ • 変数aを様々な値に変更して挙動を確認してください 演習

Slide 76

Slide 76 text

ループ処理で繰り返しを記述する • このセクションで学ぶこと • リストのデータを準備する • リストのデータを取り出す • リストのデータを上書きする • リスト⻑を取得する • リストのデータをまとめて処理するforループ • Breakによるループ打ち切り • Continueによるループの周回スキップ • Continueの便利な利⽤法 • 条件が満たされる間はループを繰り返すwhile⽂ SECTION 03

Slide 77

Slide 77 text

リストのデータを準備する • Pythonのループでは「リスト型」の値をよくつかう • リスト型は⼀覧(リスト)となっているデータを扱うための型 • 「要素」はリストの中⾝のデータ(数値や⽂字列など)のこと • リストの要素には順序がある >>> ['taro', 'jiro', 'saburo'] ['taro', 'jiro', 'saburo'] >>> [] [] >>> a = ['taro', 'jiro', 'saburo'] >>> print(a) ['taro', 'jiro', 'saburo'] >>> リストの宣⾔は⼤かっこ([])に要素を並べる 要素がひとつもない場合は[]のみ リスト内の要素の順序は保たれる

Slide 78

Slide 78 text

リストのデータを取り出す • リスト内のデータは前⽅から0,1,2と数える。1からではなく0か ら数え始めるので注意 • 要素の順番のことを「インデックス番号」と呼ぶ • 「リスト[インデックス番号]」とすると、指定したインデック ス番号の要素が取り出される。取り出されてもなくならない >>> a = ['taro', 'jiro', 'saburo', 10] >>> a[0] 'taro' >>> a[2] 'saburo' リスト要素の取得

Slide 79

Slide 79 text

リストのデータを上書きする • 「リスト[インデックス番号] = 代⼊する値」という形式でイン デックス番号を指定して要素に代⼊することもできる • リストの⻑さを超えたインデックスの参照は取得でも代⼊でも エラーとなる >>> a = ['taro', 'jiro', 'saburo', 10] >>> a[1] = 'hanako' >>> a[3] = 'adam' >>> print(a) ['taro', 'hanako', 'saburo', 'adam'] 存在しないインデックスの参照はエラーとなる >>> a = ['taro', 'jiro', 'saburo', 10] >>> a[4] Traceback (most recent call last): File "", line 1, in IndexError: list index out of range >>> a[4] = 100 Traceback (most recent call last): File "", line 1, in IndexError: list assignment index out of range リストの要素をインデックスで指定して代⼊すると その要素が代⼊値で上書きされる

Slide 80

Slide 80 text

リスト⻑を取得する • リスト⻑: リストの要素の数のこと • 「len関数」でリスト⻑を取得できる • 「len関数の取得値-1までインデックスでアクセスができる」と 覚えておく >>> a = ['taro', 'jiro', 'saburo', 10] >>> len(a) 4 >>> a[3] 10 >>> a[4] Traceback (most recent call last): File "", line 1, in IndexError: list index out of range len関数の確認と要素へのアクセス len関数の取得値でアクセス 可能なインデックス値の最⼤値が わかる

Slide 81

Slide 81 text

リストのデータをまとめて処理するforループ • リストに代表される「シーケンス(連なりのあるデータ)」構造 • 「for」ループでシーケンスを前から後ろに順番に処理できる name_list = ['taro', 'jiro', 'saburo', 'shiro', 'goro'] for name in name_list: print(name) $ python3 forloop.py taro jiro saburo shiro goro for 変数 in シーケンス: 処理 /chapter2/forloop.py コンソール出⼒ for⽂の⽂法 ループするごとにシーケンスの要素を前から後ろに変数に代⼊する シーケンスの最後までたどり着くとループが終了 ブロックの使い⽅はifと同じ

Slide 82

Slide 82 text

breakによるループ打ち切り • 「break」命令でループ処理を打ち切る • ループを継続する理由がなくなった場合に利⽤される • 例: 整数のリスト中に偶数があるかをチェック。(偶数を⾒つけ たら残りのリストの要素はチェック不要なのでbreak) a = [5, 9, 11, 3, 6, 5, 11, 4, 9] has_even = False for i in a: print('checking: ' + str(i)) if i % 2 == 0: has_even = True break print('has even: ' + str(has_even)) $ python3 forloop_break.py checking: 5 checking: 9 checking: 11 checking: 3 checking: 6 has even: True /chapter2/forloop_break.py コンソール出⼒ リストの6より後ろはbreakされたので 出⼒されていない

Slide 83

Slide 83 text

continueによるループの周回スキップ • 「continue」命令で ループのそのその回だけを抜ける • ループ⾃体は継続するのでシーケンスの次の要素は処理する • 要素が「特定条件を満たす場合のみだけ処理する」際に continueを使うとよい a = [5, 9, 11, 3, 6, 5, 11, 4, 9] for i in a: if i % 2 == 1: continue print('Even: ' + str(i)) $ python3 forloop_continue_01.py Even: 6 Even: 4 /chapter2/forloop_continue_01.py コンソール出⼒

Slide 84

Slide 84 text

continueの便利な利⽤版 • breakの利⽤難易度は低いが、continueは使い慣れない⼈が多い • ループでの条件分岐のインデント階層を減らすのに便利 for i in a: if 条件1: if 条件2: if 条件3: 処理 for i in a: if 条件1: continue if 条件2: continue if 条件3: continue 処理 Continueなし Continueあり

Slide 85

Slide 85 text

条件が満たされる間はループを繰り返すwhile⽂ • 「while」ループで条件式が満たされる限り繰り返す • 他のプログラミング⾔語ではwhileは多⽤されるが、Pythonで はforループを可能な限り使うこと。forが使えない場合にwhile ⽂を検討する a = [5, 9, 11, 3] length = len(a) i = 0 while i < length: print('index ' + str(i) + ' : ' + str(a[i])) i += 1 $ python3 while_loop.py index 0 : 5 index 1 : 9 index 2 : 11 index 3 : 3 /chapter2/while_loop.py コンソール出⼒ while 条件式: 処理 while⽂の⽂法 条件式がTrueとなる限りループを継続する ブロックの使い⽅はifやforと同じ

Slide 86

Slide 86 text

• Forループで以下の⾝⻑の平均値、最⼤値、最⼩値を求めてく ださい。ヒント: 合計値と最⼤値と最⼩値のそれぞれの変数を ループ前に定義して、ループを回るたびにその値を更新する • 180cm • 170cm • 160cm • 165cm • 175cm • 余裕がある⼈は10進数を2進数(⽂字列)に変換するプログラム をwhileループで作成してください。検索するとアルゴリズム がでてくるはずです。2進数は⽂字列の複合代⼊演算⼦(結合)で 作成してください。 演習

Slide 87

Slide 87 text

関数の使い⽅をマスターしよう CHAPTER 3 1. なぜ関数が必要なのか? 2. オリジナルの関数を定義する 3. 関数の引数と返り値を⾃在に操る 4. 名前空間と関数型について知る 5. 組み込み関数を活⽤する

Slide 88

Slide 88 text

なぜ関数が必要なのか? • このセクションで学ぶこと • 関数にしかできない処理を提供する • 複雑な処理を簡単に実現する • コードの重複の排除 SECTION 01

Slide 89

Slide 89 text

役割(1) - 関数にしかできない処理を提供する • OSやハードウェアの機能(画⾯出⼒やネットワークなど)の利⽤ は関数しかできない • 関数の内部ではシステムコールなどにより低いレイヤのプログ ラム(C⾔語)が呼び出されている

Slide 90

Slide 90 text

役割(2) - 複雑な処理を簡単に実現する(1/3) • アルゴリズムを⾃分で書けば複雑な処理も実現できる • ⼀般的な処理はPythonが関数などを提供しているので、それを 使うほうが「簡単」「バグが少ない」「速い」 例: リストの要素のソートの実装 選択ソートというアルゴリズム 1. リストの最⼩値を探す 2. 0番⽬の要素とスワップ 3. 1番⽬以降で最⼩値を探す 4. 1番⽬の要素とスワップ 5. … 6. 要素の最後までたどり着けばソート終了 変数間の値の交換は ⼀時的な変数が必要

Slide 91

Slide 91 text

役割(2) - 複雑な処理を簡単に実現する(2/3) • 現時点の知識でのソートアル ゴリズムの実装(難しい) • 変数の値の交換処理には⼀時 変数が必要 a = [5,9,4,1,8] length = len(a) i = 0 while(i < length): # i番⽬以降の最⼩の要素を探す minimum_index = i j = i + 1 while j < length: if a[j] < a[minimum_index]: minimum_index = j j += 1 # i番⽬と最⼩の要素をスワップする if minimum_index != i: tmp = a[i] a[i] = a[minimum_index] a[minimum_index] = tmp # i番⽬のループが終わった際のリスト print(str(i) + ': ' + str(a)) i += 1 print('sorted: ' + str(a)) $ python3 sort_list_01.py 0: [1, 9, 4, 5, 8] 1: [1, 4, 9, 5, 8] 2: [1, 4, 5, 9, 8] 3: [1, 4, 5, 8, 9] 4: [1, 4, 5, 8, 9] sorted: [1, 4, 5, 8, 9] コンソール出⼒ /chapter3/sort_list_01.py

Slide 92

Slide 92 text

役割(2) - 複雑な処理を簡単に実現する(3/3) • sorted関数で昇順ソート(⼩さいものから⼤きいものへ)が提供さ れている • ⾃作のソート処理より以下の点で優れる • プログラムの⾒た⽬がシンプル • ⾼速(選択ソートより賢いアルゴリズムがC⾔語で実装される) • バグが発⽣する可能性が低い a = [5,9,4,1,8] b = sorted(a) print(b) $ python3 sort_list_02.py [1, 4, 5, 8, 9] コンソール出⼒ /chapter3/sort_list_02.py ⾃作の20⾏以上のプログラムがたった1つの 関数呼び出しに置き換えられた

Slide 93

Slide 93 text

役割(3) - コードの重複の排除 • 同⼀の処理をコピーペーストで何度も書くのはよくない • ソースコードが無駄に⻑くなって読みにくくなる • バグやコードの修正が発⽣すると⾯倒だしトラブルのもと • 関数化されていれば「⾒やすい」し「変更(修正)しやすい」 a = 5 if a < 0: a *= -1 # 何か関係ない処理 b = -3 if b < 0: b *= -1 print(a) # 5 print(b) # 3 a = 5 a = abs(a) # 何か関係ない処理 b = -3 b = abs(b) print(a) # 5 print(b) # 3 /chapter3/get_abs_01.py /chapter3/get_abs_02.py

Slide 94

Slide 94 text

• 関数が必要な理由を3つ説明してください • 発展課題: ソートアルゴリズムについて調査し、バブルソート を実装してください 演習

Slide 95

Slide 95 text

オリジナルの関数を定義する • このセクションで学ぶこと • 関数の概念の復習 • 関数を定義する • ⾃分で定義した関数を利⽤する • 関数の命名ルール • 定義と参照の順序 SECTION 02

Slide 96

Slide 96 text

関数の概念の復習 • 関数の仕事 1. 「引数」でデータを受け取る 2. 受け取ったデータで処理を⾏う 3. 結果を「返り値」として呼び出し元に返す • 絶対値を求めるabs関数の例 1. 引数で数値を受け取る 2. 受け取った数値を絶対値にする(マイナスであればプラス に変換する) 3. 絶対値を呼び出し元に返す 処理 (絶対値の算出) 引数による⼊⼒(数値) 返り値による出⼒(絶対値) 関数

Slide 97

Slide 97 text

関数を定義する • 関数を定義する⽂法ルールがある • 引数は関数内で変数として利⽤される。再代⼊も可能 def my_abs(x): if x < 0: x *= -1 return x def 関数名(引数1, 引数2, ...): 処理1 処理2 return 返り値 絶対値を求める関数の定義例 • 関数名: my_abs • 引数: x • 処理: if⽂でxを絶対値にする • 返り値: 処理されたx /chapter3/define_function_02.py 関数を実装する⽂法 「return⽂」で呼び出し元に値を返す 「def⽂」で関数呼び出しの定義 • 関数名 • 引数 処理は関数のブロックで定義する

Slide 98

Slide 98 text

⾃分で定義した関数を利⽤する • ⾃作関数の利⽤法はPythonが提供する関数(printなど)と同じ • 関数名に()をつけ、引数として渡す値や変数を()内に並べる • 関数の定義より前で関数を呼び出すとエラーになる def my_abs(x): if x < 0: x *= -1 return x a = my_abs(3) print(a) print(my_abs(-5)) print(my_abs(-5)) def my_abs(x): if x < 0: x *= -1 return x $ python3 define_function_04.py Traceback (most recent call last): File "define_function_04.py", line 1, in print(my_abs(-5)) NameError: name 'my_abs' is not defined $ python3 define_function_03.py 3 5 コンソール出⼒ コンソール出⼒ /chapter3/define_function_03.py /chapter3/define_function_04.py 呼び出し側で渡した引数3が 関数側の引数xに代⼊される。 引数の数は同じにすること returnの 返り値が 戻される

Slide 99

Slide 99 text

関数の命名ルール • 関数名の⽂法的なルールは変数名と同じ • アルファベットの⼩⽂字と数字をアンダーバーで区切る • ⼤⽂字の利⽤も可能だがPythonらしくない名前 • 「関数名は動詞から始める」というのが⼀般的なルール def add_something(x): ... def get_something(x): ... def something_adder(x): ... def something_getter(x): ... def addSomething(x): ... def getSomething(x): ... よい変数名の例 Pythonらしくない変数名の例

Slide 100

Slide 100 text

コラム: 変数の定義と参照の順序 • 関数と同様に変数も「定義前に参照するとエラー」となる • プログラムがどのような流れで読み込まれて処理されるかを意 識すればトラブルを避けやすい print(a) a = 5 $ python3 define_variable.py Traceback (most recent call last): File "define_variable.py", line 1, in print(a) NameError: name 'a' is not defined コンソール出⼒ /chapter3/define_variable.py

Slide 101

Slide 101 text

• FizzBuzz問題を関数化してください • FizzBuzz⾃体の説明は2章の演習を参照してください • 引数は1つで整数を受け取ります • 返り値は「 " Fizz " 」「 " Buzz " 」「 " FizzBuzz " 」「 " " 」のいずれかの⽂字列とします • forループで「0から20までリストの各要素」にたいして FizzBuzzの関数を使い、結果を1つずつprintしてください • 数値を受け取り、その数値が偶数であればTrue, 奇数であれば Falseを返す is_even 関数を作成してください。ヒント: 偶数と 奇数の判定は2で割り切れるかを剰余計算(%記号)で求める 演習

Slide 102

Slide 102 text

関数の引数と返り値を⾃在に操る • このセクションで学ぶこと • 返り値の有無によるコードの違い • 複数のreturn⽂を記述する • 関数に複数の引数を定義する • キーワード引数を定義する • デフォルト引数 • 可変⻑引数を利⽤する • コラム: help関数で関数の詳細を確認する SECTION 03

Slide 103

Slide 103 text

返り値の有無によるコードの違い • returnが定義されていないと「None(何もないという値)」を返す • returnに変数や値が与えられていないときもNoneを返す • 「Noneを返す」ということは「関数の返り値がない」と同じ意味 def my_print1(x): print('my print1: ' + str(x)) def my_print2(x): print('my print2: ' + str(x)) return a = my_print1(5) print(a) b = my_print2(5) print(b) $ python3 return_value_01.py my print1: 5 None my print2: 5 None コンソール出⼒ /chapter3/return_value_01.py

Slide 104

Slide 104 text

複数のreturn⽂を記述する • 関数にreturnを複数定義することができる • returnが呼び出されたら関数の処理はそこで終わる。後ろに処 理が残っていようとループ中であろうと残る処理はスキップさ れる def my_abs(x): if x > 0: return x print('less than 0') return x * -1 print(my_abs(5)) print(my_abs(-5)) $ python3 return_value_02.py 5 less than 0 5 コンソール出⼒ /chapter3/return_value_02.py

Slide 105

Slide 105 text

関数に複数の引数を定義する • 関数の引数は好きな数だけ使うことができる • 引数を受け取らない関数は引数を定義しない • 「定義した引数の数」と「呼び出し時の引数の数」が異なると エラーが発⽣ def fun0(): print('fun0') def fun1(arg1): print('fun1') def fun5(arg1, arg2, arg3, arg4, arg5): print('fun5: arg1 is ' + arg1) fun0() fun1(1) fun5('a', 'b', 'c', 'd', 'e') $ python3 return_value_03.py fun0 fun1 fun5: arg1 is a コンソール出⼒ /chapter3/return_value_03.py

Slide 106

Slide 106 text

キーワード引数を定義する • 今まで利⽤してきた引数は正式には「位置引数」と呼ばれる。定 義された引数の「順序」通りに引数を与える使い⽅ • 「キーワード引数」は 定義された引数名を指定して引数を与える • 引数の数が多い場合はキーワード引数だと順番間違いがない def test(arg1, arg2, arg3): print(str(arg1) + str(arg2) + str(arg3)) # 位置引数 test(1, 2, 3) # キーワード引数 test(arg2='a', arg1='b', arg3='c') $ python3 keyword_argument_01.py 123 bac コンソール出⼒ /chapter3/keyword_argument_01.py 関数定義の引数名を指定して 値を渡している

Slide 107

Slide 107 text

デフォルト引数 • 「デフォルト引数」で引数にデフォルト値を定義できる • キーワード引数とともに利⽤されることが多く、関数呼び出し 時に対象となる引数を与えないとデフォルト値が使われる • デフォルト引数の後ろにデフォルト引数を持たない引数は定義 できない。⽂法エラーが発⽣する def test(arg1, arg2=2, arg3=3): print(str(arg1) + str(arg2) + str(arg3)) test(1, 'B', 'C') test(1) test(1, arg3='C') $ python3 keyword_argument_02.py 1BC 123 12C コンソール出⼒ /chapter3/keyword_argument_02.py

Slide 108

Slide 108 text

可変⻑引数を利⽤する • 与える引数が固定でない関数の引数を「可変⻑引数」と呼ぶ • 可変⻑引数を⾃分で定義するのは初⼼者向けではないが、既存 関数で使う場⾯は多いので使いかたは知っておくこと • 「スプラット演算⼦(*)」を使うとリストを可変⻑引数に使える print('hello') print('hello', 'python') print(1, 2, 3, 4, 5, 6, 7, 8, 9) $ python3 variable_arguments_01.py hello hello python 1 2 3 4 5 6 7 8 9 print([1, 2, 3, 4, 5, 6, 7, 8, 9]) print(*[1, 2, 3, 4, 5, 6, 7, 8, 9]) $ python3 variable_arguments_02.py [1, 2, 3, 4, 5, 6, 7, 8, 9] 1 2 3 4 5 6 7 8 9 コンソール出⼒ コンソール出⼒ /chapter3/variable_arguments_01.py /chapter3/variable_arguments_02.py

Slide 109

Slide 109 text

コラム: help関数で関数の詳細を確認する • 「help関数」の引数に関数名をあたえることで、その関数の詳 細を確認することができる • 引数などを忘れた場合にインタプリタですぐに確認できる >>> help(print) Help on built-in function print in module builtins: print(...) print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False) Prints the values to a stream, or to sys.stdout by default. Optional keyword arguments: file: a file-like object (stream); defaults to the current sys.stdout. sep: string inserted between values, default a space. end: string appended after the last value, default a newline. flush: whether to forcibly flush the stream. help関数を使ったprint関数の詳細確認

Slide 110

Slide 110 text

• None型の値と型名をtype関数で調べてください • 先に作成したmyabs関数を「ifブロック内でマイナスをプラス に戻した値をreturnで返す」ように変更してください • 2つの引数を受け取り、⼤きい側の引数を返すmymax関数を作 成してください • mymax関数をキーワード引数で呼び出してください • help関数で今まで学んだPython標準の関数のなにかを調べてく ださい 演習

Slide 111

Slide 111 text

名前空間と関数型について知る • このセクションで学ぶこと • 関数の中にある変数の扱い • global宣⾔ • 名前空間 • 関数型 • 関数を受け取る関数 SECTION 04

Slide 112

Slide 112 text

関数の中にある変数の扱い (1/2) • 関数の外では関数内で定義された変数を使えない(アクセスでき ない) • アクセスできない変数を参照しようとするとエラーが発⽣ def test(x): y = x + 1 return y print(test(5)) print(y) $ python3 name_space_02.py 6 Traceback (most recent call last): File "name_space_02.py", line 6, in print(y) NameError: name 'y' is not defined コンソール出⼒ /chapter3/name_space_02.py

Slide 113

Slide 113 text

関数の中にある変数の扱い (2/2) • 関数の外で定義された変数は、関数内でも参照できる • 関数内で関数外の変数を上書きしても、関数外の変数の値は変 わらない(厳密には関数内部に同じ名前の変数が定義され、それ に代⼊されているという動きをしている) a = 1 def test(): print(a) test() $ python3 name_space_03.py 1 a = 1 def test(): a = 10 test() print(a) $ python3 test1.py 1 コンソール出⼒ コンソール出⼒ /chapter3/name_space_03.py test1.py

Slide 114

Slide 114 text

global宣⾔ • 「グローバル宣⾔(global)」を変数にすることで、関数外の変 数を関数内で上書きできるようになる • グローバル宣⾔の利⽤は⾮推奨。関数外の変数を上書きしたい のであれば、関数の返り値を変数に再代⼊するのが⼀般的 a = 1 def test(): global a a = 10 test() print(a) $ python3 name_space_04.py 10 コンソール出⼒ /chapter3/name_space_04.py

Slide 115

Slide 115 text

名前空間 (1/2) • 変数を参照できるスコープ(エリア)を「名前空間」と呼ぶ • 基本的には「中から外の変数は参照できる」「中で外の変数に 代⼊しない」「外から中の変数は参照できない」と覚えておく 名前空間のまとめ図 細かいですが理解してください

Slide 116

Slide 116 text

名前空間 (2/2) • 名前空間を使う鉄則(中級者向けトピック) • どこからでも参照できる変数は「どこでどういった操作が⾏ われるか」管理しにくく、バグになりやすい • あえて変数が利⽤できる範囲を狭めることで、その変数の使 いみちを分かりやすくし、変な状態にならないようにする • 「グローバル変数(どのブロックにも属さない⼀番上のレベ ルの変数)」は可能な限り利⽤しないようにして、関数内の 変数やクラスで定義された変数(5章)を使うこと

Slide 117

Slide 117 text

関数型 • Pythonの関数も「関数型(概念)」の値(具体的なデータ) • print関数は関数型の値の1つであり、len関数も同様 • type関数に関数を与えることで関数型である確認ができる • 関数型の値は変数に代⼊でき、変数経由で関数を呼び出せる。 上級者向けのプログラミングテクニックでよく使う >>> type(abs) >>> def my_abs(x): ... if x < 0: ... x *= -1 ... return x ... >>> type(my_abs) >>> fun = abs >>> fun(-5) 5 コンソール出⼒ 組み込み関数と⾃作関数の型の確認。厳密には違うが区別しなくてよい

Slide 118

Slide 118 text

関数を受け取る関数 • 関数Aの引数として関数Bを渡す場合がある。関数Aの挙動を関 数Bで調整する。関数を受け取る関数を「⾼階関数」と呼ぶ。 • たとえばソートの基準を関数として定義し、その基準通りに ソートを実施するなど a = [5, -7, 0, 9, -3] print(sorted(a)) a = [5, -7, 0, 9, -3] def my_abs(x): if x < 0: x *= -1 return x print(sorted(a, key=my_abs)) $ python3 sort_argument_01.py [-7, -3, 0, 5, 9] $ python3 sort_argument_02.py [0, -3, 5, -7, 9] コンソール出⼒ コンソール出⼒ /chapter3/sort_argument_01.py /chapter3/sort_argument_02.py keyはキーワード引数(デフォルト付き)の指定

Slide 119

Slide 119 text

コラム: 制御構⽂の名前空間 • Pythonではifやforなどの制御⽂のブロックで宣⾔した変数は、 そのブロック外でも参照できる • 他のプログラミング⾔語では参照できないものが多いので注意 def fun(x): if x == 1: y = 5 else: y = 10 print(y) fun(1) $ python3 test.py 5 test.py コンソール出⼒ 変数yは条件分岐の構⽂内で宣⾔されているので、 print⽂があるブロック(関数)より内側にある。 問題なくアクセスできている

Slide 120

Slide 120 text

• Pythonの名前空間の動きを説明してください • 関数内から関数外の変数のアクセス • 関数外から関数内の変数のアクセス • global宣⾔の効果 • なぜglobal宣⾔が推奨されないか • 関数で関数外の変数を更新したいときはどのような関数とす るのが望ましいか • sorted関数に⾃作関数を渡して降順ソート(⼤きいものから ⼩さいものへ)を実現してください 演習

Slide 121

Slide 121 text

組み込み関数を活⽤する • このセクションで学ぶこと • for⽂で便利なrange関数 • リストを扱うのに便利な関数 • filter関数でリストの要素を絞り込む • map関数でリストをまとめて処理する SECTION 05

Slide 122

Slide 122 text

for⽂で便利なrange関数 • 「range関数」で数字の連番(0,1,2...など)を作れる • 利⽤法1: 引数を1つ与えて0からその値-1までの連番を作る • 利⽤法2: 引数を1つ与えて「1つめの引数の値」から「2つめの 引数の値 - 1」までの連番を作る • 「N回ループする」ときにfor⽂と利⽤法1の組み合わせが便利 a = range(5) print(a) print(list(a)) for i in range(2,5): print(i) $ python3 range_01.py range(0, 5) [0, 1, 2, 3, 4] $ python3 range_02.py 2 3 4 コンソール出⼒ コンソール出⼒ /chapter3/range_02.py /chapter3/range_01.py

Slide 123

Slide 123 text

リストを扱うのに便利な関数 • len関数: リスト⻑さの取得 • max関数: 引数の最⼤値を取得。引数はリストか可変⻑引数 • min関数: 引数の最⼩値を取得。引数はリストか可変⻑引数 list1 = [4, 2, 5, 8, 9, 1] print(len(list1)) print(max(list1)) print(min(list1)) コンソール出⼒ /chapter3/len_max_min.py $ python3 len_max_min.py 6 9 1

Slide 124

Slide 124 text

filter関数でリストの要素を絞り込む • リストから特定条件を満たす要素を取り出す処理は多⽤する • 「filter関数」にリストと条件判定の関数を与えて実現可能 • 返り値はループで直接使えるが、リスト型ではないので注意が 必要。リストが必要な場合は「list関数」でキャストする $ python3 filter.py [4, 2, 8] def is_even(x): return x % 2 == 0 list1 = [4, 2, 5, 8, 9, 1] filter_object = filter(is_even, list1) list2 = list(filter_object) print(list2) コンソール出⼒ /chapter3/filter.py リスト型へのキャスト

Slide 125

Slide 125 text

map関数でリストをまとめて処理する • リストの要素全てに特定の処理を施す場⾯は多い • 「map関数」にリストと関数を与えると、リストの全要素に関 数の処理を実施した結果を返す def add5(x): return x + 5 list1 = [4, 2, 5, 8, 9, 1] map_object = map(add5, list1) for i in map_object: print(i) $ python3 map.py 9 7 10 13 14 6 コンソール出⼒ /chapter3/map.py

Slide 126

Slide 126 text

• range関数とforループを使って指定された数だけ「hello」と出 ⼒する関数を作成してください • 正と負の整数を持つリストをfilter関数と⾃作関数を使って正の 整数のみを抽出したリストにしてください。たとえば[5, -3, 8, -1, 4]を与えると[5, 8, 4]が得られます • map関数を使って数値を含むリストを⽂字列を含むリストに変 換してください。たとえば[5, -3, 8, -1, 4]を与えると['5', '-3', '8', '-1', '4']が得られます 演習

Slide 127

Slide 127 text

オブジェクト指向を理解しよう CHAPTER 4 1. オブジェクトとメソッドの関係を理解する 2. リストオブジェクトを操作する 3. 不変オブジェクトを操作する 4. その他のデータ型を理解する

Slide 128

Slide 128 text

オブジェクトとメソッドの関係を理解する • このセクションで学ぶこと • オブジェクトとは • メソッドでListインスタンスを操作する • メソッドの副作⽤と返り値 • コラム: dir関数を使ったオブジェクトのメソッド確認 SECTION 01

Slide 129

Slide 129 text

オブジェクトとは • ⽂字列型や整数型には概念と実データが存在する • 型の概念のことを「クラス」と呼ぶ • 型の実データ(値)を「インスタンス」や「オブジェクト」と呼ぶ

Slide 130

Slide 130 text

メソッドでListインスタンスを操作する (1/2) • 「メソッド」はインスタンスを操作するための特別な関数 • インスタンス(値そのものか変数)の後ろに「.(ドット)」を置き、 続けてメソッド名とメソッドの引数を記述する • appendメソッド: 対象のインスタンスに要素を追加 • reverseメソッド: 対象のインスタンスの要素の順序を反転 a = ['ab', 'cd', 'ef'] print(a) # リストに値を追加 a.append('gh') print(a) $ python3 object_02.py ['ab', 'cd', 'ef'] ['ab', 'cd', 'ef', 'gh'] a = ['ab', 'cd', 'ef', 'gh'] a.reverse() # リストの要素を反転 print(a) $ python3 object_03.py ['gh', 'ef', 'cd', 'ab'] コンソール出⼒ コンソール出⼒ /chapter4/object_02.py /chapter4/object_03.py

Slide 131

Slide 131 text

メソッドでListインスタンスを操作する (2/2) • メソッドの操作対象はインスタンス内のデータ • インスタンス内ではデータと処理が密接に結びついている • 利⽤できるメソッドはインスタンスの型に依存する。たとえばList 型インスタンスと⽂字列型インスタンスが使えるメソッドは違う

Slide 132

Slide 132 text

メソッドの副作⽤と返り値 • 「副作⽤」は操作によりオブジェクトの状態が変化すること • メソッドには以下のパターンが存在する • 副作⽤はあるが、返り値はない(Listのappendメソッド) • 副作⽤はなく、返り値がある(Listのcountメソッド) • 副作⽤も返り値もある(Listのpopメソッド) • 副作⽤も返り値もない(呼び出す意味がないので普通はない) a = [1,3,5,3,1,3] b = a.count(3) print(b) print(a) $ python3 object_05.py 3 [1, 3, 5, 3, 1, 3] a = [1,3,5,3,1,3] b = a.pop(0) print(b) print(a) $ python3 object_06.py 1 [3, 5, 3, 1, 3] コンソール出⼒ コンソール出⼒ /chapter4/object_05.py /chapter4/object_06.py 副作⽤なし 返り値あり 副作⽤あり 返り値あり

Slide 133

Slide 133 text

コラム: dir関数を使ったオブジェクトのメソッド確認 • どの型がどういったインスタンスを使えるか記憶しきれない • dir関数を使うことでオブジェクトの属性(5章)を確認できる • メソッドも属性の⼀部なので確認可能 >>> dir([]) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] コンソールで属性(メソッド)の⼀覧を確認

Slide 134

Slide 134 text

• リストの「[1,2,3,4]」はクラスですか、インスタンスですか • 「クラス」と「インスタンス」の関係について説明してくださ い • インスタンスのメソッドがなにかについて説明してください • 以下のリストのメソッドの副作⽤と返り値を説明してください • append • reverse • count • pop 演習

Slide 135

Slide 135 text

リストオブジェクトを操作する • このセクションで学ぶこと • リストオブジェクトを操作するメソッド • その他のリスト操作 SECTION 02

Slide 136

Slide 136 text

リストオブジェクトを操作するメソッド (1/4) • append: リスト末尾に要素を追加する • insert: 指定した位置に要素を挿⼊する a = ['a', 'b', 'c', 'd', 'e'] a.append('hello') print(a) a = ['a', 'b', 'c', 'd', 'e'] a.insert(3, 'hello') print(a) $ python3 list_method_01.py ['a', 'b', 'c', 'd', 'e', 'hello'] $ python3 list_method_02.py ['a', 'b', 'c', 'hello', 'd', 'e'] コンソール出⼒ コンソール出⼒ /chapter4/list_method_01.py /chapter4/list_method_01.py

Slide 137

Slide 137 text

リストオブジェクトを操作するメソッド (2/4) • remove: 指定した要素を削除する。インデックス指定ではなく 消したい値を指定するので注意 • reverse: リストの順序を反転させる a = ['a', 'b', 'c', 'd', 'e'] a.remove('c') print(a) $ python3 list_method_03.py ['a', 'b', 'd', 'e'] a = ['a', 'b', 'c', 'd', 'e'] a.reverse() print(a) $ python3 list_method_04.py ['e', 'd', 'c', 'b', 'a'] コンソール出⼒ コンソール出⼒ /chapter4/list_method_03.py /chapter4/list_method_04.py

Slide 138

Slide 138 text

リストオブジェクトを操作するメソッド (3/4) • clear: リストの要素を全削除して空にする • count: リストに指定した要素がいくつあるか数える a = ['a', 'b', 'c', 'd', 'e'] a.clear() print(a) a = ['a', 'b', 'c', 'b', 'a'] count = a.count('b') print(count) $ python3 list_method_06.py 2 $ python3 list_method_05.py [] コンソール出⼒ コンソール出⼒ /chapter4/list_method_05.py /chapter4/list_method_06.py

Slide 139

Slide 139 text

リストオブジェクトを操作するメソッド (4/4) • index: 指定した値を持つ要素のインデックス番号を取得 • pop: リストからインデックスを指定して要素を取り出して削除 a = ['a', 'b', 'c', 'd', 'e'] index = a.index('d') print(index) a = ['a', 'b', 'c', 'd', 'e'] value = a.pop(0) print(value) print(a) $ python3 list_method_07.py 3 $ python3 list_method_08.py a ['b', 'c', 'd', 'e'] コンソール出⼒ コンソール出⼒ /chapter4/list_method_07.py /chapter4/list_method_08.py

Slide 140

Slide 140 text

その他のリスト操作 (1/2) • 「in演算⼦」で指定した値がリストに含まれていればTrueを返す • 「del⽂」で指定したインデックス番号の要素を削除 a = 'c' in ['a', 'b', 'c', 'd'] print(a) print('c' in ['a', 'b', 'd']) a = ['a', 'b', 'c', 'd', 'e'] del a[3] print(a) $ python3 list_operator01.py True False $ python3 list_operator02.py ['a', 'b', 'c', 'e'] コンソール出⼒ コンソール出⼒ /chapter4/list_operator_01.py /chapter4/list_operator_02.py

Slide 141

Slide 141 text

その他のリスト操作 (2/2) • 「スライス」でリストの要素の⼀部分を取り出せる。元のリストに は変化なし • a[x:y] : リストaのインデックス番号xからy-1の要素のリストを取得 • a[:y] : インデックス番号0からy-1までの要素のリストを取得 • a[x:] : インデックス番号のxから最後までの要素のリストを取得 • a[:] : リストaをコピーしたリストを取得 a = ['a', 'b', 'c', 'd', 'e'] b = a[1:3] print(b) c = a[:3] print(c) $ python3 list_operator03.py ['b', 'c'] ['a', 'b', 'c'] コンソール出⼒ /chapter4/list_operator_03.py

Slide 142

Slide 142 text

• 「[1,2,3,4,5]」を持つリストをinsertで「[1,2,3,100,4,5]」にし てください • 整数を含むリストから偶数だけを抽出したリストを作成してく ださい。ただしfilter関数などは使わず「forループ内で事前に作 成した偶数リストに偶数を追加」という⽅式です。 • 「[1,2,3,4,5]」というリストをwhileとpopを使って 5, 4, 3, 2, 1 と逆順序に要素がなくなるまで取り出してください。reverseメ ソッドの利⽤は禁⽌です。ヒント: FIFOとスタックというデー タ構造を調べてください 演習

Slide 143

Slide 143 text

不変オブジェクトを操作する • このセクションで学ぶこと • ⽂字列型のメソッドはオブジェクトを変化させない • ⽂字列型のメソッド • in演算⼦を使った⽂字列型の処理 • ⽂字列の⼀部を取り出す • コラム: メソッドチェーン SECTION 03

Slide 144

Slide 144 text

⽂字列型のメソッドはオブジェクトを変化させない (1/2) • upper: ⽂字列を⼤⽂字にした「新しい⽂字列を返す」 • replace: ⽂字列を置き換えた「新しい⽂字列を返す」 • 上記2つのメソッドを呼び出してもインスタンスは変化しない a = 'Hello Python' b = a.upper() print('Original a : ' + a) print('Return val b : ' + b) a = 'Hello Python' c = a.replace('Hello', 'Hell') print('Original a : ' + a) print('Return val c : ' + c) $ python3 string_method_01.py Original a : Hello Python Return val b : HELLO PYTHON $ python3 string_method_02.py Original a : Hello Python Return val c : Hell Python コンソール出⼒ コンソール出⼒ /chapter4/string_method_01.py /chapter4/string_method_01.py

Slide 145

Slide 145 text

⽂字列型のメソッドはオブジェクトを変化させない (2/2) • 「不変オブジェクト」は⾃分⾃⾝を変化させないオブジェクト • ほとんどの型は不変オブジェクトではないが、原始的な型(整数 型や⽂字列型)は不変オブジェクトであることが多い

Slide 146

Slide 146 text

⽂字列型のメソッド (1/5) • formatメソッド: ⽂字列に値を埋め込む。+演算⼦で⽂字列化し て連結するよりも綺麗に書ける • ⽂字列中の{}に引数が埋め込まれた⽂字列を返す • 埋め込む値の整形やキーワードでの埋め込みもできる(割愛) name = 'Tom' age = 25 text = 'Hi, this is {}. {} years old.'.format(name, age) print(text) $ python3 string_method_03.py Hi, this is Tom. 25 years old. コンソール出⼒ /chapter4/string_method_03.py

Slide 147

Slide 147 text

⽂字列型のメソッド (2/5) • startswithメソッド: 引数の⽂字列で開始されていればTrue • endswithメソッド: 引数の⽂字列で終了していればTrue print('Hello Python'.startswith('thon')) print('Hello Python'.startswith('Hello')) print('Hello Python'.endswith('thon')) print('Hello Python'.endswith('Hello')) $ python3 string_method_04.py False True $ python3 string_method_05.py True False コンソール出⼒ コンソール出⼒ /chapter4/string_method_04.py /chapter4/string_method_05.py

Slide 148

Slide 148 text

⽂字列型のメソッド (3/5) • replaceメソッド: 第1引数の⽂字列を第2引数の⽂字列で置き 換えた⽂字列を返す • lowerメソッド: ⽂字列を全て⼩⽂字にした⽂字列を返す • upperメソッド: ⽂字列を全て⼤⽂字にした⽂字列を返す print('Hello Python'.replace('Python', 'World')) print('Hello Python'.replace('Pyth0n', 'World')) print('Hello Python'.replace('Python', '')) $ python3 string_method_06.py Hello World Hello Python Hello >>> a = 'Hello World' >>> a.lower() 'hello world' >>> a.upper() 'HELLO WORLD' >>> a.lower() == 'hello world' True lowerもしくはupperで⼤⽂字⼩⽂字を 気にせずに⽂字列の合致判定ができる コンソール出⼒ lowerとupperメソッドの確認 /chapter4/string_method_06.py

Slide 149

Slide 149 text

⽂字列型のメソッド (4/5) • stripメソッド: ⽂字列の前後の空⽩(半⾓空⽩、改⾏、タブな ど)を取り除く • joinメソッド: リストの要素を⽂字列で連結する print(' hello\n') print(' hello\n'.strip()) list3 = ['taro', '180', '80'] text = ','.join(list3) print(text) $ python3 string_method_07.py hello hello $ python3 string_method_10.py taro,180,80 コンソール出⼒ コンソール出⼒ /chapter4/string_method_07.py /chapter4/string_method_08.py

Slide 150

Slide 150 text

⽂字列型のメソッド (5/5) • splitメソッド: ⽂字列を特定の⽂字列で分解して⽂字列のリス トにする • CSV形式をコンマで分けたり、改⾏コードで複数⾏のテキスト を⾏ごとに分解する処理によく使われる text = 'taro, 180, 80' list1 = text.split(',') print(list1) text = 'taro, 180, 80' list1 = text.split(',') def apply_strip(text): return text.strip() list2 = list(map(apply_strip, list1)) print(list2) $ python3 string_method_08.py ['taro', ' 180', ' 80'] $ python3 string_method_09.py ['taro', '180', '80'] コンソール出⼒ コンソール出⼒ /chapter4/string_method_08.py /chapter4/string_method_09.py

Slide 151

Slide 151 text

in 演算⼦を使った⽂字列型の処理 • 特定の⽂字列が別の⽂字列内に含まれるかをin演算⼦で判別で きる。返り値はTrue/False • 複雑な条件で⽂字列判定がしたい場合は8章の正規表現を使う print('Hell' in 'Hello') print('Ho' in 'Hello') $ python3 string_operator_01.py True False コンソール出⼒ /chapter4/string_operator_01.py

Slide 152

Slide 152 text

⽂字列の⼀部を取り出す • ⽂字列はシーケンス型(リストなど)の1つ • []でインデックスを指定して特定位置の1⽂字を抜き出せる • []を使ったスライスで⽂字列の特定箇所を抜き出せる • ⽂字列のスライスの利⽤法は4章2節のリストのスライスと同じ $ python3 string_operator_02.py l lo py text = 'hello python' print(text[3]) print(text[3:8]) コンソール出⼒ /chapter4/string_operator_02.py

Slide 153

Slide 153 text

コラム: メソッドチェーン • 返り値を変数に格納せずに直接メソッドを呼び出せる • 鎖状に連ねることから「メソッドチェーン」と呼ばれる

Slide 154

Slide 154 text

• 不変オブジェクトについて例を使って説明してください • ⽂字列型のformatメソッドでテンプレートを埋めてください。 「'hello {}'」 • ⽂字列型のlowerを使って⽂字列からbool値を得る関数を作成 してください • 引数が⼤⽂字⼩⽂字を問わず「true」であればTrue • それ以外は全てFalse • replaceメソッドで⽂字列「"Hello I'm Yuichi"」の名前を⾃分の 名前に変えてください。 • メソッドチェーンで「'hello world python'」を1⾏で 「['HELLO', 'WORLD', 'PYTHON']」にしてください 演習

Slide 155

Slide 155 text

その他のデータ型を理解する • このセクションで学ぶこと • タプルの概要 • タプルの利⽤⽅法と利⽤例 • タプルからタプルへの代⼊(アンパック代⼊) • タプルやリストを扱う関数 • セットの概要 • セット型の操作 • 辞書型の概要 • 辞書型の操作 • 辞書型のメソッド • コラム: 基本的な型と制御がプログラミングの中⼼ SECTION 04

Slide 156

Slide 156 text

タプルの概要 • 複数の異なるデータをまとめて管理するための型。リストに似 ているが「不変オブジェクト」。データ構造を作る • 出席簿を例としたリストとの使い分け • タプル: 各⽣徒のデータ(名前、⾝⻑、体重) • リスト: ⽣徒1, ⽣徒2, ⽣徒3, ...

Slide 157

Slide 157 text

タプルの利⽤⽅法 • 少カッコ()内に各要素をコンマ区切りで並べる。リストと同じ • 要素へのアクセスはインデックス番号を使う • 要素は上書きできない • 要素数は変更できない taro = ('taro', 180, 80) print(type(taro)) print(taro[1]) $ python3 tuple_02.py 180 >>> taro = ('taro', 180, 80) >>> taro[0] = 'jiro' Traceback (most recent call last): File "", line 1, in TypeError: 'tuple' object does not support item assignment >>> del taro[1] Traceback (most recent call last): File "", line 1, in TypeError: 'tuple' object doesn't support item deletion インタプリタでの挙動確認 /chapter4/tuple_02.py コンソール出⼒

Slide 158

Slide 158 text

タプルの利⽤例 • 表の列(構成が決まっている)をタプルとする • 表の⾏(⻑さが変わる)をリストとする taro = ('taro', 180, 80) jiro = ('jiro', 170, 70) saburo = ('saburo', 160, 60) list1 = [taro, jiro, saburo] sum_height = 0 for person in list1: sum_height += person[1] print(sum_height/len(list1)) $ python3 tuple_03.py 170.0 /chapter4/tuple_03.py コンソール出⼒

Slide 159

Slide 159 text

タプルからタプルへの代⼊ • 「アンパック代⼊」を使うとタプルに含まれる変数群に右側の タプルの要素をまとめて代⼊できる • 左辺のカッコは省略できる。例「a, b, c = (1, 2, 3)」 • for⽂の変数や関数の返り値にタプルを使うことが多い (name, height, weight) = ('taro', 180, 80) print(height) taro = ('taro', 180, 80) jiro = ('jiro', 170, 70) saburo = ('saburo', 160, 60) list1 = [taro, jiro, saburo] sum_height = 0 for (name, height, weight) in list1: sum_height += height print(sum_height/len(list1)) $ python3 tuple_04.py 180 $ python3 tuple_05.py 170.0 /chapter4/tuple_04.py /chapter4/tuple_05.py コンソール出⼒ コンソール出⼒

Slide 160

Slide 160 text

タプルやリストを扱う関数 • 「enumerate関数」でリストの要素をタプル形式にしてイン デックス番号を与える • 「zip関数」で複数のリストを束ねてタプル形式のリストにする list1 = ['a', 'b', 'c', 'd', 'e'] enum_object = enumerate(list1) print(list(enum_object)) list1 = ['a', 'b', 'c'] for (index, item) in enumerate(list1): print('{} : {}'.format(index, item)) $ python3 tuple_06.py [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')] $ python3 tuple_07.py 0 : a 1 : b 2 : c /chapter4/tuple_06.py /chapter4/tuple_07.py コンソール出⼒ コンソール出⼒ enumerateはforループでインデックス値が必要な時に便利

Slide 161

Slide 161 text

セットの概要 • 順序と重複がない複数の要素を保持するデータ構造 • 要素を追加、削除することができるが、Listと異なり同じ要素 を2つ持つことはできず、要素の順序もない • set()で空のセットオブジェクトを作成する >>> set1 = set() >>> set1.add('apple') >>> print(set1) {'apple’} >>> set1.add('banana') >>> print(set1) {'banana', 'apple’} >>> set1.add('apple') >>> print(set1) {'banana', 'apple'} インタプリタでの挙動確認(詳細は次ページより)

Slide 162

Slide 162 text

セット型の操作 (1/2) • セットオブジェクトの作成⽅法 • set() • {'elem1', 'elem2', 'elem3'} • 宣⾔⽅法が後述する辞書型とほぼ同じなので注意。特に「{}」 はセット型ではなく辞書型のオブジェクトが⽣成されるのはよ く間違えるポイント >>> set1 = set() >>> type(set1) >>> set2 = {'elem1', 'elem2', 'elem3'} >>> type(set2) インタプリタでの挙動確認

Slide 163

Slide 163 text

セット型の操作 (2/2) • addメソッド: 要素を追加 • removeメソッド: 要素を削除 • popメソッド: 要素をランダムに取り出し(取り出すとなくなる) • in演算⼦: 要素が存在するかチェック。リストより⾼速 >>> set1 = {'A', 'B', 'C'} >>> 'A' in set1 True >>> 'D' in set1 False >>> set1.remove('B') >>> set1 {'C', 'A’} >>> a = set1.pop() >>> a 'C’ >>> set1 {'A'} インタプリタでの挙動確認

Slide 164

Slide 164 text

辞書型の概要 • セットと似ているが要素は「キー(key)」と「バリュー (value)」を持つ。キーは重複できないがバリューは重複できる • キーを指定してバリューを取得/更新する • 同じキーで要素を追加するとバリューが上書きされる >>> fruits_dict = dict() >>> fruits_dict['apple'] = 'red' >>> fruits_dict['banana'] = 'yellow' >>> fruits_dict {'apple': 'red', 'banana': 'yellow'} >>> fruits_dict['apple'] 'red' インタプリタでの挙動確認(詳細は次ページより)

Slide 165

Slide 165 text

辞書型の操作 (1/3) • 辞書オブジェクトの作成⽅法 • dict() • {} • {key1:value1, key2:value2, ...} • セット型と使う記号が同じ中括弧。違いは要素がキーとバ リューのペアになっていることのみ • キーの型は⽂字列が⼀般的だが他の型(数値など)も使える >>> fruits_dict = {'apple':'red', 'banana':'yellow'} >>> type(fruits_dict) >>> fruits_dict2 = {} >>> type(fruits_dict) インタプリタでの挙動確認

Slide 166

Slide 166 text

辞書型の操作 (2/3) • 辞書オブジェクトからのバリューの取得 • 書式: OBJECT[KEY] • 辞書オブジェクトへの要素の追加 • 存在しないキー: 新しいキーとバリューのペアが登録される • 存在するキー: キーの対となるバリューが更新される • 書式: OBJECT[KEY] = VALUE >>> fruits_dict = {'apple':'red', 'banana':'yellow'} >>> fruits_dict['apple'] 'red' >>> fruits_dict['apple'] = 'green' >>> fruits_dict['apple'] 'green' インタプリタでの挙動確認

Slide 167

Slide 167 text

辞書型の操作 (3/3) • in演算⼦: キーの存在確認 • 存在しないキーのバリューを取得しようとするとエラーになる • キーの存在が不明な場合は事前にin演算⼦か後述のgetメソッド を使うこと >>> fruits_dict = {'apple':'red', 'banana':'yellow'} >>> 'apple' in fruits_dict True >>> 'grape' in fruits_dict False >>> fruits_dict['grape'] Traceback (most recent call last): File "", line 1, in KeyError: 'grape' インタプリタでの挙動確認

Slide 168

Slide 168 text

辞書型のメソッド (1/4) • keys: キーの⼀覧をリスト形式で返す • values: バリューの⼀覧をリスト形式で返す • items: 「キーとバリューのタプル」をリスト形式で返す • itemsはforループでの利⽤に便利 >>> a = {'apple':'red', 'banana':'yellow'} >>> a.keys() dict_keys(['apple', 'banana']) >>> a.values() dict_values(['red', 'yellow']) >>> a.items() dict_items([('apple', 'red'), ('banana', 'yellow')]) インタプリタでの挙動確認

Slide 169

Slide 169 text

辞書型のメソッド (2/4) • 辞書型をforループで全て処理する操作 • for⽂のin演算⼦に辞書オブジェクトを与える: keyでループ • for⽂のin演算⼦にitemsメソッドを与える: keyとvalueでループ fruits_dict = {'apple':'red', 'banana':'yellow'} for key in fruits_dict: print(key) fruits_dict = {'apple':'red', 'banana':'yellow'} for (key, value) in fruits_dict.items(): print('{} : {}'.format(key, value)) $ python3 dict_01.py apple banana $ python3 dict_02.py apple : red banana : yellow /chapter4/dict_01.py /chapter4/dict_02.py コンソール出⼒ コンソール出⼒

Slide 170

Slide 170 text

辞書型のメソッド (3/4) • get: キーを指定してバリューを取得する。キーが存在しない場 合はデフォルト値を取得 • デフォルト値を指定しない場合はNoneがデフォルト値 • デフォルト値を取得しても元の辞書オブジェクトに変化なし • 似た関数にsetdefaultがある(割愛) page_counter = {} value = page_counter.get('/hello.html', 0) print(value) print(page_counter) $ python3 dict_03.py 0 {} /chapter4/dict_03.py コンソール出⼒

Slide 171

Slide 171 text

辞書型のメソッド (4/4) • getメソッドを使うことでカウンターのような実装を簡単に実 現できる • 複雑な初期化処理が必要な場合はin演算⼦を使って以下のよう な実装をすることを推奨 • 存在しない場合: 初期化処理をして辞書オブジェクトに代⼊ • 存在する場合: 辞書オブジェクトから取得 page_counter = {} page_counter['/page_a.html'] = page_counter.get('/page_a.html', 0) + 1 page_counter['/page_a.html'] = page_counter.get('/page_a.html', 0) + 1 page_counter['/page_b.html'] = page_counter.get('/page_b.html', 0) + 1 print(page_counter) $ python3 dict_04.py {'/page_a.html': 2, '/page_b.html': 1} /chapter4/dict_04.py コンソール出⼒

Slide 172

Slide 172 text

コラム: 基本的な型と制御がプログラミングの中⼼ • Pythonプログラミングの基本は以下となる • ライブラリにある処理はライブラリに任せる • ライブラリを使うプログラムは⾃分で作る(貼り合わせ) • 後者はこの章までに学んだ基本的な型(数値、⽂字列、リスト、 タプル、セット、辞書型)を基本的な制御(if, for, while)で操作 するのが上級者でもおよそコードの8割以上と思われる • すでに学んだ関数や今後学ぶクラスや例外処理などは上記の ベーシックなプログラムを整理するためのもの。⾼度なプログ ラミングテクニックを学ぶ前に基礎を抑えるのが⼤事 • フルスクラッチで素材から開発するのではなく、ライブラリと いう「レゴの出来合いのパーツ」をスマートに⾃分のコードで 張り合わせて作品を作るのがPython流のプログラミング

Slide 173

Slide 173 text

コラム: 著者の型の使い分け • タプル: 引数や返り値で値をまとめる • リスト: 可変⻑の複数の要素を管理するために使う。なにかを ループ処理するときに使う第⼀候補。要素探索が遅いので注意 • セット: 要素の存在チェックが必要な場合にリスト代替で使う • 辞書型: リストに似た使い⽅だが、要素をすばやく検索できる 必要がある場合に使う。辞書型のキーは「データベースでいう 主キーやインデックス」で、それを使って該当エントリを素早 く抜き出すようなイメージ。Pythonプログラミングでは辞書型 が⾮常に便利なので使いこなそう。 • 余談: 辞書型とListの特徴をあわせ持つ 「順序付き辞書 (OrderedDict)」などの変種もある

Slide 174

Slide 174 text

• 数値のリストを受け取り、そこから最⼩値と最⼤値を同時に返 す関数 get_min_max を作成し、その関数の返り値の最⼩値と 最⼤値をそれぞれ別の⾏でコンソールに出⼒してください。 • リスト型での要素の探索に⽐べて、セット型での要素の探索が ⾼速である理由をインターネットで調べてください。 • 数値のリストを受け取り、各数値が何回出現したかをカウント する関数を辞書型を使って作成してください。返り値は{数値1: 出現数1, 数値2:出現数2, ...}という形式とします。 • 上記関数の出⼒をforループでキーとバリューのペアごとに 「'{} : {}'.format(key, value)」というフォーマットでプリント 出⼒してください。 演習

Slide 175

Slide 175 text

クラスの使い⽅をマスターしよう CHAPTER 5 1. クラスの仕組みと設計⽅法を知る 2. クラスの必要性を理解する 3. クラスの⾼度な使い⽅を知る

Slide 176

Slide 176 text

クラスの仕組みと設計⽅法を知る • このセクションで学ぶこと • クラスとは • この章の学習の流れ • クラスとメソッドを定義する • ⾃分で定義したクラスのインスタンスを作成 • メソッド定義の第⼀引数selfは⾃動で代⼊される • クラスの命名規則 • インスタンス変数 • コンストラクタでのインスタンス変数の定義 • メソッド間のインスタンス変数の共有 • インスタンス変数の外部からの参照 SECTION 01

Slide 177

Slide 177 text

クラスとは • 複雑なデータと処理をまとめるための⽂法 • クラスを使わないとプログラムが⼤規模化した際に「どの関数 がどのデータを使うか」を管理しにくくなる • クラスで枠を作ることで構造をプログラマに強制する

Slide 178

Slide 178 text

この章の学習の流れ • クラスの概念の理解は難所のため、以下の順を追って学ぶ 1. Section1 : クラスとメソッドの定義⽅法 2. Section1 : クラスをインスタンス化する⽅法 3. Section1 : データ(インスタンス変数)の定義 4. Section2 : クラスの有無によるプログラムの⽐較 5. Section3 : その他のトピック

Slide 179

Slide 179 text

クラスとメソッドを定義する • classに続けてクラス名を書く • classのブロック内にメソッドを関数と同じくdefで定義 • メソッドの第⼀引数は常に「self」とする class MyClass: def plus(self, a, b): return a + b def minus(self, a, b): return a - b /chapter5/myclass.py クラスの定義 インスタンスが使うメソッドの定義

Slide 180

Slide 180 text

⾃分で定義したクラスのインスタンスを作成 • 「クラス名()」でインスタンス化をおこなう • インスタンス.メソッド名()でメソッドの呼び出しを⾏なう • 呼び出し側で引数selfに相当するものを与えていない(後述) class MyClass: def plus(self, a, b): return a + b def minus(self, a, b): return a - b myclass = MyClass() a = myclass.plus(5, 3) print(a) b = myclass.minus(5, 3) print(b) $ python3 myclass.py 8 2 /chapter5/myclass.py コンソール出⼒

Slide 181

Slide 181 text

メソッド定義の第⼀引数selfは⾃動で代⼊される • 引数の数の違い • クラスでの定義: 3つ。 下図のminusは「self, a, b」 • メソッドで与える数: 2つ。数のminusは「7, 5」 • Pythonのクラスでのメソッド定義のルール • 第⼀引数はselfとする • selfにはインスタンス⾃⾝が代⼊されている(利⽤法は後述)

Slide 182

Slide 182 text

クラスの命名規則 • 単語の区切りを⼤⽂字にする • クラス名の例 • MyClass • User • BingoMachine • この命名ルールは⼀般的に「キャメルケース」と呼ばれる。 キャメルはラクダで、⼤⽂字⼩⽂字の連なりがラクダのコブの ようにぼこぼこしているため

Slide 183

Slide 183 text

インスタンス変数 • 「インスタンス変数」は同⼀インスタンスのメソッド間で共有 される変数 • インスタンス変数はインスタンスごとに独⽴している • 同⼀クラスから作られた複数インスタンスの差はインスタンス 変数のみ。メソッドの処理などに違いはない クラスでインスタンス変数を定義 - name - age インスタンスでインスタンス変数に 具体的な値が代⼊される - name = beckey - age = 40

Slide 184

Slide 184 text

コンストラクタでのインスタンス変数の定義 • Pythonでインスタンス変数を定義するのは「コンストラクタ」 • コンストラクタは特殊なメソッドで「__init__(self, 初期化のた めの引数)」とし、処理でインスタンス変数の初期化を書く • 「self.インスタンス変数名 = 初期価値」として変数定義 • コンストラクタはクラスのインスタンス化時に呼び出される class User: def __init__(self, x, y): self.name = x self.age = y def dump(self): print('name:{}'.format(self.name)) print('age:{}'.format(self.age)) ana = User('ana', 30) ana.dump() $ python3 define_instance.py name:ana age:30 /chapter5/define_instance.py コンソール出⼒

Slide 185

Slide 185 text

メソッド間のインスタンス変数の共有 • メソッドの第⼀引数 selfはオブジェクト⾃⾝ • コンストラクタ内で⾃分⾃⾝にインスタンス変数を追加(定義) • メソッド内で⾃分⾃⾝が持つ変数にアクセス(read/write) self: インスタンス⾃⾝ name age コンストラクタ __init__ メソッド dump 初期化 (作成) 参照

Slide 186

Slide 186 text

インスタンス変数の外部からの参照 • インスタンス変数はメソッド内部だけでなく「インスタンス.イ ンスタンス変数名」としても参照できる • この利⽤法はJavaなどでは⾮推奨とされるがPythonは問題ない ので不必要なセッターやゲッターは作らないこと class User: def __init__(self, x, y): self.name = x self.age = y def dump(self): print('name:{}'.format(self.name)) print('age:{}'.format(self.age)) ana = User('ana', 30) print(ana.name) print(ana.age) $ python3 check_instance.py ana 30 /chapter5/check_instance.py コンソール出⼒

Slide 187

Slide 187 text

• 以下のクラスを作成してください • クラス名: User • 以下のインスタンス変数を持ち、コンストラクタで初期化 • id • name • address • 以下のメソッドを持つ • dumps: ⽂字列のformatメソッドを使ってCSV形式で「id, name, address」を⽂字列で返す • 上記クラスをインスタンス化してdumpsの結果を出⼒する 演習

Slide 188

Slide 188 text

クラスの必要性を理解する • このセクションで学ぶこと • ⽐較題材のプログラムについて • クラスを使わないプログラムの実装 • 中級者向け: 関数内での参照と代⼊の違い • クラスを使わないプログラムの実⾏ • クラスを使うプログラムの実装 • なぜクラスが必要か • インスタンスに閉じた副作⽤を使う • 正しいクラスの設計ができたら中級者 SECTION 02

Slide 189

Slide 189 text

⽐較題材のプログラムについて • クラスを使うべき理由を具体例(ビンゴマシーン)で確認する • 仕組み • 1-99の番号が振られたボールをランダムに抽出する • 同じボールは⼀度しか出ない • 全てのボールがなくなったら終了 ボール群をリストとする リストに要素(ボール)を追加 リストの要素(ボール)の順序を シャッフルして1つ取り出す 同じ仕組みをクラスなし/ありで実装

Slide 190

Slide 190 text

クラスを使わないプログラムの実装 • ビンゴを実現する関数 • initialize: 1-99のボール揃える • get_ball: ランダムにボールを取り出す(ランダム操作は6章) • has_ball: まだボールがあるか確認 • プログラムの問題: 引数経由でしかデータ共有ができない import random # ランダムな機能を使うという宣⾔ def initialize(balls1): balls1.clear() # リストを空にする balls1.extend(list(range(1, 100))) # リストに1-99を⼊れる def get_ball(balls1): random.shuffle(balls1) # リストをランダムに並べ替える return balls1.pop() def has_ball(balls1): return len(balls1) != 0 balls2 = [] initialize(balls2) # ボールがあればビンゴを回す while has_ball(balls2): print(get_ball(balls2)) 続き /chapter5/bingo_01.py

Slide 191

Slide 191 text

中級者向け: 関数内での参照と代⼊の違い • さきほどのinitializeで引数balls1にリストを代⼊すると失敗する • 引数をextendメソッドで参照して要素変更すると成功 • 深いレベルの知識(ポインタの概念)を理解していないと間違える 第3章で関数外の変数を 関数内で更新する例と 実はほとんど同じ動き bingo_01.py bingo_02.py

Slide 192

Slide 192 text

クラスを使わないプログラムの実⾏ • /chapter5/bingo_01.py: 2ページ前の正しいプログラム • /chapter5/bingo_02.py: 参照ではなく代⼊する誤ったプログラム $ python3 bingo_01.py 29 41 93 28 84 ... 32 22 5 49 83 80 13 $ python3 bingo_02.py ボールの初期化に成功している。 そのあとのランダムな取り出し処理も ボールがなくなるまで繰り返す。 ボールの初期化に失敗してリストが空のまま。 取り出すボールがないので取り出し処理はおきない bingo_01.pyの実⾏結果 bingo_02.pyの実⾏結果

Slide 193

Slide 193 text

クラスを使うプログラムの実装 (1/2) • クラスを使うことでメソッド間でデータ(ビンゴのボール)をイ ンスタンス変数として共有できる • あるメソッドでの変更(たとえば初期化や取り出し)が、別のメ ソッドでも反映される import random class Bingo: def __init__(self): self.balls = list(range(1, 100)) def get_ball(self): random.shuffle(self.balls) return self.balls.pop() def has_ball(self): return len(self.balls) != 0 bingo = Bingo() while bingo.has_ball(): print(bingo.get_ball()) 続き /chapter5/bingo_03.py

Slide 194

Slide 194 text

クラスを使うプログラムの実装 (2/2) • 初⼼者にはクラスという⽂法で難しく⾒えるかもしれない • 処理(メソッド)間で「データ(インスタンス変数)を共有するこ と」が簡単になる • 難しい参照と代⼊の違いを意識しないでも動く

Slide 195

Slide 195 text

なぜクラスが必要か ⽐較項⽬ クラスなし クラスあり ⽂法 シンプル 複雑 変数と関数 同じ空間上に多数存在 クラス内の数は少ない データの共有 難しい メソッド間はインスタンス変数を使えば簡単 データ構造の定義 タプルやリストなどの組み合わせ クラスで構造を定義し、新しい型を作れる 初期化処理 ⾃分で任意で実⾏ コンストラクタで⾃動で実施 副作⽤の利⽤ 管理しにくいので避けるべき クラス内では積極的に使うべき デバッグ しにくい 整理されているためやりやすい 総合判断 単純なプログラム向け 複雑なプログラムでは必須 • 複雑なプログラムを構造化することで、データや制御の流れをシ ンプルにできるため。難しさをクラス内に押し込める • 逆に⾔えばシンプルなプログラムではクラスを使わなくてもよい 気になる⼈は「カプセル化」というキーワードで調べてみるとよいかも

Slide 196

Slide 196 text

インスタンスに閉じた副作⽤を使う • ⼀般的にプログラミングでは副作⽤(3章)を減らすのが望ましい • ただしインスタンス内の変数にたいしては例外 • プログラムの影響範囲がクラス定義内と限定的 • 外部の複雑さをクラス内に押し込むことで全体を綺麗にする • インスタンスを使う側が簡単に使えることを最も優先する

Slide 197

Slide 197 text

正しいクラスの設計ができたら中級者 • オブジェクト指向のクラスの⽂法は頑張れば覚えられる • 正しいオブジェクト指向の設計は勉強だけでなく経験が必要 • 上級者でも設計変更は発⽣するので完璧なものを最初から作ろ うとするのではなく、作って修正を繰り返して慣れるのがよい ブラック ボックス 複雑な プログラム 複雑な プログラム 利⽤する側の プログラム クラス内部の複雑なプログラムを 意識せず表⾯的に他のクラスを使う 分かりやすい メソッドの定義

Slide 198

Slide 198 text

• テキストを追加するクラスを作成してください • インスタンス変数 self.text = “”をコンストラクタで定義 • メソッドadd_text: インスタンス変数self.textに引数のテキスト を追加 演習 ta = TextAdder() ta.text '' ta.add_text('hello') ta.text 'hello' ta.add_text(' world') ta.text 'hello world' 操作イメージ

Slide 199

Slide 199 text

• ⽂字の出現数(空⽩を含む)をカウントするクラスを作成してく ださい • コンストラクタ: 引数はselfのみでインスタンス変数 self.char_counterに{}を設定する • メソッド • add_text: 引数はselfとtext(⽂字列)で、メソッド内でtextを1 ⽂字ごとforループで回す。出現する⽂字を self.char_counterで数える(ヒント: dictのgetメソッドと初期 値を使うと実装が簡単) • get_counts: インスタンス変数 self.char_counter の値を返 す。 演習

Slide 200

Slide 200 text

クラスの⾼度な使い⽅を知る • このセクションで学ぶこと • クラス変数 • クラスメソッド • クラスの継承 • コラム: 初⼼者はあまり継承を使わない? SECTION 03

Slide 201

Slide 201 text

クラス変数 • 「クラス変数(定数)」はインスタンスをまたいで共有されるクラス レベルの変数(定数)で、クラス直下に定義する • クラス内で「クラス名.クラス変数名」で参照や代⼊をおこなう class MyClass: abc = 'abc' DEF_GHI ='def ghi' def print_abc(self): print(MyClass.abc) def set_abc(self, abc): MyClass.abc = abc a = MyClass() b = MyClass() # クラス変数の変更前 a.print_abc() b.print_abc() # クラス変数の変更後 a.set_abc('hello python') a.print_abc() b.print_abc() 続き $ python3 class_var_const.py abc abc hello python hello python /chapter5/class_var_const.py コンソール出⼒

Slide 202

Slide 202 text

クラスメソッド (1/2) • 「クラスメソッド」はクラス外から直接「クラス名.メソッド名()」 として呼び出せる特別なメソッド • メソッド前に「@classmethod」と「アノテーション」を加える • クラスメソッド内でインスタンス変数や通常のメソッドは使えない class MyClass: def __init__(self): self.a = 'aaa' @classmethod def method1(cls): print('class method') def method2(self): print('instance method') # インスタンス化してからクラスメソッドを呼び出す mc = MyClass() mc.method1() mc.method2() # インスタンス化せずにメソッドを呼び出す MyClass.method1() MyClass.method2() 続き /chapter5/method.py

Slide 203

Slide 203 text

クラスメソッド (2/2) • メソッド呼び出し可否のまとめ • インスタンスでクラスメソッド: 呼び出せる • インスタンスで通常メソッド: 呼び出せる • クラス名でクラスメソッド: 呼び出せる • クラス名で通常メソッド: 呼び出せない(下記エラー) • クラスメソッドに似た「スタティックメソッド」もある(割愛) $ python3 method.py class method instance method class method Traceback (most recent call last): File "method.py", line 19, in MyClass.method2() TypeError: method2() missing 1 required positional argument: 'self' コンソール出⼒ クラス名でメソッドを 呼び出そうとしてエラー

Slide 204

Slide 204 text

クラスの継承 • 「継承」はクラスAの特徴をクラスBに引き継がせる機能 • 継承元を「親クラス」、親を継承する側を「⼦クラス」と呼ぶ • 基本機能を持つ親クラスを⼦クラスが継承して拡張する使い⽅ • ⼦クラスのクラス名の後のカッコに親クラス名を書く class ParentClass: def method1(self): print('parent method') class ChildClass(ParentClass): def method2(self): print('child method') cc = ChildClass() cc.method2() cc.method1() $ python3 succession.py child method parent method ⼦クラスが親クラスのメソッドも呼び出せている /chapter5/succession.py コンソール出⼒

Slide 205

Slide 205 text

コラム: 初⼼者はあまり継承を使わない? • クラスAにクラスBの機能を取り込む際に何も考えずに継承を使うの は間違った使い⽅。継承は「Reader -> TextReader, ImageReader」といったように親を⼦がより詳細化する際に使う • 単純に機能だけを使いたければクラスA内でクラスBを使えばよい • 別クラスの機能を取り込むことを「委譲(デリゲーション)」という class ClassA: def __init__(self): self.class_b = ClassB() def use_class_b(self): self.class_b.print_hello() class ClassB: def print_hello(self): print('hello') class_a = ClassA() class_a.use_class_b() /chapter5/define_instance.py $ python3 delegation.py hello コンソール出⼒

Slide 206

Slide 206 text

• 継承とデリゲーションの使い所について説明してください • Pythonのアノテーションがなにか、他にどのようなものがある か調べてみてください 演習

Slide 207

Slide 207 text

モジュールを利⽤しよう CHAPTER 6 1. モジュールを利⽤する 2. ⾃分でモジュールを作成する 3. 標準ライブラリを利⽤する 4. 外部パッケージを利⽤する

Slide 208

Slide 208 text

モジュールを利⽤する • このセクションで学ぶこと • モジュールによるプログラムの整理 • 組み込みモジュール • 標準ライブラリ • 外部パッケージ • ⾃作のモジュール • モジュールとクラスの違い • モジュールを使ってみよう • モジュール内のクラスの利⽤ • 複数のモジュールを組み込む • モジュール名を付けずに関数やクラスを呼び出す • コラム: from⽂の問題点 SECTION 01

Slide 209

Slide 209 text

モジュールによるプログラムの整理 • 「モジュール」はプログラムが書かれたファイルのこと • 巨⼤な1つのファイルに全てを書くのではなく、分類に沿って プログラムを複数ファイルに分けることで全体を整理できる • 「パッケージ」は複数のモジュールをおさめるディレクトリ • モジュールは以下の以下図の4つに分類できる

Slide 210

Slide 210 text

組み込みモジュール • 「組み込みモジュール」はPythonがデフォルトで読み込む • print関数などの特に宣⾔なく利⽤できる機能が格納されている

Slide 211

Slide 211 text

標準ライブラリ • 「標準ライブラリ」はPythonをインストールすると⾃動で付属 してくるモジュール群 • プログラム内で利⽤する宣⾔をすると、その内部で定義されて いる関数やクラスが利⽤できるようになる

Slide 212

Slide 212 text

外部パッケージ • 「外部パッケージ」はPythonに標準で付属しないモジュール • 「pipコマンド」でインターネット上のリポジトリからインス トールをすることで使えるようになる • インストール後は標準ライブラリと同じように利⽤可能となる

Slide 213

Slide 213 text

⾃作のモジュール • 1つのファイルに収まりきらないコードを分割して作成する • Pythonでは可能な限り⾃分では難しい処理を書かずに標準ライ ブラリや外部パッケージを繋ぐ書き⽅が⼀般的

Slide 214

Slide 214 text

モジュールとクラスの違い • モジュールもクラスもプログラムを整理する仕組み • モジュールはクラスよりも⼤きい単位でのコードの分割 • 1つのモジュール内に複数のクラスを含めることができる

Slide 215

Slide 215 text

モジュールを使ってみよう • 数学関係のモジュール「math」(標準ライブラリ)を利⽤する • モジュール利⽤の宣⾔: import モジュール名 • モジュールの関数などの利⽤: モジュール名.関数() • 宣⾔はプログラムファイルの先頭周辺で⾏なうのが⼀般的 # mathモジュールの読み込み import math # mathモジュールのceil関数の利⽤ a = math.ceil(5.4) print(a) # mathモジュールのfloor関数の利⽤ print(math.floor(5.4)) $ python3 math_01.py 6 5 モジュールを利⽤する前にimportしないと エラーになる。 プログラムの冒頭でimportするのが慣習 /chapter6/math_01.py コンソール出⼒

Slide 216

Slide 216 text

モジュール内のクラスの利⽤ • ⽇時を扱うdatatimeモジュールを使う • モジュールのクラスの利⽤: モジュール名.クラス名 import datetime now = datetime.datetime.now() print(now) >>> import datetime >>> datetime >>> datetime.datetime >>> datetime.datetime.now $ python3 datetime_01.py 2020-04-17 14:44:45.660410 /chapter6/datetime_01.py 「datetime.datetime.now」は「モジュール名.クラス名.メソッド名」 コンソール出⼒

Slide 217

Slide 217 text

複数のモジュールを読み込む • 必要なモジュールを1⾏ごと宣⾔するのが⼀般的 • 1⾏にまとめて宣⾔することもできる • 利⽤しないモジュールは宣⾔しないこと import math import time, datetime print(datetime.datetime.now()) time.sleep(3) print(datetime.datetime.now()) $ python3 math_datetime_01.py 2020-04-17 14:55:04.546417 2020-04-17 14:55:07.550372 /chapter6/math_datetime_01.py コンソール出⼒

Slide 218

Slide 218 text

モジュール名を付けずに関数やクラスを呼び出す • fromで宣⾔するとモジュール名を省略して利⽤できる • from モジュール名 import クラス名や関数名 • from モジュール名 import *(全て) from math import ceil from time import * print(ceil(5.4)) sleep(1) print(floor(5.3)) $ python3 from_import_01.py 6 Traceback (most recent call last): File "from_import_01.py", line 6, in print(floor(5.3)) NameError: name 'floor' is not defined /chapter6/from_import_01.py コンソール出⼒ importで指定したクラスや関数のみ読み込み モジュールの全てのクラスや関数を読み込み 読み込んでいないmathのfloorを 呼び出そうとしたためエラー

Slide 219

Slide 219 text

コラム: from⽂の問題点 • fromで*(ワイルドカード)指定するのは⼿間がかからなくて簡単 • クラスや関数を多いと「関数やクラスがどのモジュールに属し ているかが分かりにくくなる」という問題がある • from⽂の使い所 • 短いスクリプトなどで保守されない場合は使って問題ない • メンテされる⼤きめのプログラムではきちんとimport⽂を 使って宣⾔する

Slide 220

Slide 220 text

• 「組み込みモジュール」「標準ライブラリ」「外部パッケー ジ」の違いについて説明してください • 標準ライブラリの利⽤演習 • jsonモジュールをimportしてください • 以下のdictを作成してください。{'apple':'red', 'banana':'yellow'} • json.dumps(dictオブジェクト)で辞書データを⽂字列型の JSONに変換してください • json.loads(⽂字列型のJSON)で辞書データを得てください • JSONはPythonに限らずマシン間やサービス間でのやりとり に多⽤されるデータ構造なので調べてみてください。 演習

Slide 221

Slide 221 text

⾃分でモジュールを作成する • このセクションで学ぶこと • モジュールは2つの種類に分けて書く • モジュールを作成する • モジュールが組み込まれる流れ • モジュールの中⾝と開始条件 • 定義と実⾏コードの分離 SECTION 02

Slide 222

Slide 222 text

モジュールは2つの種類に分けて書く • タイプ1: システム特有の汎⽤的な処理をまとめたモジュール。 ⾃作ライブラリに近く、他のプロジェクトでも再利⽤可能 • タイプ2: タイプ1のモジュールを使ってシステムを形作るモ ジュール。汎⽤処理はタイプ1に押し込むこと。 タイプ1のモジュールは 機能ごとに別モジュールに 分割することが好ましい

Slide 223

Slide 223 text

モジュールを作成する • モジュールA(main.py)がモジュールB(myutil.py)を使う • 2つのファイルは同じフォルダに格納する • ファイルがあるフォルダに移動してからプログラムを呼び出し print('main.py start') import myutil print('main.py after import') def main_test(): print('main_test() called') main_test() myutil.myutil_test() print('main.py end') print('myutil.py start') def myutil_test(): print('myutil_test() called') print('myutil.py end') $ python3 main.py main.py start myutil.py start myutil.py end main.py after import main_test() called myutil_test() called main.py end /chapter6/main-myutil1/main.py /chapter6/main-myutil1/myutil.py 同じフォルダに使う側と使われる側の Pythonプログラム(モジュール)を置く。 そのフォルダでプログラムを起動 コンソール出⼒

Slide 224

Slide 224 text

モジュールが読み込まれる流れ • 起動したファイルの⽂頭から読まれる • 途中でimportやfrom⽂があると指定されたモジュールから先に 読み込み処理をおこなう

Slide 225

Slide 225 text

モジュールの中⾝と開始条件 • 複数のモジュールから構成されるプログラムで最初に呼び出さ れるモジュールを「エントリポイント」と呼ぶ • エントリポイント以外では実⾏処理は書かないことが期待され る。つまり定数や関数、クラスの宣⾔のみをおこなう

Slide 226

Slide 226 text

定義と実⾏コードの分離 (1/2) • エントリポイント以外では定義のみ⾏い処理は実⾏させない • 「if __name__ == ' __main__ ':」という条件式を使う • 特殊属性 __name__ にはエントリポイントの場合は 「'__main__'」が、それ以外はモジュール名が⼊る • __name__ が'__main__'の場合にのみ処理を実⾏させる import myutil def start(): myutil.myutil_test() # エントリポイントの場合の処理 if __name__ == '__main__': print('main.py is entry point') start() この条件はこのプログラムファイルが エントリポイントの場合だけ満たされる /chapter6/main-myutil2/main.py

Slide 227

Slide 227 text

定義と実⾏コードの分離 (2/2) import myutil def start(): myutil.myutil_test() # エントリポイントの場合の処理 if __name__ == '__main__': print('main.py is entry point') start() def myutil_test(): print('myutil_test() called') print('__name__ of myutil : ' + __name__) # エントリポイントの場合の処理 if __name__ == '__main__': print('myutil.py is entry point') myutil_test() $ python3 main.py main.py is entry point myutil_test() called __name__ of myutil : myutil $ python3 myutil.py myutil.py is entry point myutil_test() called __name__ of myutil : __main__ /chapter6/main-myutil2/main.py /chapter6/main-myutil2/myutil.py コンソール出⼒ コンソール出⼒ 他から使われるモジュールではエントリポイントを 「モジュールのテストの実施」に使うとよい。 モジュールレベルでの完成度が得られるまでテストする myutilの実⾏処理は動作していない

Slide 228

Slide 228 text

• モジュール mymath.py を作成して⼩数点を受け取る「切り下 げ: floor」と「切り上げ: ceil」を関数として作成してください。 • ヒント: 切り下げはint型への変換、切り上げは「もとの値と切 り下げ値が同⼀なら切り下げ値、そうでなければ切り下げ+1」 で実装できます。⾯倒ならmathモジュールを使ってください • 5.1 -> 切り下げ:5, 切り上げ6 • 5.0 -> 切り下げ:5, 切り上げ5 • 等号演算⼦(==)で5.0と5を⽐較するとTrueになる • main.py モジュールで上記のmymathをimportし、切り上げと 切り下げの計算を確認してください • main.pyではエントリポイントとして起動された時だけ上記処 理を実施するために「if __name__ == '__main__': 」を使って ください 演習

Slide 229

Slide 229 text

標準ライブラリを利⽤する • このセクションで学ぶこと • 時間関連の処理をおこなうtimeモジュール • 時間関連の処理をおこなうdatetimeモジュール • 乱数を⽣成するrandomモジュール SECTION 03

Slide 230

Slide 230 text

時間関連の処理を⾏うtimeモジュール • 時間を扱う基本的な処理 • time.sleep(x): x秒のスリープ • time.time(): 現在のUNIX時間(世界標準時の1970年1⽉1⽇から 何秒経過したか)を取得する • ある作業の前後で時間を取得し差分から実⾏時間を測定できる import time start = time.time() print(start) time.sleep(10) end = time.time() print(end) print(end - start) $ python3 time_01.py 1587107549.013738 1587107559.0178628 10.004124879837036 /chapter6/time_01.py コンソール出⼒

Slide 231

Slide 231 text

時間関連の処理を⾏うdatetimeモジュール • 時刻を扱うモジュール。⼈間の時間(2020年4⽉17⽇ 16:00な ど)はtimeではなくdatetimeが使いやすい • datetime.datetime.today(): 現在時刻の取得し、datetimeイン スタンスを返す • datetimeインスタンスには様々なメソッドと変数がある $ python3 datetime_02.py 2020-04-17 16:16:31.147644 2020/4/17 16:16:31 import datetime now = datetime.datetime.today() print(now) print('{}/{}/{} {}:{}:{}'.format(now.year, now.month, now.day, now.hour, now.minute, now.second)) /chapter6/datetime_02.py コンソール出⼒

Slide 232

Slide 232 text

乱数を⽣成するrandomモジュール • 乱数(ランダムな値)を⽣成するモジュール • random.random(): 0から1のあいだのランダムな⼩数を得る • random.randint(x, y): 引数のあいだにあるランダムな整数を得る • random.shuffle(): 引数のリスト要素をランダムに並び替える import random print(random.random()) print(random.randint(0, 100)) import random numbers = list(range(10)) print(numbers) random.shuffle(numbers) print(numbers) $ python3 random_01.py 0.2799910238537131 89 $ python3 random_02.py [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [4, 9, 3, 7, 1, 6, 5, 2, 0, 8] /chapter6/random_01.py /chapter6/random_02.py コンソール出⼒ コンソール出⼒

Slide 233

Slide 233 text

• 3章の⾃作のソート関数を⾃作モジュールのmysortに定義して、 簡単なリストがきちんとソートされるか確認してください • randomモジュールを使って「0から100万」まででランダムに ⽣成した数値を1000個持つリスト⽣成してください • ⾃作の関数とPythonが提供するsorted関数で昇順ソートしてく ださい • Timeモジュールを使って⾃作のsort関数とPythonが提供する sort関数の処理時間を⽐較計測してください 演習

Slide 234

Slide 234 text

外部パッケージを利⽤する • このセクションで学ぶこと • 外部パッケージでPythonに機能を追加する • パッケージをインストールする • パッケージを利⽤する • コラム: ライブラリの使い⽅と探し⽅ SECTION 04

Slide 235

Slide 235 text

外部パッケージでPythonに機能を追加する • 標準ライブラリにない処理であっても⼀般的な処理(たとえば後 述するHTTPの操作)は外部パッケージに多く存在する • Python Package Indexにパッケージが集積されている • 有名なライブラリは信頼性が⾼いが無名なものは利⽤に注意

Slide 236

Slide 236 text

パッケージをインストールする • Pythonインストール時に付属する「pipコマンド」を使う (Linuxのyumやaptに相当する) • Windows: pip install <パッケージ名> • Mac: pip3 install <パッケージ名> PS C: \Users\yito8> pip install requests Collecting requests Using cached requests-2.13.0-py2.py3-none-any.whl Installing collected packages: requests Successfully installed requests-2.13.0 $ pip3 install requests Collecting requests Using cached .../requests-2.23.0-py2.py3-none-any.whl Installing collected packages: requests Successfully installed requests-2.23.0 Windowsでのpipを使ったrequestsのインストール Macでのpipを使ったrequestsのインストール

Slide 237

Slide 237 text

パッケージを利⽤する • pipでインストールしたパッケージは標準ライブラリと同じく import⽂もしくはfrom⽂で使える • インストールしていないパッケージをimportするとエラー import requests response = requests.get('http://www.yahoo.co.jp/') print(response.text) $ python3 requests_01.py ... /chapter6/requests_01.py コンソール出⼒

Slide 238

Slide 238 text

コラム: ライブラリの使い⽅と探し⽅ • ⾃分で特定の機能を実装する前に有名なパッケージがないか調 べてみるのがよい。低レイアの実装は可能な限り避けること • Googleで「python ライブラリ <やりたいこと>」と調べると パッケージの利⽤法ページやQAページがヒットすることが多い • 標準ライブラリの利⽤法はPythonの公式ドキュメントにある

Slide 239

Slide 239 text

• pip(pip3)でcowsayパッケージをインストールしてください • インタプリタでcowsay.関数名(⽂字列)を実⾏してください • 関数⼀覧[ʻbeavisʼ, ʻcheeseʼ, ʻdaemonʼ, ʻcowʼ, ʻdragonʼ, ʻghostbustersʼ, ʻkittyʼ, ʻmeowʼ, ʻmilkʼ, ʻstegosaurusʼ, ʻstimpyʼ, ʻturkeyʼ, ʻturtleʼ, ʻtuxʼ] 演習 >>> import cowsay >>> cowsay.cow('hello python') ____________ < hello python > ============ \ \ ^__^ (oo)\_______ (__)\ )\/\ ||----w | || ||

Slide 240

Slide 240 text

ファイルの読み書きと例外処理を⾏おう CHAPTER 7 1. テキストファイルの読み書きを⾏う 2. 予期しないエラーに例外処理で対応する 3. Pythonで⽇本語の⽂字列を扱う 4. プログラムへのユーザー⼊⼒を利⽤する

Slide 241

Slide 241 text

テキストファイルの読み書きを⾏う • このセクションで学ぶこと • ファイルの読み書き処理はテキストエディタと同じ • テキストファイルの読み込み • ファイルのクローズ • ファイルの書き込み処理 • ファイルの追記処理 • バイナリデータの読み書き処理 • コラム: バイナリデータの処理 SECTION 01

Slide 242

Slide 242 text

ファイルの読み書き処理はテキストエディタと同じ • ファイル操作の流れ 1. ファイルをモード(Read/Write/Append)を指定して開く 2. ファイルを操作する 3. ファイルを閉じる • Pythonでファイルの読み書きには「open」関数を使う • 関数の返り値のファイルオブジェクトのメソッドでファイル操作 hello world hello python fin = open('hello.txt', 'r') print(fin) $ python3 open_01.py <_io.TextIOWrapper name='hello.txt' mode='r' encoding='UTF-8'> コンソール出⼒ /chapter7/hello.txt /chapter7/open_01.py

Slide 243

Slide 243 text

テキストファイルの読み込み • open関数の第⼆引数を「r」にして読み込み専⽤のファイルオ ブジェクトを取得する • 読み込みモードでの主要な操作 • readメソッド: ファイルの内容を全て読み込む • forループ: ファイルの1⾏ずつループ処理する。省メモリ fin = open('hello.txt', 'r') text = fin.read() print(text) hello world hello python $ python3 open_02.py hello world hello python fin = open('hello.txt', 'r') i = 1 for line in fin: line = line.rstrip() print('{} {}'.format(i, line)) i += 1 $ python3 open_03.py 1 hello world 2 hello python コンソール出⼒ コンソール出⼒ /chapter7/hello.txt /chapter7/open_02.py 1⾏ずつ⾏番号とテキストを出⼒: /chapter7/open_03.py 巨⼤なファイルには 必ずforループを使う

Slide 244

Slide 244 text

ファイルのクローズ • OSのリソースの開放と「書き込み処理を確実にする」ために ファイル操作終了後にファイルオブジェクトをクローズする • 「close」メソッドを使う fin = open('hello.txt', 'r') text = fin.read() fin.close() hello world hello python $ python3 close_01.py コンソール出⼒ /chapter7/hello.txt /chapter7/close_02.py

Slide 245

Slide 245 text

ファイルの書き込み処理 • openする際に「w(write)」モードを指定する • オープン時にファイル内容が全削除される • writeメソッドでテキストを書き込む • 改⾏は付与されないので必要ならテキストに「\n」を追加 fout = open('test.txt', 'w') fout.write('write text1\n') fout.write('write text2\n') fout.close() $ python3 write_01.py write text1 write text2 コンソール出⼒ /chapter7/test.txt /chapter7/write_01.py

Slide 246

Slide 246 text

ファイルの追記処理 • すでにあるファイルの末尾にデータを書き込むには 「a(append)」を指定して追記モードでファイルを開く • 開いたあとの操作は「w」モードと同じ fout = open('test.txt', 'a') fout.write('write text3\n') fout.close() write text1 write text2 write text3 write text1 write text2 write text3 write text3 $ python3 write_02.py $ python3 write_02.py コンソール出⼒ /chapter7/test.txt(1回⽬の実⾏) /chapter7/test.txt(2回⽬の実⾏) /chapter7/write_02.py

Slide 247

Slide 247 text

バイナリデータの読み書き処理 • 画像などのバイナリデータはモードに「b(binary)」を加える • 読み込みモード: 「rb」 • 書き込みモード: 「wb」 fi = open('sample.png', 'rb') image = fi.read() fi.close() fo = open('test.png', 'wb') fo.write(image) fo.close() $ python3 write_03.py コンソール出⼒ /chapter7/sample.png /chapter7/test.png 画像ファイルのコピー: /chapter7/write_03.py

Slide 248

Slide 248 text

コラム: バイナリデータの処理 • バイナリデータを直接ユーザー操作することは少ない • たとえばPILモジュールによる画像操作(サイズを⼩さくする) 1. ファイルからバイナリデータを読み込む 2. ライブラリにバイナリデータを渡す 3. ライブラリでデータ加⼯(画像サイズを⼩さくする) 4. バイナリデータをライブラリから取得 5. バイナリデータをファイルに書き込む • 「io.BytesIO」でバイナリをファイルに⾒せる処理をバイナリ 系の操作ではよく使う。ファイルパスが求められるところにバ イナリを与えたり、ファイルに書き出すのではなくバイナリを 書き出すなどができる データ操作は ライブラリ 任せ

Slide 249

Slide 249 text

• テキストファイルを読み込んで、各⾏を逆に出⼒したファイル を書き出す。各⾏処理はforループがおすすめ。 • 発展課題: PILモジュールをインストールして画像サイズを編集 してください。 • 上記のファイル名指定での動作を確認したら、ライブラリに ファイル名を与えるかわり「io.Bytes()」でライブラリにバイ ナリデータを渡して、ライブラリからバイナリデータを受け 取ってファイルに書き出してください 演習 abcd efgh ijkl dcba hgfe lkji 読み込むファイル 出⼒するファイル >>> 'abc'[::-1] 'cba' ヒント: ⽂字列の反転処理

Slide 250

Slide 250 text

予期しないエラーに例外処理で対応する • このセクションで学ぶこと • 例外とは • 2種類の例外 • try/exceptによる例外処理 • 例外の詳細を取得する SECTION 02

Slide 251

Slide 251 text

例外とは • 「例外」はプログラムの予期しない動作で発⽣するエラー • エラーと例外(英語ではException)はほぼ同じ意味 • たとえば存在しないファイルを読もうとすると例外が発⽣する fin = open('abc.txt', 'r') for line in fin: print(line) fin.close() print('finished') $ python3 exception_01.py Traceback (most recent call last): File "exception_01.py", line 1, in fin = open('abc.txt', 'r') FileNotFoundError: [Errno 2] No such file or directory: 'abc.txt' /chapter7/exception_01.py コンソール出⼒

Slide 252

Slide 252 text

2つのタイプの例外 • 例外はおおまかに以下の2つに分類できる • プログラムのバグから発⽣する例外。⽂法エラーや0除算など • 外部要因で発⽣する例外。アクセス先サーバーのダウンなど • バグ起因の例外はプログラムを修正して対処することが必要 • 外部要因の例外は防げないので「例外処理(失敗したときの処理)」 を定義して対処する

Slide 253

Slide 253 text

try/exceptによる例外処理 (1/2) • 例外発⽣時に処理を継続するために「try/except」⽂を使う • try: 例外が発⽣する可能性がある場所 • except: try内で例外が発⽣した場合におこなわれる処理 try: file_name = 'test.txt' print('ファイルの読み込み開始') fin = open(file_name, 'r') fin.read() fin.close() print('読み込み成功') except: print('エラーが発⽣') print('プログラムが終了') $ python3 exception_02.py ファイルの読み込み開始 読み込み成功 プログラムが終了 $ python3 exception_02.py ファイルの読み込み開始 エラーが発⽣ プログラムが終了 存在する ファイル 存在しない ファイル コンソール出⼒ コンソール出⼒ /chapter7/exception_02.py エラーが発⽣してもプログラム最後まで実施されている

Slide 254

Slide 254 text

• tryブロック内の処理はエラー発⽣箇所以降は実⾏されない • exceptブロックはエラーが発⽣しなければ実⾏されない • try/except後の処理はエラーの有無に関わらず実⾏される try/exceptによる例外処理 (2/2)

Slide 255

Slide 255 text

例外の詳細を取得する (1/2) • except⽂で例外を「例外クラス」の変数に補⾜できる • 例外クラスの最も⼀般的なものは「Exception」 • 例外クラスの種類に応じた例外処理の定義なども可能で、可能 ならより詳細な例外クラスで実装することを推奨(割愛) try: fin = open('test999.txt', 'r') fin.close() except Exception as e: print('エラーが発⽣') print(e) $ python3 exception_03.py エラーが発⽣ [Errno 2] No such file or directory: 'test999.txt' /chapter7/exception_03.py コンソール出⼒

Slide 256

Slide 256 text

例外の詳細を取得する(2/2) • 「traceback」モジュールを使うとエラー発⽣時に出⼒されて いたメッセージのほぼ全てを補⾜できる • エラー発⽣箇所がファイルと⾏単位で分かる import traceback try: fin = open('test999.txt', 'r') fin.close() except: print('エラーが発⽣') error_text = traceback.format_exc() print(error_text) $ python3 exception_04.py エラーが発⽣ Traceback (most recent call last): File "exception_04.py", line 4, in fin = open('test999.txt', 'r') FileNotFoundError: [Errno 2] No such file or directory: 'test999.txt' コンソール出⼒ /chapter7/exception_04.py 中級者向け: 例外処理に慣れたら例外クラスを 指定した「予測していた」例外処理に加えて、 予測していなかった例外処理をExceptionなどの 上位の例外クラスでtraceback付きで処理する

Slide 257

Slide 257 text

• requestsモジュールのgetを例外処理でラップした関数を作成 してください(6章に従ってインストールが必要) • 返り値はタプルで(成功したか, レスポンスのテキスト)とします • 例外が発⽣した場合はtracebackをプリントして、(False, '') を返す • レスポンスに問題がある場合は(False, '')を返す • 問題がない場合(True, テキスト)を返す • リクエストレスポンスに問題があるかないかは「レスポンスオ ブジェクト.ok」で調べられます • わざと「存在しないサイトにアクセス」「存在するサイトの存 在しないURLにアクセス」をしてみてください 演習

Slide 258

Slide 258 text

Pythonで⽇本語の⽂字列を扱う • このセクションで学ぶこと • ⽂字コードとは • プログラムファイルの⽂字コード • コラム: python2の⽂字コード • 様々な⽂字コードのファイルの読み書き SECTION 03

Slide 259

Slide 259 text

⽂字コードとは • テキストファイル内の⽂字列も01で構成されている • 特定の01の組み合わせが「a」や「あ」と解釈されている • 同じ⽂字でも「⽂字コード」によって01の組み合わせが異なる • 16進数(0,1,...9,A,B,C,D,E)の1桁で2進数4桁「0000-1111」を表 現できるため、読みやすさで⽂字コードを含むバイナリ表記に は16進数を使うのが⼀般的 ⽂字コード 「a」の⽂字コード 「あ」の⽂字コード UTF-8 0x61 0x82A0 Shift-JIS 0x61 0xA4A2 EUC-JP 0x61 0xE38182

Slide 260

Slide 260 text

プログラムファイルの⽂字コード • Pythonの標準⽂字コードはUTF-8。これを使うのが基本 • 諸事情で他の⽂字コードを使う場合はプログラムの冒頭で「ど の⽂字コードでプログラムを書いているか」を宣⾔する # -*- coding: shift-jis -*- print('こんにちは') $ python3 encoding_01.py こんにちは コンソール出⼒ Shift-Jisで書かれたプログラム: /chapter7/encoding_01.py プログラムの⽂字コードの指定。 プログラムが指定した⽂字コードで なければエラーが発⽣する

Slide 261

Slide 261 text

コラム: python2の⽂字コード • Python2のデフォルト⽂字コードはASCII(アルファベットのみ) • ⽇本語及びマルチバイト⽂字を使うのであれば⽂頭での⽂字 コードの宣⾔がUTF-8でも必要 • ⾊々と⾯倒なので⽇本語を使うのであればPython3を使うべき

Slide 262

Slide 262 text

様々な⽂字コードのファイルの読み書き (1/2) • OSによってopen関数が想定するデフォルト⽂字コードが異なる • Windows(⽇本語環境): Shift-JIS • Mac: UTF-8 fin_sjis = open('sjis.txt', 'r') print(fin_sjis.read()) fin_sjis.close() fin_utf8 = open('utf8.txt', 'r') print(fin_utf8.read()) fin_utf8.close() $ python3 encoding_02.py Traceback (most recent call last): File "encoding_02.py", line 2, in print(fin_sjis.read()) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/codecs.py", line 322, in decode (result, consumed) = self._buffer_decode(data, self.errors, final) UnicodeDecodeError: 'utf-8' codec can't decode byte 0x82 in position 0: invalid start byte • デフォルト⽂字コードと異なる ファイルを⽂字コード指定なしに openするとエラー コンソール出⼒ /chapter7/encoding_02.py MacでUTF-8を期待していたのにShift-Jisをオープンしたのでエラーとなっている

Slide 263

Slide 263 text

様々な⽂字コードのファイルの読み書き (2/2) • open関数のencode引数で⽂字コードを指定可能 • マルチプラットフォーム環境も考慮すると以下を推奨 • テキストファイルの⽂字コードにはUTF-8を利⽤ • 移植性を考えてMacであってもファイル読み込み時の encodeオプションにUTF-8を指定しておく • writeモードではopen時に指定した⽂字コードでファイルが書 き出される fin_sjis = open('sjis.txt', 'r', encoding='shift-jis') print(fin_sjis.read()) fin_sjis.close() fin_utf8 = open('utf8.txt', 'r', encoding='utf-8') print(fin_utf8.read()) fin_utf8.close() $ python3 encoding_03.py あいうえお かきくけこ あいうえお かきくけこ コンソール出⼒ /chapter7/encoding_03.py

Slide 264

Slide 264 text

• 中に書かれている⽂字コードが不明なファイルの⽂字コードを 特定するプログラムを作成してください • UTF-8, Shift-JIS, EUC-JPの3つを判定するものとします • AsciiのテキストはUTF-8に分類されるとします • ヒント: 指定した⽂字コードで読み込めればその⽂字コード、 エラーがおきればその⽂字コードでないと分かります • 本書籍で提供されているUTF-8とShift-Jisのサンプルファイル を使って正しく判別できるか確認してください 演習

Slide 265

Slide 265 text

プログラムへのユーザー⼊⼒を利⽤する • このセクションで学ぶこと • コマンドライン引数による⼊⼒ • コマンドライン引数の利⽤例 • input関数での標準⼊⼒ • input関数の利⽤例 • コラム: コマンドライン引数 vs 標準⼊⼒ SECTION 04

Slide 266

Slide 266 text

コマンドライン引数による⼊⼒ • プログラムにユーザー⼊⼒を与える場⾯は多い • 解析プログラムで解析するデータのファイル • 接続先IPやパスワードなど • プログラム内に直接定数で定義するよりユーザーに⼊⼒させた ほうがプログラム修正がいらないので利⽤が簡単 • コンソールでプログラム起動時に与えるパラメーター(コマンド ライン引数)を「sys.argv」でリスト形式で取得できる $ python3 argument_01.py abcd efgh ['argument_01.py', 'abcd', 'efgh'] import sys print(sys.argv) 起動時にプログラム名に加えて「abcd」「efgh」が与えられている。 sys.argv(リスト)にプログラムファイルと コマンドライン引数が順番に格納されている コンソール出⼒ /chapter7/argument_01.py

Slide 267

Slide 267 text

コマンドライン引数の利⽤例 • 指定したファイルを読み込むプログラム • コマンドライン引数を使うコツ • 引数が指定された数か最初にチェックする • sys.argvの要素の値を分かりやすい定数に代⼊する import sys if len(sys.argv) < 2: print('Error. please input file name') exit() FILE_NAME = sys.argv[1] fin = open(FILE_NAME, 'r') print(fin.read()) fin.close() $ python3 argument_03.py hello.txt hello world hello python hello world hello python コンソール出⼒ /chapter7/argument_03.py /chapter7/hello.txt

Slide 268

Slide 268 text

input関数での標準⼊⼒ • 「input関数」で標準⼊⼒受け付け(ユーザーのキーボード⼊⼒ を受け付ける)状態となる • エンター(リターン)ボタンが押されたら⼊⼒終了 print(1) a = input('何か⽂字を⼊⼒してください:') print('⼊⼒値:' + a) print(2) $ python3 input_01.py 1 何か⽂字を⼊⼒してください: $ python3 input_01.py 1 何か⽂字を⼊⼒してください:hello ⼊⼒値:hello 2 コンソール出⼒ 「hello」と⼊⼒しエンターキー /chapter7/input_01.py

Slide 269

Slide 269 text

input関数の利⽤例 • パラメーター⼊⼒を対話式に⾏なうプログラム • IPやパスワードなどを順番に⼊⼒させる • 設定項⽬の番号を⼊⼒させ、各項⽬でIPやパスワードを⼊⼒ • プログラムをあえて⼀時中断させる⽬的 • デモやテストのステップごとに⽌めて結果を表⽰。確認を終 えたら次のプログラムに向かう file_name = input('please input filename: ') fin = open(file_name, 'r') print(fin.read()) fin.close() $ python3 input_02.py please input filename: hello.txt hello world hello python コンソール出⼒ ファイル名を聞いて、それを出⼒するプログラム: /chapter7/input_02.py

Slide 270

Slide 270 text

コラム: コマンドライン引数 vs 標準⼊⼒ • Pythonのプログラムはシェルスクリプトやバッチなどから呼び 出されることも多い • 標準⼊⼒はユーザーの敷居は低いかもしれないが、他のプログ ラムから使いにくくなる • コマンドライン引数は呼び出せば動くので、他のプログラムか ら使いやすい • 特別な理由がなければコマンドライン引数でパラメーターを⼊ ⼒させるのがよい • 第三の⼿法として「環境変数でのパラメーター指定」なども使 われることがある

Slide 271

Slide 271 text

• コマンドライン引数と、input関数でそれぞれ以下を実現するプ ログラムを作成してください • 「数値1, 計算記号, 数値2」を受け取る • 対応する計算記号は +, -, *, / の4つ • 数値1と数値2を与えられた計算記号で計算した結果をprint 出⼒する • ヒント1: 数値は⽂字列からfloatにキャストする • ヒント2: 計算記号の値に応じてif/elseで処理を変える 演習

Slide 272

Slide 272 text

アプリケーションを作成しよう CHAPTER 8 1. アプリケーション開発の流れを知る 2. 重要箇所をテスト実装する 3. 本番のプログラムを作る

Slide 273

Slide 273 text

アプリケーション開発の流れを知る • このセクションで学ぶこと • プログラム開発の計画を作る • ⽬的を実現するためになにが必要かまとめる • プログラム全体の流れを考える • コラム: 設計とフレームワーク SECTION 01

Slide 274

Slide 274 text

プログラム開発の計画を作る • 題材:インターネットから複数の画像を集めるプログラムを作成 • アプリケーション開発には計画が必要 • 本章では以下のステップで開発を進めていく • ⽬的を実現するためには何が必要かまとめる • プログラム全体の流れを考える • プログラムの中の重要な箇所を試験的に作ってみる • プログラムの⼤枠を作る • コードに機能を追加していき設計や品質を向上させる

Slide 275

Slide 275 text

⽬的を実現するためになにが必要かまとめる • ⽬的: インターネットから画像を取得する • 必要なこと • 画像のURLを取得してダウンロード • 画像のURLはウェブサイトのHTMLに埋め込まれている • 埋め込まれているURLを「正規表現(後述)」で抽出する

Slide 276

Slide 276 text

プログラム全体の流れを考える • 画像ファイルのURLを取得するウェブページのURLが必要 • ウェブページ1でウェブページと画像URLを集めたら、そこに あるウェブページ2で取得。次にウェブページ3と繰り返せる • 終了条件や同じURLの再取得を防ぐ⽅法を検討

Slide 277

Slide 277 text

コラム: 設計とフレームワーク • ⼊⾨書は読んで理解できたが、実際にサンプル以上のプログラ ムを書けないという⼈が多い • フレームワークは「⼤枠のなかの処理を⾃分で実装する」とい う⽅式でシステムを作成するので、ライブラリを使って⾃分が 全てを設計するよりも「設計が簡単」 • ⾃分で設計をするのは慣れが必要なので、HTML/CSSを学んで 簡易ウェブフレームワークで簡単な動的なウェブサイトを作っ てみるとよいかも ライブラリ ライブラリ ライブラリ ⾃分で設計した⼤枠 作成したパーツ フレームワークが⽤意する⼤枠 作成したパーツ 作成したパーツ 独⾃設計のアプリ フレームワークに従うアプリ

Slide 278

Slide 278 text

重要箇所をテスト実装する • このセクションで学ぶこと • なぜテスト実装が必要なのか • URLを指定してHTMLを取得 • 正規表現でHTMLからURLを取得 • 相対URLを絶対URLに変換 • URLが画像ファイルか否かを判定 • 画像ファイルを保存 SECTION 02

Slide 279

Slide 279 text

なぜテスト実装が必要なのか • 開発スピードを向上させるため • ⼤きなサービスのなかで⼩さな1つの機能を0から開発するの は「起動」「準備(テスト値の⽤意など)」に時間がかかる • ⼩さなコードでエラーを繰り返しながら機能を実現させ、その あとで組み込めばトラブルが少ない • 当初の想定と異なる場合があるため • 利⽤を想定していたライブラリが⽬的の機能を果たせない場合 などがある • 他を作り込んだうえで発覚すると修正が⼤変なので⼤枠を固め る前に可能な限りパーツを作っておく • すでに重要箇所が動いているとメンタル的に安⼼して開発できる

Slide 280

Slide 280 text

URLを指定してHTMLを取得 • 本番プログラムは⼤きくて複雑なので、「本番でも使いやすい テスト⽤のコード(たとえば関数)」を作成するのがよい • HTMLの取得には6章のrequestsモジュールを利⽤ import requests def download_html(url): response = requests.get(url) html = response.text return html html = download_html('https://gihyo.jp/book/list') fout = open('sample.html', 'w', encoding='utf8') fout.write(html) fout.close() $ python3 get_images_01.py 書籍⼀覧新刊|技術評論社 ... URLを指定してHTMLを取得するコード: /chapter8/get_images_01.py 出⼒ファイル: sample.html コンソール出⼒

Slide 281

Slide 281 text

正規表現でHTMLからURLを取得(1/2) • 先に取得したHTML内にはURLが多数ある • ウェブサイトや画像のURLを抜き出す処理に正規表現を使う • 「正規表現」は 特定のパターンの⽂字列が含まれるかのチェック や抜き出し処理をする⼿法。他のプログラミング⾔語にもある • 複雑な正規表現のパターンは検索するのが⼿っ取り早い。たとえ ば「Python 正規表現 URL」や「Python regex URL」など ... 複雑な正規表現は検索から 答えを発⾒

Slide 283

Slide 283 text

相対URLを絶対URLに変換 • 絶対URL: https://gihyo.jp/news/info/2020/03/1301 • 相対URL(ドメインが省略): /news/info/2020/03/1301 • 相対URLは現在のURLを基準とした表記なので、プログラムで 使う場合は現在地に依存がない絶対URLへの変換が望ましい import urllib.parse def get_abs_url(current_url, url): abs_url = urllib.parse.urljoin(current_url, url) return abs_url print(get_abs_url('https://gihyo.jp/book/list', 'http://gihyo.jp/site/inquiry')) print(get_abs_url('https://gihyo.jp/book/list', '/book/2017/978-4-7741-8751-8')) print(get_abs_url('https://gihyo.jp/book/list', '2017/978-4-7741-8751-8')) $ python3 get_abs_url.py http://gihyo.jp/site/inquiry https://gihyo.jp/book/2017/978-4-7741-8751-8 https://gihyo.jp/book/2017/978-4-7741-8751-8 コンソール出⼒ 相対URLを絶対URLに変換するプログラム: /chapter8/get_abs_url.py

Slide 284

Slide 284 text

URLが画像ファイルか否かを判定 • URLを以下の2種類のいずれか拡張⼦で判定する • 画像ファイル: 拡張⼦が「.jpg」「.png」「.gif」 • HTMLファイル: 画像ファイルでない場合全て • (厳密にはHTTPレスポンスのMIMEで判断することが望ましい) def check_url_type(url): if '.jpg' in url: print('jpg') elif '.png' in url: print('png') elif '.gif' in url: print('gif') else: print('html') urlの画像判定プログラム: /chapter8/check_url_type.py

Slide 285

Slide 285 text

画像ファイルを保存 • requestsで取得したレスポンスからデータを取得 • データをバイナリ書き込みモードでファイルに保存 import requests import os def save_image(url, filepath): # 画像データを取得 response = requests.get(url, stream=True) image_data = response.content fout = open(fpath, 'wb') fout.write(image_data) fout.close() URLの画像を保存する: /chapter8/save_image.py

Slide 286

Slide 286 text

• このセクションで作成したプログラムを全て実⾏してみる • 関数定義のみで実⾏コードが書かれていないプログラムは、⾃ 分で実⾏コードを作成してください 演習

Slide 287

Slide 287 text

本番のプログラムを作る • このセクションで学ぶこと • クラスを設計する流れ • コンストラクタの実装 • メソッドの役割を決める • メインメソッドの実装 • 指定ページから絶対URL⼀覧を得るメソッドの実装 • 絶対URLを画像とHTMLに振り分けるメソッドの実装 • 画像データを保存するメソッドの実装 • メインプログラムの実⾏ • コラム: プログラムのテスト SECTION 03

Slide 288

Slide 288 text

クラスを設計する流れ • 複雑なプログラムでは「関数(メソッド含む)が別の関数を呼び出 す」を繰り返すことで実現する • 関数間で全てのデータを引数で受け渡しするとカオスになるので、 クラスを使って共有データはインスタンス変数として定義する(詳 細な理由は5章を参照) • クラス設計 • プログラムが必要とする情報はコンストラクタで受け取る • メソッド間で共有されるデータはコンストラクタでインスタン ス変数として定義する • 処理に応じてメソッドを分けて、中⼼となるメソッドが各機能 を担当するメソッドを呼び出すシンプルな処理の流れを作る

Slide 289

Slide 289 text

このアプリケーションの設計概要 __init__(コンストラクタ) インスタンス変数の定義 run メインメソッド Whileループで集め 終わるまで繰り返す get_abs_url 指定URLから絶対値のURL群を取得 get_image_url_list URL群から画像のURL群を取得 save_images 画像URL群の画像をローカルに保存 実⾏ コード クラス定義 (1) (2) (3) (4) (5) (6) この章での実装順序

Slide 290

Slide 290 text

コンストラクタの実装 • 引数 • save_dirpath: 画像保存場所 • start_page: 最初にアクセスするURL • maximum_download: 集める画像の枚数 import os import re import urllib import requests class ImageCrawller: def __init__(self, save_dirpath, start_page, maximum_download): self.save_dirpath = save_dirpath self.crawl_url_list = [start_page] self.stocked_url = set() self.maximum_download = maximum_download self.download_counter = 0 • インスタンス変数 • self.save_dirpath: 引数より • self.crawl_url_list: 次にアクセスするURLのリスト • self.stocked_url: すでにアクセスしたURLのセット • self.maximum_download: 引数より • self.download_counter: 何枚保存したか数える コンストラクタの定義: /chapter8/image_crawller_01.py

Slide 291

Slide 291 text

メソッドの役割を決める • メソッドの分割について • ⼤きい: 処理が多すぎてメソッドの⾒通しが悪くなる • ⼩さい: メソッド間の呼び出しが多すぎて分かりにくい • 適切な粒度(分割する⼤きさ)が必要 • 本章で作成するメソッド • コンストラクタ(作成済み) • 下記3つを束ねる中⼼となるメソッド(メインメソッド) • あるURLのHTMLに含まれる絶対URLをリストで返すメソッド • URLをHTMLと画像に振り分けるメソッド • イメージを保存するメソッド

Slide 292

Slide 292 text

メインメソッドの実装 (1/2) • 荒削りでよいので、全体の処理の流れをコメント付きで書く • 細部を実装してからメインメソッドも微修正される • 実験的に主要な機能をテストしていないと設計しづらく、あと にプログラムの⼤きな修正が発⽣する可能性が⾼まる • プログラム(次ページ)の設計 1. 終了条件に合致していないか確認。合致していれば終了 2. URL回収⽤のウェブページURLをリストから取得 3. そのURLにアクセスして絶対URLのリストを取得 4. 絶対URLのリストを「画像」「ウェブページ」に分類 5. 画像のURLリストの画像を全て取得 6. 1に戻る(whileによる無限ループ)

Slide 293

Slide 293 text

メインメソッドの実装 (2/2) def run(self): while True: # 処理1: 探索するURLがなければ終了。規定数以上を集めていても終了 if len(self.crawl_url_list) == 0: break if self.download_counter >= self.maximum_download: break # 処理2: 次に調べるHTMLのURLを取得 crawl_url = self.crawl_url_list.pop(0) # 処理3: HTMLページから絶対URLを抽出する urls = self.get_abs_urls(crawl_url) # 処理4: 絶対URLをHTMLかイメージかに分類する。イメージのリストを返す image_url_list = self.get_image_url_list(urls) # 処理5: リストに格納されたイメージを全て保存する self.save_images(image_url_list) print('Finished') メインメソッドの定義を追加: /chapter8/image_crawller_02.py

Slide 294

Slide 294 text

Slide 295

Slide 295 text

絶対URLを画像とHTMLに振り分けるメソッドの実装 def get_image_url_list(self, url_list): try: image_url_list = [] for url in url_list: if url in self.stocked_url: # すでに登録されたURLなので無視 continue if '.jpg' in url: image_url_list.append(url) elif '.png' in url: image_url_list.append(url) elif '.gif' in url: image_url_list.append(url) else: self.crawl_url_list.append(url) # 画像ファイルではないのでURL取得に使う self.stocked_url.add(url) # URLを登録。同じものは再登録しない return image_url_list except Exception as e: print('Error: {}'.format(e)) return [] メソッドget_image_url_listを追加: /chapter8/image_crawller_04.py

Slide 296

Slide 296 text

画像データを保存するメソッドの実装 def save_images(self, image_url_list): for image_url in image_url_list: try: # 決められた回数以上のダウンロードをした場合は終了 if self.download_counter >= self.maximum_download: return # イメージを取得 response = requests.get(image_url, stream=True) image = response.content # イメージをファイルに保存 file_name = image_url.split('/').pop() save_path = os.path.join(self.save_dirpath, file_name) fout = open(save_path, 'wb') fout.write(image) fout.close() self.download_counter += 1 print('saved image: {}/{}' .format(self.download_counter, self.maximum_download)) except Exception as e: print('Error: {}'.format(e)) メソッドsave_imagesを追加: /chapter8/image_crawller_05.py

Slide 297

Slide 297 text

メインのプログラムの実⾏ • プログラム最後に「if __name__ == ' __main__ ' :」を定義 if __name__ == '__main__': save_dirpath = 'test' start_page = 'https://gihyo.jp/book/list' maximum_download = 10 crawller = ImageCrawller(save_dirpath, start_page, maximum_download) crawller.run() $ python3 image_crawller_06.py saved image: 1/10 saved image: 2/10 saved image: 3/10 saved image: 4/10 saved image: 5/10 saved image: 6/10 saved image: 7/10 saved image: 8/10 saved image: 9/10 saved image: 10/10 Finished コンソール出⼒ アプリを動かす実⾏コードを追加: /chapter8/image_crawller_06.py

Slide 298

Slide 298 text

コラム: プログラムのテスト • 数⼗⾏以上のコードがミスなく書けていると思わないこと • 「ビッグバンテスト」と呼ばれる全てを書き終わってから動かし てテストをすることは避けること • テストを使ってきちんと動くプログラムを書くコツ • モジュールの設計で役割ごとにプログラムファイルを分離 • 確実に動く⼩さなプログラムを開発してモジュールに組み込む • モジュール間の依存関係を減らしてモジュールレベルでテスト を実施できるようにする • 変更を繰り返した汚いコードは綺麗に書き直す • ユニットテストでテストを⾒える化する(中級者) • ⾃動化などでテストを勝⼿に⾛らせるようにする(上級者)

Slide 299

Slide 299 text

• 最初にアクセスするページを変更してアプリケーションを⾃分 で起動してみる(ウェブサイトに過負荷を与えるのを避けるため ⼩規模のサイトは使わないでください) • 画像ではなくHTMLを集めて保存するプログラムを作成してく ださい • 発展課題: HTMLがすでに保存されているファイル名であれば 名前に連番を付けるなどしてください 演習

Slide 300

Slide 300 text

お悩み相談コーナー 教科書は理解したけど次のレベルに進めません!! おまけ 1. ⼊⾨者卒業: 本を読むよりコードを書くべし 2. 初級者卒業: 美しい設計を体と頭で覚える 3. 中級者卒業: 開発はプログラミング以外にもある 4. 駆け出し編: インフラエンジニアという道もある 5. 歴史編: 開発とインフラの技術変遷

Slide 301

Slide 301 text

⼊⾨者卒業: 本を読むよりコードを書くべし • このセクションで学ぶこと • プログラミングのレベル • 包丁をにぎらず本ばかり読む駆け出し料理⼈ • やりたいことは書き始めてから考えよう • おすすめ1: Flaskによる簡易ウェブサービスの作成 • おすすめ2: Tkinterによるデスクトップアプリの作成 • おすすめ3: 業務向けの作業スクリプト作成 • 著者が興味でプログラムを書いた例 • ⼊⾨者卒業に難しい知識はいらない SECTION 01

Slide 302

Slide 302 text

プログラミングのレベル • ドラクエと同じで「適切な場所(学習内容)」でレベル上げ • 低いレベルで難易度の⾼すぎるエリアには向かわないこと • 2010年以降は開発スタイルが⼤きく変わってきている ⼊⾨者 初級者 中級者 中上級者 (オールラウンド型) 上級者 (プログラミング特化型) ⼊⾨書(2000円ぐらいの書籍)の レベルの内容を習得済み。 • 基礎⽂法はわかる • オブジェクト指向を使える • 簡単なスクリプトを書ける • 簡易フレームワーク習得 • ⾃分で簡単なアプリを作成できる ⾼度なプログラミング知識 • ⾃分で中規模アプリを作成できる • オブジェクト指向を設計可能 • フルスタックフレームワーク習得 • デザインパターン習得 • リファクタリング習得 • テスト習得 • 複数のプログラミング⾔語を習得 3ヶ⽉ 2年 達⼈プログラマ 中級者からの純粋レベルアップ プログラミング以外も得意 クラウドの普及で最近増加 5年 3年(中級者向けの⾼度なプログラミング知識習得をスキップ) ⼊⾨書完読。 基本レベルの演習を 全て解答可能

Slide 303

Slide 303 text

包丁をにぎらず本ばかり読む駆け出し料理⼈ • プログラミングの第⼀歩は本やトレーニングで問題ない • 本だけを読んで「分かった気になる」かもしれないが、実際に コードを書かないとプログラミングは⾝につかない • アプリケーションを作るレベル(脱初⼼者)になるまでは本ト レーニングの演習のようなお題をこなすことで基礎スキルを⾝ につけるのが⼿っ取り早い • 同じ演習でもいくつかの解答⽅法はある場合が多いので、いろ いろなテクニックを駆使して解いてみよう

Slide 304

Slide 304 text

やりたいことは書き始めてから考えよう • プログラミングは作りたいものを作ることで学べる • ただし適切なレベルの作りたいものがある⼈はごく少数 • 多くの個⼈プログラマは以下の3種類を作る • ウェブサービス <- おすすめ • デスクトップアプリ • 作業スクリプト • これらの利⽤法を学びながらなにか作りたいものを探すか、練 習がてら⼀般的なサービス(掲⽰板)を簡易模倣したり、仕事の 作業(エクセル操作など)をPythonで実装してみるとよいかも

Slide 305

Slide 305 text

おすすめ1: Flaskによる簡易ウェブサービスの作成 • Pythonの軽量Webフレームワーク • アクセスされるURLに処理を関数として結びつけることでウェ ブサービスを簡単に作ることができる • ウェブアプリは現在の開発の⼤きな割合になりつつあるので、 簡易ウェブサービスの作成経験は損にはならない ページ(HTML)作成の関数1 ページ(HTML)作成の関数2 ページ(HTML)作成の関数3 ページ(HTML)作成の関数4 フレームワーク ウェブサーバー機能 ブラウザ ページ要求 ページを返す 開発者ページ(HTML)作成のみを開発 他のサーバー処理は全てFlaskが担当

Slide 306

Slide 306 text

補⾜) HTML/CSS • ウェブページのマークアップ⾔語 • HTMLにウェブページの内容を書く。これをFlaskで動的に作成 する。たとえばお店サイトの商品ページをURLごとに作成 • CSSはHTML(ページ本体)にデザインを加える。 • フロントエンジニアやウェブデザイナーなどの専⾨家がいる領 域なので素⼈が有名サイトレベルのものを作ることは不可能 • 素⼈でウェブ作成したければ「Bootstrap」などの「初級者で もそこそこのページ」を作れるフレームワークを学ぶとよい

Slide 307

Slide 307 text

おすすめ2: Tkinterによるデスクトップアプリの作成 • ⽬に⾒えるものを作るので「プログラム初⼼者が楽しみながら 開発をしやすい」という学習メリットがある • アプリケーションを他の⼈にも利⽤してほしければ「バイナ リ」にしてから配布(⼿法は割愛) • 他にもGUI作成の外部ライブラリがあるので深⼊りするのであ れば、Tkinter以外の⾃分にあったライブラリを探すとよい GUIのカウンターアプリ アプリケーションの配布

Slide 308

Slide 308 text

補⾜) アプリからのデータベースの利⽤ • 状態を持つアプリケーション(ユーザーや商品などがある)は必ず データベースを使っている • Pythonや他の⾔語およびフレームワークには⼤事な情報を持たせ ずに、データベースを介して情報を読み書きする • フレームワーク依存の⾼度な利⽤法を学ぶまえにローレベルの利 ⽤法(SQLの直接呼び出し、ORマッピング)を体感しておくとよい Python DB (SQLite3など) Sqlite3モジュール SQLAlchemy

Slide 309

Slide 309 text

おすすめ3: 業務向けの作業スクリプト作成 • 以下の操作をPythonで実施して省⼒化。ウェブやGUI化してもOK • ディレクトリやファイル操作 • ExcelやCSV • Word • PDF • Eメール • 画像 • ウェブページのスクレープ • キーボードとマウス操作の⾃動化 • 英語ですが「Automate the Boring Stuff with Python」のウェブサ イト(無料)がおすすめ。オライリーから4000円ぐらいの邦訳本も でている

Slide 310

Slide 310 text

著者が興味でプログラムを書いた例 • 本トレーニングの8章の画像回収ツール相当のものをJavaで作 成(1番最初に作ったアプリ) • ゆっくり実況が好きだったので、⾳声合成ソフトのMacアプリ (Objective-C)とクラウド版(Python + C⾔語)を作成して公開 • 仕事での巨⼤なログの解析アプリケーション(C++とQt)。あく までも仕事ではなく趣味の⼀環で • 鉱物標本のラベルを作成するサイト • インフラ作業の⾃動化系(趣味から現在の本業へ)

Slide 311

Slide 311 text

⼊⾨者卒業に難しい知識はいらない • プログラミングの書籍やウェブ情報は簡単なものから難しいも のまで様々ある • あれもこれもと⼿を出さずに以下に絞って学ぶとよい • 薄い超初⼼者向けのプログラミング書籍を2-3冊を何度も読 む(内容を95%理解するまで) • テーマを絞って簡単なアプリを作成する • プログラミングで分からないことは検索をする

Slide 312

Slide 312 text

初級者卒業: 美しい設計を体と頭で覚える • このセクションで学ぶこと • スキルは「困ってからの設計変更」で向上 • 複雑さを減らすことに気を配ろう • クラスを徹底活⽤しよう • リファクタリング • テスト • デザインパターン • フルスタックフレームワーク: Django • 他のプログラミング⾔語を学んでみよう • 初級者卒業には⾼度な専⾨書が必要 SECTION 02

Slide 313

Slide 313 text

スキルは「困ってからの設計変更」で向上 • ⾼度なプログラミングスキルの基本は「巨⼤なコードを整理して、 バグを少なく拡張しやすくする」ことに尽きる • ⾼度なプログラミングスキルが役⽴つ場⾯ • 開発前の設計 • 増築/改造を繰り返したコードの整理 • ⼤規模な開発を効率よくおこなう • 初級者は深い経験が必要なことはできない(短時間では⾝につけに くい)ので、最初からよい設計をするための⼿法を学ぶのではなく、 「とりあえずコードを書きまくり、増築⽅式アプリをでかくしてい き、継ぎ接ぎがカオスになってからコード整理」して体で覚える • どのように設計しなおすと「構造がシンプルになるか」を考える

Slide 314

Slide 314 text

複雑さを減らすことに気を配ろう • プログラム複雑になるシナリオ • 関数やメソッドの呼び出しが深くなっている • 1つのデータが⾊々な箇所で読み書きされている • 機能追加をその場しのぎの継ぎ接ぎで加えた • 複雑なコードを設計変更して綺麗にするとスキルが向上 関数 関数 関数 関数 関数 関数 関数 関数 関数 関数 汚いコード例 (深い階層) 綺麗なコード例 (階層を浅くした)

Slide 315

Slide 315 text

クラスを徹底活⽤しよう • クラスには様々な機能がある • 処理や複数のデータをまとめられる(トレーニングで学んだ) • クラスにクラスをいれて複雑さをさらに集約できる • 継承により複数の似たクラスの実装をまとめられる • 多重継承でクラス内のメソッドを分離できる 共通処理のクラス 機 能 機 能 機 能 機 能 機 能 機 能 利⽤したいクラス 常に継承 必要な機能の クラスのみ継承 (ハリボテ) 呼び出し側 多重継承の利⽤例(REST APIをPythonラップするライブラリの作成などに便利)

Slide 316

Slide 316 text

リファクタリング • プログラム(関数やクラス、モジュールレベルなど)の挙動を変 えずにコードの品質をあげること • 専⾨書籍などで学んでもよいが、初級者は⾃分で試⾏錯誤しな がら設計変更するのがよい(痛いめに合って、それを頑張って解 決することが経験となる) • ライブラリで解決できる問題ではないか • 関数、クラス、モジュールの⼤きさは適切か • ループ処理はわかりやすいか • クラスの設計は正しいか • 中級者に近くなったら「教科書的な解答」も学習して覚える

Slide 317

Slide 317 text

テスト • プログラムが正常に動作するかをテストで確認 • 開発を終えてからテストをするのではなく、モジュールをテス トしながら開発していくことが望ましい • 習得するべきテスト • Printデバッグ • ユニットテスト • ツールを使ったテスト(サービスに⼤量の負荷を与えてみる、 Seleniumでブラウザ操作チェックなど)

Slide 318

Slide 318 text

デザインパターン • ⼤規模なコードを書くための設計パターン • クラスやモジュール間をどう接続して連携するのがよいかとい うベストプラクティス • 1つのシステムから構成される中規模以上のサービス開発で設 計段階で導⼊するとよい • ⾃分で設計したりリファクタリングした経験が積み重なってい ないと机上の理論にすぎないので、数年のプログラミングの経 験を積んでから学べばよい(超有名なシングルトンなど10個以 下のパターンをピックアップして学習してもよい)

Slide 319

Slide 319 text

フルスタックフレームワーク: Django⼊⾨ • メジャーなPythonのフルスタックWebフレームワーク • Ruby⾔語でいうところのRailsに近い • Flaskと異なりウェブサービスに必要なほとんど全ての機能が フレームワークに搭載されているので「フルスタック」と呼ば れる • Flaskで作成した動的なウェブサイトの作り込み(DBとの連携や HTML⽣成)あたりをDjangoのモデル(DB)やテンプレート機能 (Jinja)で作り直すとフルスタックのメリットがわかる

Slide 320

Slide 320 text

他のプログラミング⾔語の学習 • おすすめはJavaScript。ウェブ開発で他に選択肢がない場合が多い ため • 次点はGo(モダンな開発によい)か、Java(まだ需要が多くてオブ ジェクト指向の学習によい) • 他にはやりたい仕事向きの⾔語(SwiftやC#、PHPなど) • 以下は3⾔語め以降でよいと思う • Pythonと利⽤⽬的が近い他のスクリプト⾔語(Ruby/Perlなど) • 学習難易度の⾼いC/C++や関数型の⾔語。(これらを必要とする 仕事についていないと利⽤する機会は少ない) • 汎⽤的でない⾔語。Rなど

Slide 321

Slide 321 text

初級者卒業には⾼度な専⾨書が必要 • 3000円 - 4000円あたりの書籍は⼊⾨書に⽐べると専⾨的 • 中級者向けの書籍は⼊⾨書よりも扱う範囲が広いので「まんべん なく深い」のではなく「いくつかのトピックが深い」傾向がある • 2000円台の本とは違ってプログラミングの⾼度な専⾨書籍の半分 以上の知識は必須ではないのですぐには役⽴てられない • 詰め込みではなく継続的に書籍を読み続けてスキルの⼟壌を耕し ておくとよい • コードを書き続けているうちに利⽤するべき場⾯に遭遇する場合 がある。⼟壌が整っていると難しい状況でもよい判断ができる

Slide 322

Slide 322 text

中級者卒業: 開発はプログラミング以外にもある • このセクションで学ぶこと • 巨⼈の肩の上に⽴つ凡⼈ > プログラミングだけを知る達⼈ • パーツごとに別々に作成するのが今のトレンド • パーツ間の連携⽅法 • 軽量な実⾏基盤であるコンテナ • 既存ミドルウェアをアプリケーションで使う • サービスの監視 • APIフレームワーク: FastAPI • リバースプロキシーのURL設計例 • CI/CDによる省⼒化と安定性の確保 • DevOps環境の構築と著者が採⽤している環境の紹介 SECTION 03

Slide 323

Slide 323 text

開発巨⼈の肩の上に⽴つ凡⼈ > プログラミングだけを知る達⼈ • 開発スキルはプログラミングスキル以外も含む • たとえばデータベースの利⽤のように「プログラムに既存のサー ビスを使わせる」ことでシステム開発を効率化できる • 全てをコードで作ると開発も保守も⼤変になる Linuxの知識 DBの知識 コンテナの知識 その他、多数 プログラミングスキル プログラミングスキル 開発の達⼈ プログラミングの達⼈ インフラの知識

Slide 324

Slide 324 text

パーツごとに別々に作成するのが今のトレンド • モノリシックなサービス: 1つの構成要素からなるアプリ • マイクロサービス: 複数の構成要素からなるアプリ • 2010年以降はマイクロサービスが⼤幅に普及 • ウェブサービス以外でもマイクロサービスの設計は使える。た とえばプライベート基盤を提供するNutanixの製品もコンポー ネントごとに独⽴したマイクロサービスな設計となっている モジュールC モジュールD (過去遺産) モジュールA モジュールB アプリケーション モノリシックな設計 サービスA (新規でPython製) サービスB (MongoDBなど) サービスC (Go製の過去遺産) サービスD (新規でJava製) APIで連携 マイクロサービスアーキテクチャ 達⼈プログラマ(上級) でないと設計できない 万能プログラマ(上級) でないと設計できない

Slide 325

Slide 325 text

パーツ間の連携⽅法 • リバースプロキシー: URLによるアクセス先の振り分け。 HTTPSオフロードやキャッシュ機能などもある • メッセージング: サービス間のやりとりのための仕組み(割愛) Web Server API Server Image Server /api/...へのアクセス /images/...へのアクセス /...へのアクセス リバースプロキシー 内部IPで通信 外部IP(1つ) アプリケーション全体 サービスA サービスB サービスC

Slide 326

Slide 326 text

軽量な実⾏基盤であるコンテナ • コンテナはサービスを独⽴させるのに便利なツール • 軽量ですぐに起動できて、どこでも動かせる擬似OS環境 • 複数のコンテナを1つのホスト上で動かしたり、多数のコンテ ナを複数ホストで構成されるクラスタ上で動かせる 本番ホスト Docker コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ ホスト1 Docker ホスト2 Docker クラスタ(Kubernetesなど) コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ 開発ホスト Docker コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ 他環境(別IPなど)に すぐに移せる マイクロサービスの各サービスを コンテナとして動かすことが多い

Slide 327

Slide 327 text

既存ミドルウェアをアプリケーションで使う • 以下は筆者がマイクロサービス開発よく使うサービス。⾃作す るのではなくサービスを使う前提でプログラムを書くと簡単 • NGINX • リバースプロキシー • ウェブサーバー(静的なファイルの配布) • MongoDB: ドキュメント指向データベース。プログラムが使う データ構造(辞書型。JSON)をそのまま格納したり検索可能 • Redis: KVSと呼ばれる⾼速なキャッシュ • オブジェクトストレージ: ファイルやイメージをURL形式で保 存する。著者はローカルではMinioを利⽤

Slide 328

Slide 328 text

サービスの監視 • 複雑に構成されるサービス群は監視が必要。以下は著者の構成 • Loki: システムログの集約(次世代のシスログサーバー) • Prometheus: メトリックの集約(性能や稼働状況などの指標) • AlertManager: しきい値を超えた際に管理者にメール通知 • Grafana: 集約したログやメトリックを表⽰、検索 ホスト Docker (Loki Logging Driver) コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ コン テナ 全コンテナの ログ 全コンテナの メトリック ウェブで表⽰

Slide 329

Slide 329 text

ミドルウェアを利⽤する際のポイント • 完璧なものを⽬指すのではなく規模にあったコスパで選ぶ • 「構築/運⽤コストと覚えること」は少ないほうがいい • たとえば著者はログ監視にElasticsearch/Kibana/Fluentdという 構成ではなく、Grafanaを使っているのでLokiを採⽤している • 状態をホストやコンテナではなく共有されるミドルウェアに任せる • たとえばローカルキャッシュではなくRedisを使う • たとえば画像やファイルの管理はローカルではなくオブジェクト ストレージを利⽤する • これを守らないとパーツへの依存性が発⽣して、構成変更(ノード 数を増やすなど)の難易度が跳ね上がる

Slide 330

Slide 330 text

マイクロサービスのウェブアプリの構成例 Node (SPA担当) ウェブサーバー (静的ファイル配信) Node (JS等のビルド) APIサーバー 1 APIサーバー N Minio(画像) JS CSS 画像 gulp アプリサーバー (HTML⽣成) 内部API呼び出し 画像の 取得/保存 画像取得 外部API呼び出し SPAのページへの アクセス 静的ファイル 取得 ページ アクセス Redis MongoDB キャッシュ セッション管理 データ管理 Grafana Loki Prometheus Exporters 管理/監視系 AlertManager Browser ページ アクセス セッション管理 (ログイン状態で表⽰切り替え) JavaScript API呼び出し リバースプロキシ + ⼀部のキャッシュ 信頼できないゾーン 信頼できるゾーン コンテンツビルダー (MarkDown -> JSON) ページデータ 作成 ... ⾃作ツール群

Slide 331

Slide 331 text

APIフレームワーク: FastAPI⼊⾨ • フルスタックフレームワークはマイクロサービス向きでない • Flaskのような軽量フレームワークを主体とした⼩型のAPIサー バー群を⽤途ごとに作成する • 著者はPython製のAPI向けで⾼速なFastAPIを利⽤している Docker (Logging-Driver) ミドルウェア • 例外処理 • Prometheus Exporter APIの実装 他のAPIサーバー Appサーバーのみ他を参照 Redis MongoDB キャッシュ セッション管理 データ管理 バルクアクセス Prometheus Loki APIアクセス

Slide 332

Slide 332 text

リバースプロキシーのURL設計例 • リバースプロキシーでプレフィックス(前⽅)基準でURLごとに処理変更 • ウェブ(APPサーバー)の懸念事項 • キャッシュ対象(全ユーザー共通)と⾮対象(ユーザーごと)ページがある • 同⼀ドメインで多⾔語対応させることが現在は多い(URLで⾔語区別) • APIの懸念事項 • 複数のAPIサーバーが存在している。APIのバージョン管理も必要 • パブリックAPI(外から)とプライベートAPI(中のみ)がある • URLの設計例 • 静的ファイル: /static/... • ウェブ: /<キャッシュの有無>/<⾔語>/... • API: /api///<バージョン>/... • オブジェクトストレージ: /images/...

Slide 333

Slide 333 text

CI/CDによる省⼒化と安定性の確保 • リポジトリにコードをPushしたら複雑なマイクロサービスアプ リを全⾃動でビルド。⼈間よりスクリプトのほうが信頼できる • ビルドしたコード(イメージ)を起動して全⾃動でテストを実施 • テストにパスしたらステージング環境にのせて、管理者が最終 チェックしてから本番環境に切り替える 著者が採⽤しているDockerアプリの CI/CDの流れ。 Kubernetes利⽤時はDocker-Composeでは なく実際にK8sを利⽤する。 宣伝!! 詳しくは私のDocker本にあります

Slide 334

Slide 334 text

DevOps環境の構築 • DevOpsはバズワード • DevOpsの著者なりの解釈は「CI/CDを中⼼として、(クラウド より上の世界での)インフラを維持しつつサービスを開発/更新 公開し続ける技術」 • ⼩規模なDevOps環境はある程度の知識と試⾏錯誤は必要だが、 個⼈レベルで構築可能 • 上級者向けの個々の技術を1つ1つ深堀りする前に、とりあえず 全体像を理解するために浅知恵でよいので作って動かすべき • 開発と運⽤にDevOpsを採⽤するのであれば、チームの半分以 上は全体像を掴んでいること • 少数精鋭チームから導⼊して横展開することを推奨

Slide 335

Slide 335 text

著者が採⽤しているDocker中⼼のDevOps環境 Dockerレベルの運⽤ Compose (開発サーバー) Dockerfile DockerHub (Pull) Compose (本番環境) Compose App Infra Ansible ホストレベルの運⽤ Python GitHub (Code Push) App Infra App Compose (⾃分のPC) GitHub (Code Pull) Dockerfile Jenkins (ビルドからデプロイまで) DockerHub (Push) Jenkinsのトリガー GitHub (ドキュメント等) メトリックとログ 規模が⼤きくなると ビルドからデプロイは Composeではなく Kubernetesに切り替え

Slide 336

Slide 336 text

駆け出し編: インフラエンジニアという道 • このセクションで学ぶこと • ウェブ業界はレッドオーシャン • ITインフラ業界は敷居が⾼いが安定している • 代表的なインフラエンジニアの仕事 • 本当の基盤(電気、空調、ラック) • ネットワーク系 • サーバーとストレージの世界 • パブリッククラウドとプライベートクラウド • 構成管理ツール • インフラの⾃動化 • 専⾨性や資格について SECTION 04

Slide 337

Slide 337 text

ウェブ業界はレッドオーシャン • 低スキルから中堅まで⼈材が豊富 • ⾒た⽬にわかりやすい仕事なので新⼈が多い • ⼤量のプログラミングスクール卒業⽣ • ⼀部の優秀なエンジニアや好業績の会社を除けば、求められる 技量のわりに待遇がITインフラ業界より低いことが多い • 技術のサイクルが速いのでずっと(⼤量に)勉強し続けないとい けない

Slide 338

Slide 338 text

ITインフラ業界は敷居が⾼いが安定している • 専⾨知識が要求されるため学習が必要 • ウェブ業界に⽐べると⼈員供給が少ないので需要が多め(?) • ウェブ業界に⽐べるとコア技術の変遷が⼩さい(ウェブ開発スタ イルは⼤きく変わっても、ネットワークの仕組みやLinuxの根 幹は簡単には変わらない) • 以後で著者が経験したインフラエンジニアとしての仕事内容を 列挙していく • 仕事が⾯⽩そうと感じたなら、ウェブ屋よりもインフラ屋を駆 け出しエンジニアは⽬指したほうが仕事と給料は安定する可能 性が⾼いかも

Slide 339

Slide 339 text

サーバーラック利⽤法の設計 • コアとなるIT機器はサーバーラックに搭載するのが⼀般的 • インフラエンジニア以外がこれらを⾒かけることは珍しい • サーバーラックの利⽤法の設計に必要なステップ 1. ネットワークとサーバーの論理設計 -> 物理設計 2. 必要な電⼒と発⽣する熱量の設計 3. 物理⼯事(ラック設置、電⼒供給、ACの設置) • 配線が多い場合はネットワーク機器をToR(Top of Rack)ではな くMoR(Middle of Rack)にするとケーブルを分散させやすい。 必ずケーブルガイドを使って配線を左右に逃がすこと • スイッチのポート(ケーブルがささる側)はラックサーバーにさ すものは背⾯側の機種を選ぶ。それ以外は前⾯側にする

Slide 340

Slide 340 text

サーバーラック利⽤法の設計例 ... 1G L2 Switch 1G L2 Switch 2U/4Node Servers 2U/4Node Servers ... 2U/4Node Servers 2U/4Node Servers ... Core L3 Switch Core L3 Switch Data Stack Data Stack ... Voice Stack (PoE) Voice Stack (PoE) ... ... Infra Servers 10G/40G L3 Switch 10G/40G L3 Switch 1G L2 Switch 1G L2 Switch 2U/4Node Servers 2U/4Node Servers ... 2U/4Node Servers 2U/4Node Servers ... Firewall Firewall ONU ONU Career1 Career2 Internet Wifi Stack (PoE) Wifi Stack (PoE) Wifi Controller Wifi Controller PCs on Desk IP Phones on Desk Meeting Systems APs 終端ラック(1,2): ラック間の接続その他 ラック(1-N): ワークロード⽤ 10G/40G L3 Switch 10G/40G L3 Switch バックボーン接続(冗⻑化) ラック内接続(冗⻑化) ラック内接続(冗⻑化) ラック内接続(冗⻑化) 床下配線 冗⻑化 オフィスエリア 天井配線

Slide 341

Slide 341 text

電⼒と空調の設計 • IT基盤を動かすより低いレイヤーの基盤 • 電⼒: サーバーは200kVAでのPSU冗⻑化が⼀般的(kVA≒KW) • ラックあたりの電⼒量: ⼀般的には4kVA - 20kVA程度 • 重要な環境は電気系統と空調も冗⻑化すること • コールドアイル(冷たい空気)の通路をラック前⾯に設置し、 ホットアイル(排熱による暖かい空気)をラック背⾯に設置 • 排出熱量に猶予をもたせること。空調が冷やせる限度を越える と冷⾵が送れずに急激にオーバーヒートをおこす。夏は室外機 (排熱)も⾼温になるので冷却性能が落ちる点に注意 • ITインフラとは異なる領域なので、その専⾨家(電気、空調等) と相談しながら要件にあった設計をする(⼿伝う)必要がある

Slide 342

Slide 342 text

電⼒と空調の設計例 Front Front コールド アイル 室内機 室外機 室外機 室内機 ホット アイル 発⽣する熱量と電気使⽤量、価格 あたりから適切な機器を選定する。 弱いよりは強いほうがだいぶマシ。 稼働後の増強は難しい(⾦と時間がかかる) 排熱環境に注意 排熱できない = 冷やせない 200V 100V 200V 100V 200V 100V 200V 100V 200Vの電⼒使⽤量の⾒積もりが必要。 100Vを⼤量に使⽤する場合は⼤容量の 配電が可能な200Vを使うことを検討。 ⽇本では100Vもないと不便 100V配電盤 200V配電盤 ... PDU(電源タップ)は 背⾯側の左右が基本

Slide 343

Slide 343 text

L2/L3ネットワークの設計 • L2ネットワーク: 同じネットワーク内の通信 • L3ネットワーク: ネットワーク間をまたぐ通信 • L3スイッチ: ネットワークの中⼼なる機器。L2/L3の両対応 • 設計のコツ: 利⽤⽤途から正しいサイジングをして、L2の物理 範囲を狭めて、アドレス集約を徹底してルーティングを簡単に する。責任分界点には社内であってもFirewallを設置する • 重要箇所は全て冗⻑化することが必須 • ネットワークを使う側のサーバーエンジニアのレベルは⾊々 • ネットワークに詳しくない⼈が使う⼤きなVLAN(Native) • 詳しい⼈が複雑なことをできる複数の⼩さなVLAN • パブリックIPやDMZの設定は素⼈にはやらせないかガイド

Slide 344

Slide 344 text

L2/L3ネットワークの設計例 Goto Corp, External Office 10.4.0.0/16 Office Core Office Infra Office Data 1 Office Voice 1 Office Wifi 1 External Firewall VRF Routing + Internal Firewall Goto Corp, External Site B Small Sites Big VLAN Small VLANs Site A External Firewall Lab1 10.5.0.0/16 Lab2 10.6.0.0/16 10.4.0.0/23 10.4.100.0/24 10.4.101.0/24 10.4.2.0/23 10.4.4.0/22 10.4.8.0/22 10.4.12.0/22 10.5.0.0/17 10.5.128.0/20 ⽀社A 10.4.0.0/14 本社: 10.0.0.0/8 (全⽀社は内部にある) ... ⽀社B ⽀社C ... サイト間VPN(冗⻑化) サイト間VPN(冗⻑化) サイト間VPN(冗⻑化) 必要に応じて 拠点間も直接 接続をする 極論すると全てスタティックルートの設定で まかなえるぐらい経路を集約しまくること。 最初に正しく設計してないと集約できなくなる Internet 10.0.0.0/8 10.4.0.0/14 0.0.0.0/0 Corp 0.0.0.0/0 10.6.0.0/16 全ての通信を 通す必要はない

Slide 345

Slide 345 text

名前解決の設計 • ドメイン名をIPアドレスに変換する仕組み • アプリケーションを様々な環境で動かすための必須条件なので、 クラウドが⼀般化した今では昔よりも重きがおかれる • 完全にランダム割り振られるDHCPや固定IPの使⽤ではなく、 「IPAM(IP Address Management)」で賢くDHCPを使うこと • クラウドにはIPAMが搭載されることが多い • 存在しない場合には作る(Linux or Windows) • アプリケーションを構成するノード間は名前解決で連携できる ように実装しておくこと。接続先を固定IPではなく解決可能な ドメイン名にしておく。⾃分⾃⾝のIPもDHCPでIPAMから得る

Slide 346

Slide 346 text

名前解決の設計例 プライベート クラウド パブリック クラウド コンテナ基盤 VLAN 172.30.0.0/16 VPC 172.31.0.0/16 コンテナネットワーク 172.32.0.0/16 Backend VM Front VM Reverse Proxy etc Backend Instance Front Instance CDN etc Backend Container Front Container Load Balance r etc IPAM + DHCP(管理コンソール) IPAM + DHCP(管理コンソール) YAMLでの定義 ネットワークアドレスに依存せずサービス 構成ノード間で会話できる必要がある。 IPではなく名前で相⼿を指定する。 フロントも直接外に出さないほうがよい Global IP DNS 公開⽤パブリックIPとサービスのドメイン名の結びつけ

Slide 347

Slide 347 text

Wifiの設計 • 物理設計 • L2ネットワークへの接続と給電(PoEが多い) • アクセスポイントがカバーできる範囲の調査 • 設置ポイントと⼈⼯密度、衝突しない周波数の調整など • 認証システム • 物理的に離れた多数のAPをどう⼀元管理するか • 数⼗台以上のAPは個別ではなくコントローラーに設定を集 約するのが基本

Slide 348

Slide 348 text

セキュリティの設計 • Firewall • 社外から社内だけでなく、社内から社外への通信も対象 • 社内の異なるグループ間もFirewallを通すべき • VPN • サイト間接続 • PCからの接続 • ActiveDirectory(AD) • セキュリティ系の機能はADに強く依存しているものが多い。 また、ADを安定稼働させるための専⾨知識が必要 • FirewallやActiveDirectoryも壊れることがあるので、冗⻑化と 壊れた際にきちんとシステムが動き続けるかの検証が必須

Slide 349

Slide 349 text

クラウド間接続の設計 • 接続⽅式 • VPN • 専⽤線(ダイレクトコネクト): ⾼額 • アドレスレンジを「/16」程度で分離しておかないとルーティ ングができなくなる(パブリッククラウドには従来のL2/L3の ルールが適⽤されないことが多いので注意) • アプリのレイヤーを「グループレベルでクラウド間で動く」こ とを前提に構築しておく必要がある。クラウド間やリージョン 間は遅延が⼤きいので「アプリはクラウドでDBはオンプレ」 などの構成はNG

Slide 350

Slide 350 text

クラウド間接続の設計例 172.31.0.0/16 Public Cloud (AWS) 172.30.0.0/16 Public Cloud (Azure) 172.31.1.0/24 172.31.2.0/24 172.31.3.0/24 VM VM VM VM VM 172.30.1.0/24 172.30.2.0/24 172.30.3.0/24 VM VM VM VM VM Firewall Appliance 1 Firewall Appliance 2 L3 Switch (Gateway) 172.16.0.0/16 Private Cloud (Nutanix) 172.16.1.0/24 172.16.2.0/24 172.16.3.0/24 VM VM VM VM VM VPN VPN 0.0.0.0/0 via L3 Switch 172.31.0.0/16 via L3 FW1 172.30.0.0/16 via L3 FW2 172.16.0.0/16 via L3 Switch 172.31.0.0/16 via AWS 172.16.0.0/16 via FW1 172.30.0.0/16 via Azure 172.16.0.0/16 via FW2 VLAN X VLAN Y ⽮印の通信経路の設定はスタティック ルートか⾃動学習(BGPとOSPFなど)で与える

Slide 351

Slide 351 text

物理サーバーの設計 • 今は「仮想化」を前提に考える。ベアメタルは特殊な状況のみ • 基盤導⼊後に拡張することを前提に考えておく(ネットワークのア ドレス空間の⼤きさ、物理スペース、電⼒、エンジニアの物理と 設定作業のコストなど) • ミドルレンジより性能が上がっても落ちても「処理能⼒あたりの 購⼊価格」が⾼く傾向、台数が増えると維持コストが増える • 物理より上の価格(ライセンス代など)が⾼ければ、⾼いサーバーで コストを圧縮したほうがよい。普通はコスパでミドルレンジを選 び、予算がなければローエンドを選ぶ。ミッションクリティカル 環境はハイエンド • ワークロード(負荷)に応じたサイジング(台数や構成決定)をする

Slide 352

Slide 352 text

物理サーバーの設計例 ハイパー バイザー ハイパー バイザー 仮想化基盤のクラスタ 物理サーバー 物理サーバー SAN Switch San Switch Network Switch Network Switch 上流 ネットワーク ストレージ ストレージ VM VM VM VM VM VM VM VM VM VM VM VM VM VM ... 上流 ネットワーク 物理サーバー 物理サーバー Network Switch Network Switch プライベートクラウド VM VM VM VM VM VM マネージドDB その他機能 レガシーな「3Tier」と呼ばれる構成 構築と拡張が難しい 現在主流になりつつあるプライベートクラウド⽅式 全般的に3Tierよりも簡単(個⼈で作る⼈もいるぐらい) ... コン テナ コン テナ コン テナ コン テナ

Slide 353

Slide 353 text

障害と保守 • 機械は壊れるもの • ソフトウェアにはバグがある • エンジニアは知らないことが多いし間違えることも多い • アプリでバグがおきるようにインフラにも障害が発⽣する • 障害に対応するように以下が必要 • ハードウェアの冗⻑化(2つ構成で組み、1つ壊れても動き続 ける) • 冗⻑化と故障を想定した設計のソフトウェア • 障害発⽣時の対処法(知識かマニュアル) • 保守契約(ハード交換や障害復旧の⼿伝い) • ハードやソフトに詳しくなりたいならきちんとした保守(技術サ ポート)の仕事から始めるとよいかも。著者も経験者

Slide 354

Slide 354 text

ストレージの設計 • ⼤前提として以下の3種類を区別する • サーバー内のSSD。⾼速だが死ぬと終わるし融通が利かない • NAS(共有ファイルサーバー, NFS/SMB) • 外部ブロックストレージ(SCSI, iSCSI) • サーバー冗⻑化には外部ストレージが必要なことが多い • SCSI(SAN)は⼤企業向けだが、iSCSIは⼩規模向け • 環境の引っ越しをしにくくなる第⼀要因はストレージ(DB含む) なので最初から移⾏プランを考えておくのがよい • ストレージとSANの障害はインフラ障害で最もダメージが⼤き いのでデリケートな箇所。基盤のパフォーマンスのボトルネッ クにもなりがち。バックアップ必須 • ストレージとSANのエンジニアは⽐較的レアキャラ

Slide 355

Slide 355 text

データベースの設計 • 2種類のDBエンジニア • アプリより: アプリが使いやすいテーブルの設計 • インフラより: 複雑なクエリーや、冗⻑化やバックアップ • 純粋な「データベースだけをやるエンジニア」は少ないのでア プリであれば開発(アプリ側がDBをどう使うか)を先に学び、イ ンフラであればDBが動くサーバーレベルを先に習得するのが 個⼈的推奨 • SQL⾃体に詳しくなる(知っていてあたりまえ)というより、運 ⽤(クローンやバックアップ、スケールアップ)周りの知識が特 に求められる • DBの障害(システム全停⽌)でもデータは絶対になくさないこと

Slide 356

Slide 356 text

バックアップの設計 • 冗⻑化(Raidなど)はバックアップではない • 仮想化のスナップショットもバックアップではない • 集約箇所やシステムごとなくなる可能性を考慮しておくこと • バックアップのレベル • ファイルレベル(以下のどれかの付属機能なことが多い) • OSレベル • 仮想環境レベル • ストレージレベル • バックアップ取得時間とバックアップからの復旧時間もだいじ な指標なので、検証環境で実測しておくこと(バックアップはあ るけど戻しに2⽇かかります。などということも。。。)

Slide 357

Slide 357 text

パブリッククラウドの設計 • 「とりあえずOSを使いたい」という状況でインフラの構築と運 ⽤が不要で簡単に使えるというメリットがある • 動かすサービスをクラウドに適した設計に変更し、インスタン スを使い捨て(スケール含む)にできることが望ましい • マネージドサービスを使うことで「DBなどの⼿がかかるマシ ンのおもり」をへらすことができる • インターネットに近いのでウェブサービスに強い • 「従来の業務⽤VMを24時間稼働させる」⽬的でパブリックク ラウドを使うと割⾼になることが多いので注意が必要 • 注意:「特定パブリッククラウドのシステムにだけ強い」という エンジニアは⻑期的には不安定だと思われる。クラウドにも役 ⽴つベーシックなLinuxと開発スキルにも投資すべきかも

Slide 358

Slide 358 text

パブリッククラウドの設計例 パブリッククラウド基盤 インスタンス (ウェブサーバー) マネージドDB インスタンス (アプリサーバー) バックアップ インスタンス (アプリサーバー) インスタンス (ウェブサーバー) CDN(Cache) + HTTPS Offload ドメイン名 RDS S3 EC2 Cloud Front Route53 インターネット ユーザー 名前解決 アクセス サービス名にはAWSを使ったが、基本機能程度の利⽤であれば 主要クラウドであれば似たサービスを持っている。 これ以外にもサーバーレスや各クラウド独特の機能は多い。 初⼼者は汎⽤(どのクラウドでも使える)機能から学ぼう プライベートネットワーク 広いエリアからの⼤量のアクセスに 強いが、特定の拠点(会社など)からの ⼤量のアクセスには弱い。 ⾃社ファイルサーバーなどはクラウド ではなく拠点内に置くのが⼀般的。

Slide 359

Slide 359 text

プライベートクラウドの設計 • パブリッククラウド相当のものを社内に構築する • レガシーな3Tier構成やOpenStack(難しいので専任エンジニア が多数必要)より、NutanixのHCIなどの構築と運⽤が簡単なも のがよい • 展開する台数が多い場合は仮想マシン(インスタンス)単価で考 えると、パブリッククラウドより安価な傾向(1/2 - 2/3程度) • 初期投資が必要なので⼩規模な場合はパブリッククラウドより も⾼額になる傾向 • 24時間稼働のエンタープライズアプリや、⾼トラフィックが必 要なVDI、⾃由な操作が求められる開発基盤などに適している • 注意: プライベートクラウドはパブリッククラウドに⽐べると 設計と運⽤がきちんとできるインフラエンジニアが必要

Slide 360

Slide 360 text

プライベートクラウドの設計例 物理基盤(電気、ネットワーク) VM VM VM VM VM VM VM VM VM VM VM VM VM VM VM VM VDIサービス (管理された⼤量のユーザーマシン) ⼤量の社内通信 (40G以上の⾼速なLAN) ⾃社設備(オフィス、データセンター) VM VM VM エンタープライズ アプリケーション (会社の重要システム) DB バック アップ プライベートクラウド基盤 ⼤量のユーザー(社員) 社内通信 秘匿データ VM VM VM VM インターネット Firewall セキュリティ管理 Firewall セキュリティ管理 VPN 社外の ユーザー (社員)

Slide 361

Slide 361 text

構成管理ツール • 主にサーバーレベルでのインフラ構築/変更作業は「構成管理 ツール(Ansibleなど)」を使うことで省⼒化できる • 定義した構成にサーバーを⾃動設定(初期構築/変更)してくれる サーバーA サーバーB サーバーC 構成ファイル (Yamlで定義) Ansibleを実⾏ Ansibleが⾃動設定 必ず構成管理ツールで 全ての設定をしないと いけないわけではない 著者の利⽤例 • 構成管理ツール: Dockerホスト やK8s環境の構築(⼟台) • コンテナ: アプリケーションの 構築

Slide 362

Slide 362 text

インフラの⾃動化(1) • ITインフラの仕事には定型業務が多い • 新規ネットワークを作成した際の機器の設定変更 • 仮想マシンを作成する際の設定作業 • マシンやログの監視とアラートの作成 • 決まりきったことを毎回⼈間がやるのではなくプログラムに実 ⾏させることで労⼒削減ができる • 定形作業(⼿続きの流れが明確)以外は⾃動化できない • システム開発には「開発とインフラの両⽅の知識」が必要 ⼈海戦術の廃⽌ プログラム ITインフラ 操作省⼒化 ⾃動実⾏(定期/イベント駆動)

Slide 363

Slide 363 text

インフラの⾃動化(2) • 管理者が増えると作業が遅くなる。マシン展開の例 1. ネットワークエンジニアが場所とアドレスを決める 2. セキュリティエンジニアがポリシーを設定 3. サーバーエンジニアがインスタンスを作成 4. アプリエンジニアが環境をもらえる 5. 監視員がリソース利⽤状況をチェックして使いすぎを警戒 • ⾃動化された例。インスタンス構成のプラン化と⾃動作成 1. アプリエンジニアが必要なインスタンスの種類を選ぶ 2. システムが機械的にインスタンスを作成 3. アプリエンジニアが環境をもらえる 4. システムがクオーターを超えた利⽤やアイドルを検知した らユーザーと管理者に通達

Slide 364

Slide 364 text

インフラの⾃動化の構築例 VM VM VM VM 基盤構築アプライアンス クラウド基盤 (Nutanix) Foundation VMs 基盤のイメージング 物理ネットワーク設定 基盤の初期設定 (論理ネットワーク等) 仮想マシン管理 (クラウドレベル) 仮想マシン設定 (OSレベル。Ansible) Nginx(Reverse Proxy) + Node(SPA) DB (基盤情報) 物理電源操作 (Power-on/off) ベアメタルサーバーへの クラウド基盤インストール REST API IPMI, SSH SSH, Ansible REST API ⾃動化の利⽤者 L3物理 Switch 物理ネットワークの結線 マイクロサービス設計の ブラウザアプリ SSH, API SSHにはPythonのParamikoを利⽤ するのがおすすめ。 ローカルコマンドと同じ感覚で リモートでのコマンド発⾏が可能 ブラウザGUI 仮想マシンレベル の⾃動化 基盤レベル の⾃動化 ネットワークレベル の⾃動化 Docker (VM設定後)

Slide 365

Slide 365 text

インフラのおかね • 買う価格: 物理機器やライセンスなどのコスト。性能と安定性及び 価格を考慮して構成を決める • 維持する価格: 買った後に維持するコスト。⼈件費や保守費。複雑 なシステムだと⾼くなる • 「常に⾼機能/⾼性能であればいいわけではない」ことに注意。た とえば画像編集の素⼈は⾼いお⾦を払ってPhotoshopを買うよりも 安いiPhoneアプリのほうがうまく使えるのと同じ。必要になって からPhotoshopを買えばいい。必要な機能を⾒極めて「可能な限り シンプルなものを選ぶ」ことを⼼がける • オープンソース vs ベンダー製品: オープンソースは素晴らしいが、 それを採⽤することによる「構築コスト、運⽤コストの増加、サ ポートを得ることが難しい」点を懸念すること。全てのオープン ソースが著名なオープンソース相当のレベルと思わないこと

Slide 366

Slide 366 text

開発やインフラの専⾨性を変えることについて • キャリア的に袋⼩路に陥ったと思ったら「今の⾃分が得意なこと」 から「半歩だけ外(完全に別領域ではない)」に出てみる • 著者の場合はデータセンターというカテゴリで「ネットワークエン ジニア(4年) -> サーバー仮想化エンジニア(4年)」とキャリアチェン ジし、クラウドという観点で「インフラエンジニア(合計8年) -> DevOpsエンジニア(現在1年め)」とキャリアチェンジしている • 正しいタイミングで正しい場所に移れるように⾃分が関わるIT技術 全般についてはエキスパートレベルではなくとも「素⼈ではない」 状態にしておくのが⼤事 • 指標として業界の最⾼峰と呼ばれる⼈達と会話して「なんか違う な」「⾃分のほうができる(たいていは勘違い)」と感じたら少し別 の領域へ移ることも検討する

Slide 367

Slide 367 text

IT系の資格について • IT資格は特定領域を包括的に勉強するには役⽴つ(投資的価値) • 資格を取るだけでは本当のエキスパートにはなれない。たとえば 著者が社会⼈4年⽬のときに「Cisco CCIE」「RedHat RHCE」 「VMWare VCAP」「Oracle Java Gold」と広いエリアの⾼ランク の資格を持っていた。知識はあったが技術⼒評価では社内の最下 位職位の下位20%程度。知識と技術⼒は別ものと割り切ること • 戦略的に適切なタイミングで転職やポジションの変更をおこなう ことで机上の知識を現場スキルに落とし込める • 英語ができると国内でもキャリアの選択肢が増えて、ライバルが ⼤幅に減るので、個⼈的には既にプロ以上のレベルの⼈はIT系より も英語の勉強のコスパのほうがはよいかもしれないと思う

Slide 368

Slide 368 text

歴史編: 開発とインフラの技術変遷 • このセクションで学ぶこと • おおまかなインフラの歴史 • おおまかな開発の歴史 • ペット vs 家畜 • クラウドの抽象化 • トレンドを読むことで将来に備える • 終わりに SECTION 05

Slide 369

Slide 369 text

おおまかなインフラ基盤の歴史 • - 2005ベアメタル • 全OSを直接ハードにインストール • 2000 - : サーバー仮想化(3Tier) • ハード上のハイパーバイザーに複数のOSをインストール • 2010年までは主流だったが構築と維持コストが低いパブリック/プラ イベートクラウドに置き換えられることが現在は多い • 2010 - : パブリッククラウド • 開放されているコンピュート資源をお⾦を払って借りる • ⾃分で構築しないのでメンテナンスコストが下がる • 2015 - : プライベートクラウド • 構築と維持が難しいサーバー仮想化を簡単に実現できる • パブリッククラウド相当のものを⾃組織のために構築する • 2020 - : ハイブリットクラウド • 複数のパブリッククラウドとプライベートクラウドのミックス構成

Slide 370

Slide 370 text

おおまかなインフラ基盤の歴史(図) HW HW HW OS OS OS HW HW HW OS サーバー仮想化 ストレージ OS OS OS OS OS OS OS HW HW HW OS OS OS OS Managed Services SAN HW HW HW OS OS OS OS Managed Services ベアメタル 2000 ~ 2010 ~ 2015 ~ 2020 ~ サーバー仮想化 クラウド 2020 ~ パブリック プライベート ハイブリット OS OS OS OS HW HW HW OS OS OS ハイブリット 2020 ~ ハイブリット

Slide 371

Slide 371 text

おおまかな開発⼿法の歴史 • - 2000: 開発の対象はデスクトップアプリ中⼼ • Javaによるエンタープライズ向けサービスの開発など • 2000 - 2010: サーバーサイドレンダリングのウェブサービス開発 • Windows95/98あたりからPCとインターネットが⼀般に普及 • ⼀般ユーザー向けのサービスがブラウザ経由で提供されはじめる • 2005 - : クライアントサイドレンダリングのウェブサービス開発 • ページ遷移を伴わずにページ内容を書き換えるブラウザアプリ • Google Mapなどが広く普及し始める。多くはサーバーサイドレンダリ ングとの併⽤ • 2010 : ⾼速な開発/更新とスケールするウェブサービスの開発 • インターネット上のユーザー数が膨⼤な数となる • ユーザーを集めるために⾼速にサービスを開発/公開を繰り返して、⼤ 量のトラフィックを捌ける設計が採⽤されるようになる • スマホやタブレット向けアプリも⼤きく普及

Slide 372

Slide 372 text

おおまかな開発⼿法の歴史(図) ビジネス アプリケーション サーバーサイド ウェブアプリ クライアントサイド ウェブアプリ スマホ向けアプリ 複雑化した ⼤規模ウェブアプリ 2000 ~ 2005 ~ 2010 ~

Slide 373

Slide 373 text

ペット vs 家畜 • インフラと開発に共通するトレンド。ペットのような環境から家畜のよう な環境へ。 • ペット • ⾮常に⼤事な存在なので、⼿がかかる • 数は少ない • 病気になったり死んだりするとダメージが⼤きい • 家畜 • 機械的に管理される存在 • 数は多い • ごく⼀部が病気になったり死んだりしても、ダメージは⼩さい • クラウドで「家畜のように扱えるサービスを開発」することで、インフラ 側の構築/運⽤コストを⼤幅に減らせる

Slide 374

Slide 374 text

HW HW OS サーバー仮想化 OS HW HW OS OS クラウド HW HW HW HW クラウド OS OS OS Managed Network Managed Storage Managed Database マネージドサービス • マシン台数の削減 • 複雑な操作を削減 コンテナ サービス開発⼒ 維持管理 変更コスト OS OS OS OS Legacy Backup etc. Legacy Backup etc. VS レガシーな開発と運⽤⽅式 新しい開発と運⽤⽅式 ビジネススピード ペット vs 家畜 (図)

Slide 375

Slide 375 text

クラウドの抽象化 • 変化が激しい世界ではサービス(⼀般向け、社内向け)を塩漬け させないことが⼤事 • 塩漬けさせないコツ • 「開発して終わり -> 2年後に更新」ではなく運⽤を続けな がら開発を継続する • 開発したサービスをすぐに「どこにでも」展開できる • 特定クラウドにサービスを依存させないコツ • 特定クラウドに特化した機能ではなく、汎⽤的な機能を使う • コンテナやオーケストレーションツールをつかって、サービ ス⾃⾝を最初から可搬性が⾼い設計で作る

Slide 376

Slide 376 text

クラウドの抽象化 (図) HW HW HW HW HW HW パブリック1 プライベート HW HW HW パブリック2 Ct2 Ct1 クラウドの抽象化レイヤー(Docker, Kubernetesなど) Ct2 Ct1 開発 本番(ウェブサービス) Ct4 Ct3 開発 Ct4 Ct3 Ct4 Ct4 本番(ビッグデータ処理)

Slide 377

Slide 377 text

トレンドを読むことで将来に備える • ⾰新的な技術はいきなりは普及しない • その技術が求められている⼟壌が確実にある • 技術が誕⽣してから最先端の⼈達に広がるのに3年以上はか かる。⼀般層に広がるにはもっと時間がかかる • ⽇本で普及する前にアメリカで普及することがほとんど • 相当な審美眼がない限りは超最先端を追う必要はなく、超最先 端な技術の多くは普及せず終わる • 「世間に広まりつつあるな」と思ってから「誰にたいして」 「背景」「タイミング」などについて考察してみる • 興味を持てば新しいことは楽しんで学べるし試せる

Slide 378

Slide 378 text

終わりに • ⼩中学校でのプログラミング履修からわかるように、簡単なプ ログラミングは⾮ITを含む多くの業務で求められるベーシック スキルとなりつつあります • Pythonは他の多くのプログラミング⾔語より簡単で、いろいろ な⽬的で利⽤することのできる⾔語です • 是⾮、本トレーニング資料を読んで終わりにするのではなく実 際に⾃分の⼿でプログラムを書いてみてください