『Pythonエンジニア養成読本』読書会便り ~基礎やTipsから質疑応答の内容まで~

第1回よくわかるPythonの世界とこれだけは知っておきたいPython言語はじめの一歩

はじめに

鈴木たかのりです。

本連載ではPythonエンジニア養成読本という書籍の読書会イベントについてレポートします。この書籍は「他のプログラミング言語は知っていて、これからPythonを始める方」を対象として、筆者を含め6人のPythonista(Pythonを使う人)で執筆し、2015年4月17日に技術評論社から発売されました。

読書会では書籍と同様に、Pythonの初心者の方を対象としています。また、本連載は書籍を持っていなくても理解できるような内容にしています(書籍を持っていればより理解が深まると思いますが⁠⁠。

筆者がこの読書会を始めようと思った動機としては、単純にこの本を読んだ人はどんな人たちで、どんな感想を持っているのか知りたいということがありました。そして、どの部分を疑問と思ったのかを知りたいと思ったということもあります。

読書会の進め方

第1回の読書会は5月21日(木)アライドアーキテクツ株式会社の会議室で開催されました。今後月1回のペースでそれぞれの章の執筆者が中心となって読書会を進めていく予定です。

当日は以下のタイムテーブルで進めました。

  • 19:00-19:10:参加者の自己紹介
  • 19:10-19:40:「第1章 よくわかるPythonの世界」
  • 19:10-21:10:「第2章 これだけは知っておきたいPython言語はじめの一歩」
  • 21:10-22:00:ビアバッシュ(ビールとピザでの参加者懇親会)

一般的な読書会では「書籍の内容をみんなで読み解く」といった形式が多いと思います。しかし、この読書会では内容の読み合わせは行わず、書籍に付加した内容を話したり、参加者の持っている疑問点などをぶつけてもらって、みんなで議論して進めていこうと思っています(参加者のみなさんに活発に意見を言ってもらうのは難しかったりしますが⁠⁠。

この形式は私の発案ではなく、以前参加していたエキスパートPythonプログラミング読書会 第二期の進め方を参考にしています。ビアバッシュのときにLTを盛り込むところも参考にさせてもらいました(丸パクリしました⁠⁠。

図1 読書会の様子
図1 読書会の様子

自己紹介

最初に筆者も含めて参加者全体の自己紹介を行いました。全部で16名の方が参加してくださいました。

参加者の傾向としては「仕事でPythonを使っています」という方はほとんどおらず、⁠これからPythonをやろうと思っている」⁠普段は別言語で開発をしている」という方が多かったと思います。業界もネットワーク系、Androidの開発、Webエンジニア、研究者、営業、マーケティング等いろいろな方がいて、普段参加する開発系のイベントとは異なる人達が多く、なかなか興味深かったです。

第1章 よくわかるPythonの世界

第1章は筆者の担当です。この章ではPythonのプログラミングについてはほとんど書いていませんが、プログラミング言語Pythonをより深く知るためのネタ的な内容が書いてあります。読書会ではその内容をさらっと紹介しつつ、質疑応答を行いました。

1-1 Pythonの特徴

この節ではプログラミング言語Pythonの特徴的なポイントについて解説しました。

そもそもPythonという名前なので、ロゴマークなどには「ヘビ」をモチーフとした物が多いです。しかし、その名前は実はイギリスのコメディグループ「モンティ・パイソン」からとられています。これは作者のGuido氏が同グループのファンだからだそうです。

図2 Pythonロゴ
図2 Pythonロゴ

また、自己紹介のところで「きれいなコードだと思った」と発言された方がいますが、それはPythonのコードがインデントでブロック構造を示すことや、言語設計として「誰が書いても同じようなコードになる」という方向性であることが影響しているのでは、と話しました。

下記のサンプルコードのように、forループやif文の範囲(ブロック)は同一のインデントによって表しています。パッと見でコードの構造がわかりやすいと思います。

Pythonではブロック構造をインデントで表す
for i in range(10):
    if i % 5 == 0:
        print 'ham'
    elif i % 3 == 0:
        print 'eggs'
    else:
        print 'spam'

また、Pythonらしさを表す文章としてこの節ではThe Zen of Pythonという格言についても説明しました。この格言はPythonインタープリタでimport thisと入力すると表示されます。1行目は「きたないよりきれいな方がいい」と言った意味になります。

import thisでThe Zen of Pythonを表示
>>> import this
The Zen of Python,  Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
(以下略)

ちなみに、import thisのソースコードには格言の内容はそのままは格納されていません。import thisのソースコードを参照すると暗号化されています。興味のある方は、どのような処理なのか調べてみてください。

1-2 その歴史とバージョン選定のポイント

この節ではPythonのリリースバージョンと、どのバージョンを使うべきかについて話しました。

現在アクティブなバージョンはPython 2系(本稿執筆時の最新は2.7.10)とPython 3系(同最新は3.4.3)です。Python 3系はPython 2系とは一部の互換性を排しており、とくに重要な変更点として「文字列がUnicode文字列に統一」ということを紹介しました。

Python 2系では日本語のencode/decode処理でエラーが発生することがよくあります。そのため、新規にコードを書くのであればPython 3系をお勧めします。しかし、この書籍では「すでに存在するプロジェクトに入る方」をメインのターゲットと想定したので、Python 2系で解説をしています。

ここで「Macを使っているが、2系と3系の両方をインストールできるのか?」という質問がありました。MacであればDownload Pythonのページからダウンロードしたインストーラーで両方インストールしても問題ありません。brewでも両方インストールできます。

MacにbrewでPython 2系と3系をインストール
$ brew install python python3
$ /usr/local/bin/python -V
Python 2.7.9
$ /usr/local/bin/python3 -V
Python 3.4.2

「現在Python 2系のコードがあり、Python 3系に移行する場合はどうすべきか?」という質問がありました。これは、そのプロジェクトを今後どうしていくかにもよると思います。長く続くのであればPython 2系は2020年にサポートが切れるため、3系に移行すべきです。そうでなけば移行のためのコストが持てるのかどうかによるという回答をしました。

Python 2系のコードを3系に変換する2to3というがツールがありますが、変換すると2系に対応できなくなります。sixというパッケージを利用し、Python 2系に3系の機能を取り込み、一つのコードで両方で動作するほうがお勧めであるという話をしました。

1-3 Pythonのコミュニティ

この節ではせっかくPythonを使うのであれば、1人で勉強するよりも人と知り合ったほうが良いと考え、コミュニティについて紹介しました。この読書会イベントもコミュニティの一つと考えられます。

最初にPyCon(Python Conference)について紹介しました。PyConは名前の通り、プログラミング言語Pythonのための国際カンファレンスです。日本でもPyCon JPが開催されていますが、他にも世界各国でPyConが開催されています(筆者も台湾で開催されるPyCon APACに6月5日~7日の日程で参加予定です⁠⁠。

他にもPythonベースのツールやライブラリに関するコミュニティや、開発をする「もくもく会(集まって黙々と開発する⁠⁠」的なコミュニティがあります。Pythonコミュニティの探し方については、記事後半の「ビアバッシュ」のところで紹介します。また、今回の読書会参加者は全員男性だったため関係ありませんが、PyLadies Tokyoという女性のコミュニティもあります。

第2章 これだけは知っておきたいPython言語はじめの一歩

第2章の執筆者の清原弘貴@hirokikyから自己紹介と、PyCharmの紹介がありました。

図3 清原弘貴氏とPythonエンジニア養成読本
図3 清原弘貴氏とPythonエンジニア養成読本

普段、開発環境として使用しているPyCharmの使いやすい部分についての紹介がありました。PyCharmには機能が一部制限されている無料のCommunity Editionがあるので、まずはそちらを使ってみると良いです。有料のProfessional Editionは年間99ドルです。

2-1 Pythonをはじめよう

PythonにはPython チュートリアルという非常に優れたドキュメントがあります。ただ、少し内容が長いということと、⁠最初はここまで知らなくてもいいのでは」という内容も含まれているという印象です。そのため、この章ではPythonチュートリアルから内容を削って「これだけは知っておいてほしい」という内容を入れました。なお、Pythonチュートリアルは易しくはないですがとても良いドキュメントですので、Pythonをはじめようと思っている方はぜひ読んでみてください。

他の導入向け書籍についてはPythonスタートブックはプログラミングを知らない人も含めて導入にはとても良い本です。初めてのPythonも良い本ですが808ページと分厚いのでちょっと手に取りにくいと思います。

また自己紹介で集合知プログラミングの内容を学びたい」という方がいました。この本はPythonの書き方がきれいではないが、内容が良くPythonに慣れるにも良いという説明がありました。

この節ではPythonのインストールから、対話モードの実行、FizzBuzzをサンプルに簡単なプログラムを作成するところまでを詳細に解説しました。FizzBuzzは「数字を連続で言っていくが、3の倍数ではFizz、5の倍数ではBuzz、15の倍数ではFizzBuzzと言う」というゲームです。

最終的には以下のようなコードが作成されます。

fizzbuzz.py
def fizzbuzz(num):
    if num % 3 == 0 and num % 5 == 0:
        return 'FizzBuzz'
    elif num % 3 == 0:
        return 'Fizz'
    elif num % 5 == 0:
        return 'Buzz'
    else:
        return str(num)

for num in range(1, 101):
    print fizzbuzz(num)

その中で、Pythonのプログラミングの基本となる、下記の要素について解説しました。

  • 文字列:'Fizz''Buzz'のように文字列が定義できること
  • 関数の定義:def 関数名(引数):と書いて関数が定義できること
  • 組み込み関数:連続した数字を返すrange()関数と、文字列に変換するstr()関数について
  • for文:forによる繰り返しのループについて
  • if文:ifelifelseによる条件分岐について
  • 比較演算子:==比較演算子により値をチェックしていることについて
  • %演算子:剰余%の演算子について

ここでrange(1, 101)となっているのはなぜか?」という質問がありまいた。range()関数は引数が1つの場合は終了値を指定したことになり、0開始で終了値未満の数字を返します。引数が2つの場合は開始値と終了値を指定したことになります。この例では1から100(101未満)のFizzBuzzを実行したいためrange(1, 101)としました。また、第3引数を指定するとstepが指定できます。

range関数の例
>>> range(10)        # 終了値に10を指定
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(1, 10)     # 開始値に1、終了値に10を指定
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(1, 11, 2)  # 開始、終了値、ステップを指定
[1, 3, 5, 7, 9]

また、プログラミングの練習問題としてProject Eulerがお勧めであるという話がありました。このサイトではさまざまな数学に関する問題が提供されています。日本語の解説もあるので、英語の問題が読めない方でも安心です。

2-2 Pythonのデータ型[基本編]

この節ではPythonの基本となる、以下のデータ型について説明しました。

  • 整数型(int)
  • 浮動小数点型(float)
  • 文字列型(str)
  • Unicode文字列型(unicode)
整数型と浮動小数点型
>>> 2 + 2 # 整数型の計算
4
>>> 3 - 8
-5
>>> 6 * 9
54
>>> 7 / 3 # 整数型同士の商は整数型となる
2
>>> 5.0 + 5.2 # 浮動小数点型の計算
10.2
>>> 10.2 + 8  # 浮動小数点型と整数型の計算結果は浮動小数点型になる
18.2

シングルクォート'またはダブルクォートで"で囲むと文字列になります。また文字列の一部をインデックス指定やスライス指定で取り出せます。

str型
>>> 'Hello,world'
'Hello,world'
>>> "Hello,world"
'Hello,world'
>>> 'python'[1]   # 文字列のインデックス指定
'y'
>>> 'python'[2:5] # 文字列のスライス指定(2文字目から5文字目の前まで)
'tho'
>>> 'python'[:3]  # 最初から3文字目の前まで
'pyt'
>>> 'python'[4:]  # 4文字目から最後まで
'on'
>>> 'python'[1:-1] # 1文字目から後ろから1文字目の前まで
'ytho'

インデックスやスライスで指定する数値は以下の図のようになっており、負の数も使えます。

図4 インデックス
図4 インデックス

Python 2系ではUnicode文字列を扱うためのunicode型があります。Python 3系ではstr型(中身はUnicode文字列)に統一されました。unicode型の文字列はu'文字列'と宣言します。また、str型とunicode型の変換はencode/decodeで行います。

unicode型
>>> u'日本'
u'\u65e5\u672c'
>>> print u"日本" # printに渡すと文字列が表示される
日本
>>> u"日本".encode('utf-8') # str型にエンコード
'\xe6\x97\xa5\xe6\x9c\xac'
>>> '\xe6\x97\xa5\xe6\x9c\xac'.decode('utf-8') # unicode型にデコード
u'\u65e5\u672c'
>>> print '\xe6\x97\xa5\xe6\x9c\xac'.decode('utf-8')
日本

なお、Python 2系のインタープリタではunicode型の文字をそのまま表示しないため、print文を使用して確認しています。Python 3系のインタープリタではPEP 3138 -- String representation in Python 3000[1]によって日本語がそのまま表示されるようになっています。なお、Python 3系ではエンコードしたデータはbytes型(b''の部分)になります。

Python 3系でunicode型のエンコード/デコード
>>> u"日本".encode('utf-8')
b'\xe6\x97\xa5\xe6\x9c\xac'
>>> b'\xe6\x97\xa5\xe6\x9c\xac'.decode('utf-8')
'日本'

ここで「型推論はないのか?」という質問がありました。Pythonに型推論はないが、Python 3.5で型のヒントが付けれるようになるという解説がありました。Python 3.5ではPEP 0484 -- Type Hintsによって、以下のように引数と戻り値の型が指定ができるようになるようです。

fizzbuzz関数にType Hintsを指定した例
# 引数はint型、戻り値はstr型
def fizzbuzz(num: int) -> str:

2-3 Pythonのデータ型[コレクション編]

この節では複数のデータをまとめて扱う「コレクション」というデータ型について説明しました。

  • リスト(list)
  • タプル(tuple)
  • 辞書(dict)
  • 集合(set)

リストとタプルはどちらも複数のデータをまとめるコレクションです。リストは可変なのに対して、タプルは値を変更できない不変(immutable)なデータ型です。

リスト(list)とタプル(tuple)
>>> ['spam', 'egg', 0.5] # リストは[]で囲む
['spam', 'egg', 0.5]
>>> ('spam', 'ham', 4)   # タプルは()で囲む
('spam', 'ham', 4)
>>> animals = ['cat', 'dog', 'snake']
>>> animals.append('elephant') # append()メソッドで要素を追加
>>> animals
['cat', 'dog', 'snake', 'elephant']

リストは通常[]で囲んで定義しますが、リスト内包表記という定義方法があります。リスト内包表記を上手に使うと、複雑なリストの定義をシンプルに記述できます。先ほど作成したanimalsリストの各文字列の長さをlen()関数で取得したリストを作成するとします。for文でリストを作成する方法と、リスト内包表記の例を以下に示します。

animalsの文字列長リストを作成
>>> ret = []                    # 空のリストを作成
>>> for animal in animals:      # animalsから一つずつ要素を取り出す
...     ret.append(len(animal)) # 文字列の長さを取得し、retに追加
...
>>> ret
[3, 3, 5, 8]
>>> [len(animal) for animal in animals] # リスト内包表記で記述
[3, 3, 5, 8]

このようにリスト内包表記を使用すると、複雑なコードがシンプルに書けます。リスト内包表記については、実行速度が速いという話もありました。ただし、表現が複雑になりすぎる場合は、コードの可読性が下がるのでリスト内包表記を使わないほうが良いという説明もありました。

辞書(dict)はキー(key)と値(value)を持つデータ型です。他のプログラミング言語では連想配列と呼ばれたりもします。集合(set)同じ値を1つしか持たないデータ型です。また、データの順序も持ちません。

辞書(dict)と集合(set)
>>> user_info = {                # 辞書は{}で囲む
...     'user_name': 'hirokiky', # key: valueの形式で要素を指定
...     'last_name': 'Kiyohara',
... }
>>> user_info
{'last_name': 'Kiyohara', 'user_name': 'hirokiky'}
>>> user_info['user_name']       # 任意のkeyの値を取り出す
'hirokiky'
>>> {'spam', 'ham'}              # 集合も{}で囲む(要素はカンマ区切り)
set(['ham', 'spam'])
>>> {'spam', 'spam', 'spam', 'ham'}  # 同じ値は1つしか持てない
set(['ham', 'spam'])

「大量のデータを扱う場合はどうしたら良いか?」という質問がありました。集合を使うと最も容量が少なく、要素が存在するかチェックするin演算子も速度が速いという回答がありました。しかし、もしデータが非常に多いのであればRedis等のミドルウェアを使うべきとのことです。

2-4 ファイル操作とモジュール

ファイル操作とモジュールについては簡単に、ファイル入出力ができるということと、ファイル分割したモジュールを読み出すという話がありました。以下はファイルへの単純な読み書きの例です。

ファイルへの読み書き
>>> with open('todo.txt') as f:      # ファイルを読み込みモードで開く
...     todo_str = f.read()          # ファイルの中身を読み込む
...
>>> with open('memo.txt', 'w') as f: # ファイルを書き込みモードで開く
...     f.write('Hello Python!')     # ファイルに文字列を書き込む
...

モジュールは別のファイルに記述した関数を利用する方法です。以下の様なadd()関数が定義されたcalc.pyというファイルを作成します。

calc.py
def add(a, b):
    return a + b

同じディレクトリでPythonインタープリタを実行し、calc.pyをインポート(import)するとadd()関数が利用できます。このようにして機能毎にファイルが分割できます。

calc.pyをインポートしてadd()関数を実行
>>> import calc    # calc.py をインポート
>>> calc.add(1, 2) # add() 関数を実行
3

また、Pythonではimportして利用できる便利な標準ライブラリが多数あります。Python標準ライブラリのドキュメントにまとまっているので、参考にしてください。一部については次回の読書会で紹介する予定です。

「importでのモジュール読み込みをファイルの先頭ではなく、関数の中で読むのはどうなのか?」という質問がありました。動作上は問題ありませんが、コードがどのモジュールに依存しているのかわかりにくくなるので、先頭に書くほうが良いという回答でした。

また「モジュールに分割すると、コンパイルされたpyc、pyoというファイルができてじゃま」という話がありました。これらのファイルは実行速度向上のために必要なため、しかたがないという回答をしました。

ビアバッシュ(懇親会)

読書会の終了後、参加者全員でビールとピザでビアバッシュという形式の懇親会を行いました。

図5 ビアバッシュ!!
図5 ビアバッシュ!!

ビアバッシュの中ではPythonでどんなことをやっているか、これからやっていこうかみたいな話から、どのように学んでいくかといった話をしました。

また、後半のLTの時間で筆者からPythonコミュニティやイベントの探し方について紹介しました。以下のサイトが参考になると思います。

また、5月のPython関連イベントに業務のためのPython勉強会というのがあり気になっていたのですが、主催者が読書会に参加している方でした。ぜひ、次回どんな感じだったかを聞いてみたいと思います。ちなみにスピーカーの辻さんは「Pythonスタートブック」の著者の方だそうです。

ネタとして「Pythonエンジニア養成読本」はエンジニア養成読本シリーズの中ではダントツに表紙がかわいいという話をしました。表紙画像は下記のリンクから参照できるので、皆さんも確認してみてください。

まとめ

こんな感じで1回目の読書会は無事に終了しました。

次回は6月18日(木)に開催します。内容は「Appendix1 便利な標準ライブラリ、サードパーティ製パッケージ」⁠第3章 開発環境とチーム開発」です。

本を読んでみて疑問がある方、もっと突っ込んだポイントを聞いてみたい方など、ぜひ参加してください。下記のURLから参加をお願いします。

では、また来月お会いしましょう。

おすすめ記事

記事・ニュース一覧