0. Python の基本的な注意点

 本章は、Python初者(私のこと)が、Python初者にとって躓きやすいと思われるポイントを簡単にまとめたものである。したがって、正確性・網羅性に欠く説明もあるが予めご容赦いただきたい。より系統だった説明については、参考文献として挙げた教科書などを参照頂きたい。

~もくじ~

(1) 型、属性、メソッド:「型」によってできることが違うことに注意

(2) ライブラリ関数の使用:メソッドでは事足りないときに

(3) 配列要素の範囲指定(スライス):始まり と 終わり に注意

(4) 繰り返し処理: なるべくループ処理を使わない(配列要素へ直接アクセスしない)

(5) 困ったときは?:関数・メソッドの調べ方、エラーへの対応


(1) 型、属性、メソッド:「型」によってできることが違うことに注意

 Pythonはオブジェクト指向言語と呼ばれるプログラム言語の一種である。

 これまでFortranやCなどの言語を用いてきた人は、その違いに最初は戸惑うと思う(私もそうでした)。  

◆『オブジェクト指向言語』:

 オブジェクト指向言語の特徴を端的に言えば:

  • プログラム中のすべてのモノ(オブジェクト(Object))は、ある型 (class)を持つ(データのみならず、関数図(グラフ)なども)。
  • それぞれのモノは各々のについて定義された属性 (attribute)(モノの具体的な情報:数値データも含む)とメソッド (method)(実行処理)を同時に持っている。

ということだろう(特に後者は慣れるまで理解しづらい)。

◆『型』『属性』『メソッド』とは何か?  

 身近な例として、「人間」「車」という型を考えてみる。これらは例えば以下のような属性・メソッドを持っている。

型 (class) 属性 (attribute) メソッド (method)
人間 名前, 年齢 歩く, 食べる
名前, メーカー 走る, ブレーキをかける

  私は人間という型を持つので、名前(坂崎)や年齢(34)という属性を持ち、歩く、食べるといった処理を行うことができる。(逆に、「車」という型ではないので、メーカー情報はないし、ブレーキをかけるという処理はできない。)

◆属性の参照・メソッドの適用

Pythonにおいて、オブジェクトAの属性の取得、およびメソッドの適用は以下のように行う:

  • 属性の参照A.属性名

  • メソッドの適用A.メソッド名() <-- 最後に括弧が必要なことに注意(オプションを括弧内に記述;空欄であればデフォルトで実行される)

複数の属性参照・メソッドを用いた直列処理も可能である。例えば、

  • メソッド1の結果に、メソッド2を適用: A.メソッド1().メソッド2()

また、オブジェクトの型を確認するには以下のようにする:

  • type(A)

[例] 「あるデータ配列の平均値を計算する」という処理を考えてみよう。

In [1]:
import numpy as np #使用するライブラリを"np"という名前でインポートする
In [2]:
# ndarray型として配列を定義する(ndarray:数値計算でよく用いられる配列型)以下の(2:ライブラリ関数の使用)を参照)
a = np.array([0,-1,2,3])

# 型は何か?
print(type(a))

# 例:属性(データのタイプ)
print("Values=", a.dtype)

# 例: メソッド(平均をとる)
print("Average = ", a.mean())
<class 'numpy.ndarray'>
Values= int32
Average =  1.0

ちなみに、以下のようにデータ配列を定義するとエラーが出る

In [3]:
b = [0,-1,2,3]

# 型は何か?
print(type(b))

# .mean()メソッドを適用してみる
print("Average = ", b.mean())
<class 'list'>
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-3-0e490a128cb3> in <module>
      5 
      6 # .mean()メソッドを適用してみる
----> 7 print("Average = ", b.mean())

AttributeError: 'list' object has no attribute 'mean'

これはエラー("AttributeError")で怒られているように、listの型に.mean()というメソッドが定義されていないことによる。


(2) ライブラリ関数の使用:メソッドでは事足りないときに

データ解析を行うにあたっては、定義されたメソッドだけで事足りない場合が多い。

幸いPythonにはデータ解析や数値計算に有益な様々なライブラリが用意されており、そこで定義された関数を使って複雑な解析処理を行うことになる。

◆ 関数は、

出力 = 関数名(引数、オプション)

として使う ($y = f(x)$を想像すれば良い)。


 例えば、上の例の

a = np.array([0,1,2,3,4])

は、関数を使用した処理の一例であり、

