Pythonの本を読んで学んだことをメモしてきます
Pythonの勉強中です。読んだ本に関しては、以下ブログ記事参照下さい。
内容的には、この記事では、特にPythonで書かれたフレームワーク(具体的にはTensorFlow、PyTorch等のディープラーニングのフレームワーク)を理解するのに必要だった知識を中心にメモしています。
以下は前提です。
- 当方、永遠の初心者です。優しくして下さい
- Pythonの基礎中の基礎は理解している読者を想定しています
-
print
の次行の#
行は、出力結果を意味します - コメント、編集リクエスト歓迎です
しばらくは、随時追加、修正していく予定です。
全体的な話
Pythonは全てがオブジェクト
Pythonは全てがオブジェクトらしいです。雰囲気でオブジェクト指向をやっているので、あんまり意味がわかってないです。
クラスすらオブジェクトらしいですが、それがどういうことなのかも良くわからないです。以下を読んでもよく分からないです。
Pythonのオブジェクトとクラスのビジュアルガイド – 全てがオブジェクトであるということ
当面、理解できなくてもプログラムを読み書きはできているのですが、このことを意識しておくと、いつか悟りをひらけそうな気がするので、最初に書いておきます。
公式ドキュメント読むの大切です
当たり前のことのようですが、結構公式ドキュメントを読んでない人多いと思います(すみません、私もあんまり読んでませんでした)。
いくつかPython本を読んで気づいてたのですが、本も結構間違っていたり、初心者向けに理解しやすくするために、省略している部分があったりするので、ドキュメントを読むのが大切ですね。日本語もあります。
全部を隅から隅まで読むのは、厳しいと思いますが、コーディングルールを記載していある、PEP8とかは、さらっと目を通しておくと良さそうです。
PEP 8 -- Style Guide for Python Code
クラス関係
特殊メソッド __hoge__
に関して
よく見る__hoge__
って表現、一体何なの?という人は、以下記事読むと幸せになりそうです。
Python初心者でも__hoge__
使いたい!〜特殊属性,特殊メソッドの使い方〜
__call__
メソッドでインスタンスを関数のように使う
以下みたいな書き方ができます。
class Function:
def __call__(self, x):
return 2*x
f = Function()
print(f(2))
# 4
あれ?これって関数なの?メソッドでは?と思ったら__call__
を確認すると良いかもしれません。
ディープラーニングのフレームワークでは、結構使われているイメージです。
dataclass
データを格納するのに使われる機能です。使いどころなどは、以下記事参照ください。
データ構造
リスト・タプル・辞書・集合(セット)
Pythonで複数のデータを扱うときに使われるのが以下4つです。
- リスト:
[ ]
- タプル:
( )
- 集合(set):
{ }
orset()
- 辞書:
{ }
一人で簡単なプログラムを書くときには、大体リストを使えばこと足りてしまいますが、ディープラーニングのフレームワークでは、当然リスト以外のものもよく使われます。具体的には、教師データのラベルとファイルの対応に辞書が使われたりしますね。
コードを読むときや、自分で使うときは、これらがどう違うのか、理解しておく必要があります。また、この後、説明しますがタプルの実体は実はカッコでなく、カンマなので注意して下さい。
タプルを作るのはカンマ(カッコは省略可能だけどカンマは省略できない)
要素が1個のタプルは、以下のように書く必要があります。
tuple = (1, )
print(tuple)
# (1,)
それどころか、そもそもタプルは以下のようにカンマだけでOKです。
tuple = 1,
print(tuple)
# (1,)
入門書では、リストは[]
でタプルは()
って書いてあるだけのことが多いので、実はタプルを作るのはカンマ(,
)というのは、地味に衝撃でした。
また、Pythonは、アンパック代入と呼ばれる、要素を複数の変数に展開して代入する手法があります(以下のコードだと、a, b = b, a
の箇所)が、実はこれPythonの内部的にはタプルという扱いになります。
a = 1
b = 2
a, b = b, a
print(a,b)
# 2 1
これも、全然意識せず使っていたので、驚きました。
参考:Pythonで要素が1個のタプルには末尾にカンマが必要
内包表記:
リストに関して、内包表記と呼ばれる以下のような書き方ができます。
test = [i for i in range(5)]
print(test)
# [0, 1, 2, 3, 4]
内包表記は、集合に対しても使用可能です。
test = {i for i in range(5)}
print(test)
# {0, 1, 2, 3, 4}
if
つかって、条件に合うものだけ取り出したりもできるので、色々使い勝手が良いです。
イテレータ・ジェネレータ
仕様だけみると「こんなん何に使うの?」という感じなのですが、ディープラーニングのフレームワークだと、データセット(教師データの集まり)のローダとして大活躍します。TensorFlow(Keras)だとImageDataGenerator、PyTorchだとDataLoaderですね。
ディープラーニングは、バッチ(小さいデータのかたまり)に分けて学習を進めていくので、まさにこのイテレータの仕組みが大活躍するわけですね。なので、イテレータの仕組みを理解しないままデータローダを使うとよく分からなくなるので、基本を理解するのが良いです。
Qiita記事だと以下などが分かりやすいと思いました。
テストに関して
何か問題あったとき、テストプログラムを活用できると効率的に問題を切り分けられる場合があるので、知っておくと良いかと思います。
unittest --- ユニットテストフレームワーク オフィシャルドキュメント
Python標準のunittestの使い方メモ
Pythonのunittestでハマったところと、もっと早くに知りたかったこと
その他
あんまりフレームワークとは関係ないけど、知っておくとPythonを読み書きするときに便利なTIPS。
enumerateを使ってループにインデックスを付ける
ループの回数にインデックスが必要な場合、enumerateを使うと以下のように簡潔に書けます。
test = ['a', 'b', 'c', 'd', 'e']
for i, x in enumerate(test):
print(i, x)
# 0 a
# 1 b
# 2 c
# 3 d
# 4 e
大したことではないですが、よく使われるので、知っておくとコードを読み書きするとき便利です。
modfで数値の整数部と小数部を同時取得
正確な値取得しようとすると、ちょっと面倒臭いので知っておくと便利です。
import math
print(math.modf(1.5))
# (0.5, 1.0)
print(type(math.modf(1.5)))
# <class 'tuple'>
参考:Python, math.modfで数値の整数部と小数部を同時に取得
Pythonでのアスタリスク *
の意味
アスタリスクは、CやC++だと、ポインタなので嫌な思い出しかないのですが、Pythonは全然違うので安心(?)です。以下のまとめをみておくと良さそうです(困った時に調べる感じでも良いかとは思いますが)。
@
で行列の積を計算できる
@
で行列の積を計算できます。Python3.5, NumPy1.10.0以降でないと使用できないので注意して下さい。
import numpy as np
x = np.array([1, 2])
y = np.array([1],[2])
x @ y
# array([5])
np.matmul(x,y)
でも同じ結果になります。 np.dot(x,y)
というのもあるのですが、こちらは3次元以上の配列になると、結果が変わってくるようです(2次元だと、matmul,@
と同じ結果)。
機械学習系だと、行列の積はよく使われるので、見かけることもあるかと思います。
まとめ
Pythonで学んだことを、フレームワークへの理解を深める知識という観点で簡単にまとめました。他のテーマでも忘れないようにメモしていこうかなと考えています。
更にPythonを深く知りたいという人は、以下の記事も参考にしてみて下さい。また、他にもっと良い本がありましたら、是非コメントやTwitter等で教えて下さい。