npというライブラリの中のarrayという関数(配列を作成する関数)を、 ()内を引数(配列の中身)として実行し、その結果をa出力せよ」

という意味である(.を用いていることからも、(1)で述べたように「関数も一つのオブジェクトである」という概念がお分かりいただけるかと思う)。

 取り得る引数は関数ごとに定義されている。。


[例2] 関数を用いて「配列の値の絶対値を求める」という処理を行ってみよう:

まず、np.abs()という関数を用いると

In [4]:
np.abs(a) #np.abs()という関数を用いる。引数として、絶対値を求める配列を指定
Out[4]:
array([0, 1, 2, 3])

と、元の配列の絶対値をとったものが出力される。一方で、メソッドを使って処理しようとすると、、

In [5]:
a.abs() 
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-202a11866fea> in <module>
----> 1 a.abs()

AttributeError: 'numpy.ndarray' object has no attribute 'abs'

エラーが出る。くどいようだが、配列aの型(ndarray)に、abs()というメソッドが定義されていないからである。


(3) 配列要素の範囲指定(スライス):始まり と 終わり に注意

 データ配列から一部を抜き出して解析する場合は以下のように行う。配列要素を指定する際には、特に以下に注意されたい。

  • 最初の要素はA[0], 最後の要素はA[-1]

  • 範囲を指定する場合、startと終了位置endを用いてA[start:end]と表す。ただしstart $\le$ i $\lt$ endの範囲が選択される(end は含まない!)。

  • :「全て」を意味する。
    • A[:]: 全要素
    • A[start:]: start以降すべて
    • A[:end]: endまですべて(但し、endは含まない!)
In [6]:
print(a[0], a[-1]) #最初と最後の要素
0 3
In [7]:
print(a[0:3], a[0:-1]) #1番目から3番目まで(二通り)
[ 0 -1  2] [ 0 -1  2]
In [8]:
print(a[1:]) #2番目の要素以降全部
[-1  2  3]

(4) 繰り返し処理:なるべくループ処理を使わない(配列要素へ直接アクセスしない)

数値計算では、同じ処理を繰り返し行うループ処理を多用する。

ループ処理にあたって、FortranCではDo 文For 文を用いることが多かった。

一方でPythonでは、

◆ ループ処理で配列要素への直接参照はせず(遅い!)、メソッドや関数で済ます

ことが推奨されている。

例えば、先の平均値を求める処理は(Fortran風に):

In [9]:
rsum = 0;
isum = 0;
for v in a: #aのそれぞれの要素(v)に対して、以下の処理を実行
    rsum += v #rsum にvを足す
    isum += 1 #isum に1を足す
    
print("Average = ", rsum/isum)
Average =  1.0

とも書けるが、Pythonではメソッド関数を用いて(ここではメソッド):

In [10]:
print("Average = ", a.mean())
Average =  1.0

とする方が良い(この程度の大きさの配列であれば大したことはないが、大規模データセットではこの差が如実に表れる)。(ブラックボックス的で気持ち悪い面はあるが、、、)


(5) 困ったときは?:関数・メソッドの調べ方、エラーへの対応

 既に述べたように、Pythonでは多様なライブラリ関数があり、そこから生み出されるオブジェクトの型ごとに属性やメソッドが定義されている。 これらを全て覚えるのは不可能なので、その都度マニュアル等を参照しながらやっていくしかない。いくつか調べ方のTipsを紹介する:

◆補完機能(Tab)を利用する(Jupyter Notebook)

Jupyter Notebookでは、[Tab]を押すことで入力途中のコードに対する補完機能を利用できる。

例えば、上の例でa.まで入力した状態で[Tab]を押すと、属性・メソッドの一覧が見られることを確認してみてほしい。  

◆オンラインマニュアルを参照する

 Pythonでは関数やメソッドの使い方について、オンラインでマニュアルがきちんと整備されている。

例えばnp.array()という関数について調べたい場合、「numpy.array」などと検索するとマニュアルがヒットすると思う:numpy.array のマニュアル

これを見れば、「引数としてどういう型のオブジェクトを与えるべきか?」「どういうオプションがあるか?」などの情報を得られる。

◆ Google先生に相談

 Pythonの最大の利点の一つはユーザが多いことである。エラーメッセージの意味など考えても分からない場合は、その内容で検索をかけることで答えを得られることも多い。

In [ ]: