2014/12/30

ライブラリ:nose

Pythonの「 nose 」というライブラリをご紹介します。

import nose

nose はユニットテスト用のライブラリです。「 unittest 」という名前そのままのユニットテスト用ライブラリが標準ライブラリに含まれてはいますが、これはあくまでも xUnit 系列の標準ライブラリ、的な位置づけのもの。nose を使えば、ユニットテストをよりかんたん・シンプルに活用することができます。

以下、 nose の基本的な使い方を見ていきます。まずは最小単位から。


テストケースの書き方

次のようなスクリプトを作ります。
# test_int.py
# assert 文をシンプルに書ける ok_ eq_ メソッドの読み込み
from nose.tools import ok_, eq_

# テストケース
# test で始まる名前の関数で書けばOK
def test_1_is_true():
    ok_(bool(1))

def test_1_plus_2():
    eq(1 + 2, 3)

ここでは、ライブラリを読み込んで関数を2つ定義する、というごくごくシンプルなテストスクリプトを書いています。名前が test から始まるこれらの関数が nose ではテストケースとして認識されます。

ok_ eq_ は assert 文をよりシンプルに書くためのラッパ関数です。これを使うとよりシンプルに書くことができますが、必須ではありません。通常の assert を使っても大丈夫です。


テストの実行の仕方

テストの実行は nosetests コマンドで行います。

上記スクリプトがあるディレクトリに移動したら nosetests コマンドを実行します。
$ nosetests test_unit.py

するとテストが実行され、以下のようなメッセージが表示されます。
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

ここでは . がひとつのテストケースを表します。具体的にどのテストケースが実行されたのか確認したい場合は詳細表示のための -v オプションを利用します。
$ nosetests test_unit.py -v

テスト名が表示されるようになりました。
test_int.test_1_is_true ... ok
test_int.test_1_plus_2 ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK


テストの自動探索と実行

このようにテストスクリプトを直接指定するやり方でもOKですが、引数なしの nosetests コマンドを使うと、もっとかんたんにテストを実行することができます。
$ nosetests

nosetests が実行されると、 test で始まるスクリプトの中から test で始まる関数が探索され、順次実行されていきます。


インストール

pip が入っていれば pip install でインストールすることができます。
$ pip install nose


以上です。

ここでご紹介したのは nose の機能のごく一部です。ほかにも、 unittest と同じようにクラスを使ってテストを書く方法や unittest や doctest も合わせて実行する機能、 setup/teardown 機能など、便利な機能が豊富に用意されています。

nosetest についてはわかりやすい説明をされている方がすでにたくさんいますので、詳しく知りたい方は参考ページをご覧になってみてください。


参考
nose まとめ。とてもわかりやすいです。日本語で nose について学ぶならベストかと思います。
Nose 利用ノート

以下英語です。
「 nose って何がいいの?」という質問への答えが書かれたスレッドです。
http://stackoverflow.com/questions/5696884/python-nose-vs-unittest

nose の基礎から少し踏み込んだ内容まで1ページでまとめて説明されています。
nose introduction - Python Testing

こちらは公式ドキュメント。「基本的な使い方」のページです。
Basic usage — nose公式ドキュメント

こちらのページもシンプルでわかりやすいです。カバレッジモジュールについても触れられています。
miscellaneous

事例ベースで node を学ぼうという趣旨のページ。実コードが見たい、という方に。
Python testing with nose by example | Cesar's code

2014/12/27

Python Tips:IPython 起動時の readline 関連の警告をなくしたい

環境によりますが、MacOS X で IPython を pip からインストールして起動すると、起動時に次のような文章を含むメッセージが出ることがあります。

libedit detected - readline will not be well behaved, including but not limited to:
   * crashes on tab completion
   * incorrect history navigation
   * corrupting long-lines
   * failure to wrap or indent lines properly
It is highly recommended that you install readline, which is easy_installable:
     easy_install readline
Note that `pip install readline` generally DOES NOT WORK, because
it installs to site-packages, which come *after* lib-dynload in sys.path,
where readline is located.  It must be `easy_install readline`, or to a custom
location on your PYTHONPATH (even --user comes after lib-dyload).

この場合、 readline というPythonライブラリが不足しているということなので、 readline を入れれば解決します。

ただし、警告文で指示されているとおりに pip でインストールするとうまく解消できないことがあります。
$ pip install readline 

この場合は readline をいったんアンインストールしてから easy_install で入れるとうまくいくことがあるようです。
$ pip uninstall readline
$ easy_install readline

以上です。


参考
pip installing ipython with readline on OSX Lion - Stack Overflow
python - ipython complaining about readline - Stack Overflow

2014/12/23

Pythonのデコレータの使い方

Pythonのデコレータの使い方について見てみます。

デコレータとは、既存の関数やクラスを「装飾」する機能のこと。デコレータを使うことで、既存の関数やクラスの中身を直接触ることなく、その外側から機能を追加したり書き換えたりすることができます。

Pythonでは、関数やクラスもオブジェクトということもあって、自分オリジナルのデコレータをかんたんに作ることができます。

具体的に見ていきます。次のような hello 関数が定義されているものとします。
# あいさつを返す関数
def hello():
    return "konichiwa"

print hello()  # => konichiwa
# 定義したとおりの結果が返ってくる

続いて、 mydec 関数を定義し hello 関数を書き換えます。
# デコレータパターンを使うために
# 関数を受け取り関数を返す関数を定義する
def mydec(func):
    def new_func():
        print "%s function called".format(func.__name__)
        return func()
    return new_func

# hello を書き換え
hello = mydec(hello)

print hello()
# => hello function called
#    konichiwa
書き換えた結果、新たに作られた hello は元の hello と同じ戻り値を保ちながら、標準出力に hello function called と出力するものに変わりました。

すでにある関数を装飾するこの一連の処理がデコレータパターンです。キモとなっているのは hello = mydec(hello) の一文です。

Pythonではこの一文は @ を使ったシンタックスシュガーでシンプルな形に書き換えることができます。これがいわゆるデコレータ構文です。
@mydec
def hello():
    return "konichiwa"
このコードは次のコードと等価です。
def hello():
    return "konichiwa"
hello = mydec(hello)

「@デコレータ名」をいくつも積み重ねて、複数のデコレーションを行うことも可能です。


上記の hello は引数がない場合でしたが、引数がある関数に適用できるデコレータも、可変長引数などを使ってかんたんに定義ことができます。
def mydec(func):
    def new_func(*args, **kwds):
        print “%s function called”.format(func.__name__)
        return func(*args, **kwds)
    return new_func

@mydec
def some_function(*args):
    # ... content

ただし、このやり方では、関数のアトリビュート __name__ や __doc__ が書き換えられてしまうという問題があります。

この書き換え問題を手軽に解決してくれるのが、標準ライブラリの functools.wraps です。この wraps デコレータを使えば、書き換え前の関数のアトリビュートを書き換え後のものに手軽に移すことができます。
from functools import wraps

def memoize(func):
    cache = {}
    # wraps を使って元の関数のアトリビュート等を書き換え後の関数にコピーする
    @wraps(func)
    def decorated_func(*args):
        if args not in cache:
            cache[args] = func(*args)
        return cache[args]
    return decorated_func

@memoize
def some_function(*args):
    # ... content

一見ややこしいのですが、 wraps は次のような形で使うデコレータです。
@wraps(元の関数)
def 書き換え後の新しい関数():
    # 新しい関数の中身
よくよく考えればこの書き方になるのも納得ですが、このあたりはもう定型パターンということで、難しく考えずに「こう書くもの」と捉えてしまってもよいかもしれません。


以上です。


ちなみに、@構文は関数だけでなくクラスに対しても適用することができます。また、デレコータそのものも関数ではなくクラスとして定義することなんかも可能です。

もっと詳しく見てみたい場合は、わかりやすい解説をしている方がたくさんいらっしゃるので参考ページを参照してみてください。

参考
英語ですがとってもわかりやすいです。
Decorators and Functional Python

いろんなデコレータパターンを紹介してあります。
PythonDecoratorLibrary - Python Wiki

日本語で書かれている解説ではこのあたりのページがおすすめです。
Python - デコレータ
Pythonのデコレータを理解するときに残したメモ - kk6のメモ帳*

公式ドキュメントの解説。ちょっと短すぎるような。。。
functools.wraps — Python公式ドキュメント

2014/12/16

Python Tips:特異メソッドを作りたい

Pythonで「特異メソッド」を作る方法をご紹介します。

特異メソッドというのは(私が知るかぎり)Ruby発祥のことばで、「特定のオブジェクトだけが持つメソッド」のこと。インスタンスメソッドは特定のクラスのインスタンスであればどのインスタンスからも呼び出すことができますが、特異メソッドはある特定のインスタンスからしか呼び出すことができません。

types ライブラリの MethodType というコンストラクタを使えばPythonでも特異メソッドを作ることができます。

具体的に見ていきます。
# ライブラリの読み込み
from types import MethodType

class Dog(object):
    def __init__(self, name):
        self.name = name

d1 = Dog(“inu”)

# 以下で特異メソッドを追加していきます
# まずは特異メソッドにしたい処理を関数として用意
def hello(self):
    print “%s: bow!” % self.name

# 特異メソッドとしてオブジェクトのアトリビュートに追加
# format: MethodType(method, obj)
d1.hello = MethodType(hello, d1)

d1.hello()  # => inu: bow!
# d1 をレシーバに hello メソッドが呼び出せるようになる

d1 だけで使えるインスタンスメソッドを追加することができました。

hello は d1 だけに追加したアトリビュートなので、他のインスタンスで利用することはできません。
d2 = Dog(“hayato”)
d2.hello()  # => AttributeError
# hello はあくまでも d1 のメソッドなので他のインスタンスからは呼び出せない


ちなみに、MethodType を使わず
d1.hello = hello
とやっても一見追加できるように思いますが、これだとただの関数となってしまい、関数内でレシーバである d1 への参照を持つことができません。

また、次のようにやってもうまく行きません。
d1.__class__.hello = hello
これだと hello はクラス全体で共有されるインスタンスメソッドになるため、こちらの方法も特異メソッドを作るには不適切です。

以上です。


ちなみに、次の部分はハードコーディングしてしまっているので、再利用性が高くありません。
d1.hello = MethodType(hello, d1)

他でも使うことを考えてもっときれいに書くなら次のような感じになるでしょうか。
def add_eigen_method(obj, method):
    setattr(obj, method.__name__, MethodType(method, obj)

add_eigen_method(d1, hello)


Rubyほどシンプルにきれいに書くことはできませんが、Pythonでも特異メソッドを利用することはできます、というお話でした。


参考
python - Adding a Method to an Existing Object - Stack Overflow
Hoarded Homely Hints: Python Metaprogramming: Dynamically Adding Methods to Classes
Dynamically Adding a Method to Classes or Class Instances in Python - Ian Lewis

8.15. types — Names for built-in types — Python公式ドキュメント

2014/12/11

サンプルコード:ファイルの中身を行単位でソートして出力

サンプルコード:ファイルの中身を行単位でソートして出力


Python でファイルの中身を行単位でソートし標準出力へと出力するサンプルコードをご紹介します。

# coding: utf-8
import sys

# コマンドライン引数を取得
argv = sys.argv

if len(argv) < 2:
    print("usage: python this_script.py target_filename")
    exit()

# コマンドライン引数の最後に与えられたファイルを読み込んで行をソートし出力する
with open(argv[-1]) as f:
    lines = f.readlines()
    lines_sorted = sorted(lines)
    for l in lines_sorted:
        print(l.rstrip("\n"))

readlines() sorted() 、 rstrip() あたりを使うとシンプルに記述することができます。

2014/12/10

Python Tips:順列や組み合わせを作りたい

Pythonで、数学でいう nPr や nCr 、いわゆる「順列」や「組み合わせ」を作る方法をご紹介します。

結論としては itertools ライブラリを使う方法がかんたんです。

以下、順番に見ていきます。
  1. 順列
  2. 組み合わせ


順列

itertools.permutations を使います。
from itertools import permutations

original = "abc"
permutations(original)
# => [('a', 'b', 'c'),
      ('a', 'c', 'b'),
      ('b', 'a', 'c'),
      ('b', 'c', 'a'),
      ('c', 'a', 'b'),
      ('c', 'b', 'a')]
引数には、要素を格納したリストなどを渡します。

int を第2引数として与えると長さを指定することもできます。
permutations(original, 2)
# => [('a', 'b'), 
      ('a', 'c'), 
      ('b', 'a'), 
      ('b', 'c'), 
      ('c', 'a'), 
      ('c', 'b')]

順列は英語で permutations なので、名前そのままですね。


組み合わせ

こちらは itertools.combinations を使います。

こちらも組み合わせの英語にあたる「combination」と、そのままの名前になっています。
from itertools import combinations

original = "abc"
combinations(original, 2)
# => [('a', 'b'), ('a', 'c'), ('b', 'c')]
こちらも、第1引数にリストなどの iterable な要素を、第2引数に int を渡します。

こちらは permutations と異なり、第2引数が必須となっています。


以上です。


参考
9.7. itertools — Functions creating iterators for efficient looping — Python公式ドキュメント
algorithm - How to generate all permutations of a list in Python - Stack Overflow
Python code to pick out all possible combinations from a list? - Stack Overflow

2014/12/03

Python Tips:画像の Exif データを取得したい

Pythonを使って、画像の Exif データを取得する方法をご紹介します。

Exif データとは、画像の各種メタ情報を表すためのフォーマットのことです。写真であれば、カメラの機種や撮影した日付、位置情報などのデータが格納されています。

必ずしもすべての画像に備わっているわけではないので、「ついてる画像にはついてる」といった位置づけの情報です。

ちなみに Exif は Exchangeable Image File Format の略だとか。


この Exif データをPythonを使って取得する方法を以下ご紹介します。

結論からいえば、 PIL ライブラリを使う方法がかんたんです。

コードを見てみます。
# ライブラリ読み込み
from PIL import Image
from PIL.ExifTags import TAGS


# 関数の定義 01
def get_exif_of_image(file):
    """Get EXIF of an image if exists.

    指定した画像のEXIFデータを取り出す関数
    @return exif_table Exif データを格納した辞書
    """
    im = Image.open(file)

    # Exif データを取得
    # 存在しなければそのまま終了 空の辞書を返す
    try:
        exif = im._getexif()
    except AttributeError:
        return {}

    # タグIDそのままでは人が読めないのでデコードして
    # テーブルに格納する
    exif_table = {}
    for tag_id, value in exif.items():
        tag = TAGS.get(tag_id, tag_id)
        exif_table[tag] = value

    return exif_table

print get_exif_of_image("sample.jpg")
# => Exif 情報を格納した辞書
#    Exif 情報がない場合には空の辞書

まずは、PIL ライブラリから画像ファイルを開くための Image クラスと Exif 情報を読み取るための TAGS という辞書を読み込みます。

次に、これらを使って実際に画像を読み込み Exif データを取得します。 PIL を使えば、 Exif データは _getexif() メソッドで取得することができます。

get_exif_of_image() に画像ファイル名を渡すと、その情報を返してくれるはずです。


次に、Exif データのうち、日付情報だけを取り出す方法を見てみます。
# 関数の定義 02
def get_date_of_image(file):
    """Get date date of an image if exists

    指定した画像の Exif データのうち日付データを取り出す関数
    @return yyyy:mm:dd HH:MM:SS 形式の文字列
    """

    # get_exif_of_imageの戻り値のうち
    # 日付データのみを取得して返す
    exif_table = get_exif_of_image(file)
    return exif_table.get("DateTimeOriginal")

print get_date_of_image("sample.jpg")
# => yyyy:mm:dd HH:MM:DD 形式の文字列
#    Exif データが存在しない場合は None

上の get_exif_of_image 関数の方で例外処理なんかはしてあるので、こちらの関数ではその戻り値から日付情報を抜き出すだけです。

PIL の場合、日付情報は DateTimeOriginal という名前で扱われるので、これをキーとしてそのまま指定しています。


以上です。

使いどころとしては、画像ファイルの名前のフォーマットを統一したい場合などでしょうか。カメラを複数台使っている場合なんかには、画像ファイルの名前が機種ごとにまちまちだったりするので、それを統一するときなんかには便利だと思います。

あとは、カメラの使用日時を統計データとしてまとめたいとき、なんかでしょうか。


参考
Extracting image EXIF data with Python | Endlessly Curious
In Python, how do I read the exif data for an image? - Stack Overflow
How do I use Python's PIL library to get EXIF data from a photo starting with a hyperlink to the photo? - Stack Overflow

Exchangeable image file format - Wikipedia

2014/11/28

Python Tips:リテラルが if 文で評価されたときの結果を調べたい

Pythonで、各種リテラルが if 文で評価されたときの結果を調べる方法をご紹介します。

結論としては bool 関数を使う形がよいかと思います。

例を見てみます。
# 数値型
print bool(5)  # => True
print bool(0)  # => False
# 文字列型
print bool("Ciao")  # => True
print bool("")  # => False
# リスト型
print bool(["", ""])  # => True
print bool([])  # => False
# 辞書型
print bool({None: False})  # => True
print bool({})  # => False

最後にもうひとつ None を見てみます。
# None
print bool(None)  # => False


デバッグするときなんかに覚えておくと便利かもしれません。

以上です。

2014/11/25

サンプルコード:what_methods in Python

サンプルコード「what_methods」をご紹介します。

from what_methods_python import what

Ruby に「what_methods」というインスペクト用のライブラリがあります。指定したオブジェクトのメソッドのうち、期待した戻り値を返すメソッドだけをリストアップする what? メソッドを提供するライブラリです。

BMorearty/what_methods - GitHub


これがなかなかおもしろくてすてきなので、今回はそのPythonバージョンを作ってみました。

使い方を先に見た方がわかりやすいかと思いますので、まずは使い方から。


使い方

使うのは what 関数ひとつです。

第1引数にオブジェクト、第2引数に期待する結果を渡せば、条件を満たすメソッドをリストに格納して返してくれます。

たとえばこんな感じ。
from what_methods_python import what

print what("hello", 5)
# => ['__len__']
# 文字列 "hello" のメソッドのうち、戻り値が 5 と等しいものを調べています。
# 該当するものとして __len__ メソッドが返されました。

print what(3.14, 3)
# => ['__int__', '__long__', '__trunc__']
# 3.14 という数値のメソッドのうち、戻り値が 3 と等しいものを調べています。
# 該当するものとして複数のメソッドが返されました。
# ちなみに、戻り値の等価チェックは == で行っているため、 long なんかも含まれてきます。

メソッドに渡したい引数は、第3引数以降で指定することができます。
print what(["cat", "dog", "elephant"], "dog", 1)
# => ['__getitem__', 'pop']
# メソッドに渡す引数として 1 を指定しています。
# 該当するものとして __getitem__ pop のふたつが返ってきました。

ちなみに、 __len__ や __getitem__ のようにアンダースコア2つが先頭と末尾に付けられたメソッドはいわゆる特殊メソッドです。

直接呼び出すためではなく、何らか別の使い方をするために作られています。たとえば、 __len__ は len() 関数、 __getitem__ はアクセサ [] に相当します。


使い方はひととおりこんな感じです。あとは関数の中身を見てみます。

関数宣言

少し長いので、スクリプトまるごと Gist の方に置きました。



他から import するのではなく直接実行したらテストが走るようになっています。

以上です。

Python 版 what_methods のお話でした。


参考
BMorearty/what_methods
what_methods_python.py - Gist

2014/11/18

Python Tips:ライブラリをまとめてアンインストールしたい

Pythonでインストール済みのライブラリをまとめてアンインストールする方法をご紹介します。

アンインストールの大きな流れとしては次のとおりとなります。
  1. インストール済みのライブラリをリストアップ
  2. リストを編集
  3. pip uninstall コマンドでアンインストール


以下、順に見ていきます。


インストール済みのライブラリをリストアップ

まずは、どんなライブラリがインストールされているのかチェックします。
$ pip freeze > requirements_bk.txt
$ cp requirements_bk.txt uninstall.txt

もしものときのために復元用をバックアップしておくのがよいでしょう。 requirements_bk.txt は復元用、 uninstall.txt はアンインストール用です。


リストを編集

uninstall.txt を編集し、「削除したいライブラリ」のみの一覧を作成します。削除したいライブラリはリストに残し、残しておきたいものはリストから削除します。

たとえば次のような感じにします。

cssselect==0.9.1
lxml==3.2.4
pyquery==1.2.8


リストの編集が終わったら、あとはpipコマンドを打ち込むだけです。


pip uninstall コマンドでアンインストール

pip uninstall コマンドに r オプションを渡して先ほどの uninstall.txt をしています。
$ pip uninstall -r uninstall.txt

コマンドを実行すると、ライブラリごとに「本当に削除しますか?」という確認ダイアログが(英語で)出るので、本当によければ y を入力していきます。

確認ダイアログが必要ない場合は、 y オプションをつけることで確認なくすべてのライブラリをアンインストールすることができます。
$ pip uninstall -r uninstall.txt -y

万が一何かがあったときや改めてインストールし直したいときは、復元用の requirements_bk.txt を使って
$ pip install -r requirements_bk.txt
で元に戻しましょう。


以上です。


参考
pip uninstall — pip 公式ドキュメント
python - Is there a way to uninstall multiple packages with pip? - Stack Overflow

2014/11/12

Python Tips:行列演算を扱いたい

Pythonで行列演算をする方法をご紹介します。

Pythonで行列を扱うには「 numpy 」というライブラリを使う方法が一般的です。

基本的な使い方を以下、見ていきます。


行列オブジェクトの生成

行列オブジェクトの生成は matrix 関数で行います。
import numpy as np

# 文字列から生成
m1 = np.matrix('1 2; 3 5')

# リストから生成
m1 = np.matrix([[1, 2], [3, 5]])


要素アクセス

行列の要素へのアクセスには、リストと同じ [] を使います。
m1[0, 1]  # 1行目・2列目の要素

行全体、列全体を取得することも可能です。
m1[0]     # 1行目の要素すべて
m1[0, :]  # 同上

m1[:, 0]  # 1列目の要素すべて

m1[3:5, 0:2]  # 3~4行目・1~2列目の部分行列


四則演算

基本的な四則演算は演算子で行えます。
m1 + m2  # 和
m1 - m2  # 差
m1 * m2  # 積 ただし要素同士(追記: まちがい)
m1 / m2  # 商 ただし要素同士(追記: まちがい)

かけ算と割り算については、いずれも行列の積ではなく、要素同士のかけ算・割り算になることに注意が必要です。

追記: 指摘をいただき numpy 1.13.1 で確認をしたところ、演算 m1 * m2m1 / m2 については、要素同士の演算ではなく行列としての演算が行われるようです。この投稿を書いたときの記憶が確かではないのですが、そのとき私は numpy.array (積と商が要素同士の演算になる)と numpy.matrix (積と商が行列としての演算になる)の挙動をごっちゃにして理解、記述したのではないかと思います。。。参考にしていただく方は、ご利用の前にお手元の環境で確認をしてみてください。


メソッド

各種メソッドが用意されています。最大値や平均値など、使用頻度の高そうなものはそのままの名前で用意されています。
m1.max()  # 最大値
m1.min()  # 最小値
m1.mean() # 平均値
m1.all()  # すべて True なら True それ以外は False
m1.any()  # いずれかひとつでも True なら True それ以外は False


行列の積

* 演算子が要素同士のかけ算に割り当てられているため、行列の積は別のメソッド dot を使います。
m3 = m1.dot(m2) 行列の積


その他線形代数的演算

これらの他にも各種行列演算機能が用意されています。
from numpy import linalg as la

# 転置行列
m1_transposed = la.transpose(m1)

# 逆行列
m1_inv = la.inv(m1)

# 固有値
m1_eigenvalue = la.eig(m1)


以上です。

ほんの一部ですが、 numpy の行列機能を見てみました。 numpy には行列以外の数学的機能なども豊富に用意されているので、もっと詳しく知りたい場合は公式ドキュメントをご参照ください。


参考
numpy.matrix — NumPyマニュアル

2014/11/04

ライブラリ:inspect

Pythonの「 inspect 」というライブラリをご紹介します。

import inspect

inspect は、名前のとおり「インスペクト」ーーコードの調査を行うためのライブラリです。オブジェクトの状態や関数のふるまいを調べるための関数群が豊富に用意されています。

以下、 inspect の代表的な関数をいくつか見てみます。


inspect.getmembers()

inspect.getmembers はオブジェクトのメンバ一覧を返す関数です。

組み込み関数 dir の高機能版、と考えるとよいかと思います。

dir の場合はオブジェクトのアトリビュート名だけをリストで返しますが、 getmembers はアトリビュートの名前と中身をペアにして返してくれます。

import inspect

# dir が表示するリストのうち最後の5つだけ表示
print dir("test string")[-5:]
# => ['swapcase', 'title', 'translate', 'upper', 'zfill']

# getmembers が表示するリストのうち最後の5つだけ表示
print inspect.getmembers("test string")[-5:]
# => [('swapcase', <function swapcase>),
#     ('title', <function title>),
#     ('translate', <function translate>),
#     ('upper', <function upper>),
#     ('zfill', <function zfill>)]

inspect.isfunction()

inspect.isfunction はオブジェクトが関数かどうかを判定する関数です。引数に渡されたオブジェクトが関数であれば True 、そうでなければ False を返します。

import inspect

def hello():
    print "hello"

inspect.isfunction(hello)  # => True

if inspect.isfunction(hello):
    hello()  # => hello
    # hello が関数だったときだけ呼び出し

ただし、組み込みの関数を isfunction に渡した場合には戻り値は False となります。

組み込みの関数を調べるには、別の関数 isbuiltin を使います。

また、 inspect.isfunction は数ある is__ 関数のうちのひとつです。他にも次のような関数が用意されています。

  • ismodule モジュールなら True
  • isclass クラスなら True
  • ismethod メソッドなら True
  • isfunction 関数なら True
  • isgeneratorfunction ジェネレータ関数なら True
  • isbuiltin 組み込み関数なら True
  • isroutine 組み込み関数か自作関数なら True

この他にもまだまだたくさんあるので、もっと知りたい場合は公式ドキュメントにあたってみてください。


inspect.getsource()

inspect.getsource は、関数やメソッドのソースコードを取得するための関数です。

def hello():
    print "hello"

inspect.getsource(hello)
# => u'def hello():\n    print "hello"\n'
# hello 関数のコードを表示

以上です。

inspect には、この他にもオブジェクトやインタプリタの状態、ソースコードを調べるための関数などが豊富に用意されています。

詳しくは参考ドキュメントをご参照ください。


参考
27.13. inspect — Inspect live objects — Python公式ドキュメント
pythonのソースコードを読むコツのようなもの - maeda.na@はてな
pythonのinspect で モジュールが定義されているファイル名 をゲットする! - bokuju とか tabe1hands の日記
The GITS Blog » Python introspection with the inspect module
PyMOTW: inspect - O’Reilly ONLamp Blog

2014/10/27

Python Tips:オブジェクトのメソッドを調べたい

Pythonでオブジェクトのメソッドを調べる方法をご紹介します。

大きく2つの方法があるかと思います。
  1. 組み込みの関数で調べる
  2. inspect ライブラリの関数で調べる

順に見ていきます。


組み込みの関数で調べる

こちらは特にライブラリを読み込まなくても使える方法です。

組み込みの dir getattr callable 関数を使います。こんな感じ。
# メソッドを調べたいオブジェクト
# 今回は適当に文字列を使う
obj = ""

# アトリビュート一覧のうち
# callable なオブジェクトのみを表示する
for attr in dir(obj):
    if callable(getattr(obj, str(attr))):
        print attr

メソッド一覧をリストで取得したい場合は次のようにするとよいでしょうか。
obj_methods = [attr for attr in dir(obj) if callable(getattr(obj,  str(attr)))]

ただし、 callable はメソッド以外のオブジェクトーーたとえば関数やクラスに対しても True を返すので、その点は注意が必要です。
print callable(list)  # => True
print callable(lambda x: x)  # => True

class MyClass:
    pass

print callable(MyClass)  # => True

純粋にメソッドだけを抽出したい場合は次の inspect を使うやり方でいくのがよろしいかと思います。


inspect ライブラリの関数で調べる

inspect ライブラリの関数を使う方法もあります。

こちらは inspect の getmembers 関数あたりを使います。たとえばこんな感じ。
# ライブラリの読み込み
import inspect

# 対象オブジェクト
obj = ""

# アトリビュート一覧のうち
# isbuiltin が True を返すオブジェクトのみを表示する
# さらに末尾の5件のみに絞り込み
print inspect.getmembers(obj, inspect.isbuiltin)[-5:]
# => [('swapcase', ), ...]
この場合、組み込みのメソッドか関数のみが表示されます。

getmembers 関数は、オブジェクトのアトリビュート一覧を名前と中身をペアにして返す関数です。 第2引数に関数を渡すとその戻り値が True となるものだけにフィルタしてくれます。

isbuiltin 関数は組み込みの関数やメソッドに対して True を返すものです。

isbuiltin を ismethod などに変えると、自作のメソッドのみに絞り込むことも可能です。
print inspect.getmembers(obj, inspect.ismethod)
# => obj の自作メソッド一覧

inspect には他にも細かく判定する関数がいくつも用意されているので、適切な関数を選んで使われるとよろしいかと思います。


以上です。


参考
How do you get list of methods in a python class? - Stack Overflow
python - Finding what methods an object has - Stack Overflow
27.13. inspect — Inspect live objects — Python公式ドキュメント

2014/10/21

Python Tips:リストを指定した数の要素ごとにまとめたい

Pythonで、リストの要素を指定した数でグルーピングして返す方法をご紹介します。

最もシンプルなやり方は range でステップを指定しながらループを回してスライスする方法かと思います。
# 0, 1, 2, ... 14 のリストを作成
li = list(range(15))

# 要素を3つずつ順番にグループ化
group_by = 3
[li[i:i + group_by] for i in range(0, len(li), group_by)]
# => [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14]]
# 3 つずつに区切られたリストが返される

その他の方法としては、 iter 関数と zip 関数、スプラット演算子などを組み合わせて合わせ技で作る方法なんかもあります。
# 0, 1, 2, ... 14 のリストを作成
li = list(range(15))

group_by = 3
chunks = zip(*[iter(li)]*group_by)
print chunks
# => [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14)]
ただ、この場合はなぜこうなるのか一目ではわからない感じです。。ほんの数文字の間にいろんな処理が挟まっていてテクニックとしては面白いのですが、、あくまでもトリック的な感じですかね。。

以上です。


参考
How do you split a list into evenly sized chunks in Python? - Stack Overflow
2. Built-in Functions — Python公式ドキュメント

2014/10/14

Python Tips:Python2 で Python3 の print 関数を使いたい

Python2でPython3の print 関数を使う方法をご紹介します。

__future__ ライブラリから print_function をインポートすることで、Python3のものと同等の print 関数が使えるようになります。
from __future__ import print_function

Python3の print 関数であれば、Python2の print 文にはなかったさまざまなオプションが使えるようになります。

たとえば、複数の引数を print 関数に渡したときの区切り文字を指定するには、 sep オプションを使います。
print("Red", "Hot", "Chili", sep="\n")
# => 改行つきで Red Hot Chili が順に表示される

末尾の改行コードをコントロールしたい場合には end オプションを使います。
from __future__ import print_function

print("Red", "Hot", "Chili", end="")  # => Red Hot Chili
# 末尾に改行コードが追加されない
これはPython2 で print value, と最後に , をつけるのと近い感じですね。

出力先を標準出力ではなくファイルに変えたい場合は、 file オプションにファイルオブジェクトを渡します。
f = open("test.txt", "w")

print("Red", "Hot", "Chili", file=f)

f.close()
# test.txt ファイル内に Red Hot Chili と書き込まれる


以上です。

使いどころは多くはなさそうですが、、万が一Python2のコードの中でPython3スタイルの print 関数を使う必要が出てきたときには、いいかもしれません


参考
PEP 3105 print as a function - What’s New in Python 2.6

2014/10/07

ライブラリ:re

Pythonの「 re 」というライブラリをご紹介します。

import re

re は正規表現を扱うためのライブラリです。 re = Regular Expression の略ですね。

re の基本的な使い方を以下、見ていきます。


re.search

re.search は探索のための関数です。与えられたテキストの中の正規表現パターンを探索します。

例えばこんな感じ。
# ライブラリ読み込み
import re

# 対象テキスト
text = """
When you were born,
you cried and the world rejoiced.
Live your life so that when you die,
the world cries and you rejoice.
"""

# 一致するパターンを検索
# 「d」で終わる単語を探す
result = re.search(r"\w+d", text)

# 見つかれば結果を表示
# 見つからなければ no match とだけ表示
if result:
    print result.group()  # => 最初に一致したパターン
    print result.start(), result.end()  # => 一致した箇所のインデックス
    print result.span()  # => 上の start と end のタプル
else:
    print "no match"

re.search が返す値は、一致するパターンが
見つかった場合 マッチオブジェクト
見つからなかった場合 None
となりますので、上の例のように search の戻り値を if で判定することによって見つかった場合と見つからなかった場合の処理を分けることができます。


re.findall

re.findall も探索のための関数です。
re.search が一致したパターンをひとつだけ返すのに対し、 re.findall はすべての一致パターンを返します。

こちらも例を。
results = re.findall(r"\w+d", text)

# 見つかれば結果を表示
# 見つからなければ no match とだけ表示
if results:
    # 一致したパターンを空白区切りですべて表示
    for r in results:
        print r,
        print ""
    else:
        print "no match"

findall は結果をすぐさまリストにしますが、同様の処理をして結果をイテレータとして返すものとして finditer という関数もあります。


re.split

re.split は分割のための関数です。指定した正規表現パターンを区切り文字にしてテキストを分割します。結果はリストで返ってきます。

こんな感じです。
sentences = re.split(r"\W", text)

print sentences
# => text をアルファベットと数字以外のすべての文字を区切り文字にして分割したリスト


re.sub

re.sub は置換のための関数です。正規表現パターンと一致する部分を別の文字列に置換した文字列を返します。

こんな感じです。
text_replaced = re.sub(r"\w+d", "***", text)

print text_replaced  # => d で終わる単語がすべて *** に置換された文字列

デフォルトでは、一致したパターンがすべて置換されて返ってきます。

置換する最大数を指定したい場合はキーワード引数 count を使います。
text_replaced = re.sub(r"\w+d", "***", text, count=3)

こうすると、 count に指定した数値を上限回数として置換してくれます。


以上です。

今回はこの4つの関数を見てみました。
  • re.search 検索 1つだけ
  • re.findall 検索 複数個 ジェネレータの re.finditer も存在する
  • re.split 分割
  • re.sub 置換

これらの他にも、関数 re.compile (正規表現パターンオブジェクトを生成できる関数)や正規表現オプションなど、正規表現がらみの便利な機能が豊富に用意されています。

詳しく知りたい場合は、参考ページを参照してみてください。


参考
Python Regular Expressions - Educational Materials — Google Developers
Regular Expressions in Python. Python Tutorials.
Regular Expression HOWTO — Python公式ドキュメント

Pythonでの正規表現の簡単なまとめ - minus9dの日記
正規表現 (Regular Expression) - Python 入門

追記20141009
参考リンクの Google Developers のページを日本語訳されている方がいるということでコメントをいただきました。こちらもよろしければ。
Python の正規表現 - 手習い録

2014/09/23

Python Tips:Pythonでクロージャを使いたい

Pythonでクロージャを使う方法をご紹介します。

具体的な説明に入る前に、そもそもクロージャとはなんぞや、というところから行きたいと思います。


クロージャとは

クロージャとは「関数内の変数の名前解決が、その関数が宣言されたときのスコープによって行われるもの」です。

もう少し丁寧にいうなら、クロージャとは、

- 関数内のローカル変数以外の名前解決が、
- 呼び出し時のスコープではなく、
- 宣言時のスコープによって行われるもの。
- またそのような機能を持った関数のこと。

です。

例があるとわかりやすいです。たとえば次の場合。
x = 1
def get_x():
    return x

class MyClass(object):
    x = 10
    print get_x()  # 10 ではなく 1 が返される

MyClass 内の print get_x() は何を出力するでしょうか? 10 ? 1 ?それとも None でしょうか?答えは「 1 」です。

なぜなら、 get_x() の中の x は「呼び出し時のスコープではなく定義時のスコープ」から取得され、また、 Python の名前解決のルールには「LEGB」というものがあるからです。

この仕組みがクロージャです。

ちなみに Wikipedia には次のような説明が載っています。
In programming languages, a closure (also lexical closure or function closure) is a function or reference to a function together with a referencing environment—a table storing a reference to each of the non-local variables (also called free variables or upvalues) of that function.[1] A closure—unlike a plain function pointer—allows a function to access those non-local variables even when invoked outside its immediate lexical scope.
(意訳)
クロージャ(またはレキシカルクロージャ、関数クロージャ)とは、参照環境を伴ったような関数、あるいはその関数への参照のことを指します。参照環境というのは、特定の関数が持つ、ローカル環境にはない変数(自由変数あるいは upvalue )への参照を保持したテーブルのことです。通常の関数ポインタとは異なり、クロージャによって、関数が別のスコープで呼び出されたときにおいてもそこのローカル変数以外の変数にアクセスすることが可能となります。

わかるようなわからないような・・・概念的な説明はちょっと難しいですね。。でも、実際のコードを見るとその意味は明白です。

クロージャの使い方

では、クロージャの使い方を見てみましょう。

Pythonでは「関数内関数が定義できる」というのと「関数がスコープを分けてくれる」という特徴を利用して、次のようなことができます。
# coding: utf-8

def gen_circle_area_func(pi):
    """円の面積を求める関数を返す"""
    def circle_area(radius):
        # ここの pi は circle_area_func に渡された pi が使われる
        return pi * radius ** 2  
    
    return circle_area

# 円周率を 3.14 として円の面積を計算する関数を作成
circle_area1 = gen_circle_area_func(3.14)
print circle_area1(1)  # => 3.14
print circle_area1(2)  # => 12.56

# 次は、円周率の精度をぐっと上げて
# 円周率 3.141592 で円の面積を計算する関数を作成
circle_area2 = gen_circle_area_func(3.141592)
print circle_area2(1)  # => 3.141592
print circle_area2(2)  # => 12.566370614

circle_area1() circle_area2() はいずれも「円の半径を引数に受け取りその面積を返す関数」です。

ロジックは同じですが、それぞれ参照する pi の値が異なるため、計算の精度が異なっています。

このようにクロージャの特徴を使えば、関数を生成して返す関数をひとつ作っておくだけで「ロジックは同じだけどその内部で使用するパラメータが異なる関数」を動的に作成することができます。この仕組みにより、「変数だけでなく処理(=関数)を部品化し使いまわせる」という特徴(関数型言語的特徴)が言語に加わります。


また別の例を見てみましょう。
def fibonacci_func():
    """フィボナッチ数列を返す関数を返す メモイズ機能つき"""
    table = {}  # 計算済みのフィボナッチ数列を格納するテーブル

    def fibonacci(n):
        # 計算したことのある数値についてはテーブルを参照して返す
        if n in table:
            return table[n]

        # 計算したことのない数値についてはフィボナッチ数列の定義どおり計算
        if n < 2:
            return 1
        table[n] = fibonacci(n - 1) + fibonacci(n - 2)
        return table[n]

    return fibonacci


# 関数を生成してから 50 番までのフィボナッチ数列を計算して表示する
f = fibonacci_func()
for i in range(50):
    print f(i)
こちらはフィボナッチ数列を計算して返す関数です。クロージャのおかげで、グローバル変数を作ることもクラスを作ることもなく、関数だけでメモイズ機能が実現できています。 フィボナッチ数列をメモ化なしで50番目くらいまで求めると結構な時間がかかると思うのですが、このようなメモ化を行うと一瞬で出てきます。 ちなみに、クロージャとなった関数には __closure__ というプロパティがあり、その中身をのぞくと、その関数が持つ「参照」が「セルオブジェクト」として収められていることが確認できます。
print f.__closure__  # => セルオブジェクトのリスト
print f.__closure__[0].cell_contents  # => fibonacci 関数そのものを表すセルオブジェクト
print f.__closure__[1].cell_contents  # => table を表すセルオブジェクト
以上です。 他にもよい例が出てこれば追加していければと思います。 参考 Pythonのクロージャ その1 Closures in Python - Stack Overflow a life of coding: Closures in Python Python Closures Explained | Shut Up and Ship Understanding Python's closures Closure (computer programming) - Wikipedia, the free encyclopedia

2014/09/16

Python の内包表記の使い方まとめ

Python の内包表記についてまとめてみました。


内包表記とは?

内包表記とは、リストや辞書などの iterable オブジェクト( for ループで回せるオブジェクト)のループ処理をかんたん・シンプルに記述できる記法です。

たとえば、 1 から 5 までの数値を 2 乗した値を持つリストを作りたい場合。次のような式を書けばそのリストが得られます。

[x ** 2 for x in [1, 2, 3, 4, 5]]
# => [1, 4, 9, 16, 25]

通常の for ループと同じ for element in collection というブロックを書いて、その前に各要素の値を書いて、 [] で囲みます。この書き方が「内包表記」です。

ちなみに、「内包」は英語で「 comprehension 」というそうです。また、「内包」の逆は「外延」( extension )とのこと。内包と外延は数学の集合論における表現方法のようです。

このあたりの概念について詳しくは Wikipedia などが参考になります。

内包と外延 - Wikipedia


種類

内包表記の種類として次の4つがあります。

  1. リスト内包
  2. ジェネレータ式
  3. セット内包表記
  4. 辞書内包


内包表記といえば、基本は「リスト内包」かと思うのですが、「リスト内包」のほかにも「ジェネレータ式」、「内包表記のセット版や辞書版」というものが存在します。

以下順に見ていきましょう。


リスト内包

リスト内包は [] で定義します。リストを返してくれます。
[x + 2 for x in range(5)]
# => [2, 3, 4, 5, 6]


ジェネレータ式

ジェネレータ式はリスト内包の最初と最後の [] の部分を () に変更したものです。戻り値はリストではなく、要素をひとつずつ生成するイテレータとなります。

(x + 2 for x in range(5))
# => <generator object <genexpr> at 0x106017db0>

PEP 289 -- Generator Expressions | Python.org


セット内包表記

セット内包は {} で定義します。

{x + 2 for x in range(5)}
# => {2, 3, 4, 5, 6}


辞書内法

辞書内法も {} で定義します。辞書を返してくれます。セット内包とのちがいは、各要素の値の部分が key: value という形になっている店です。

li = [("C", 1972), ("Java", 1995), ("JavaScript", 1995)]
{k: v for k, v in li}
# => {'C': 1972, 'Java': 1995, 'JavaScript': 1995}
要素を定義する部分が「k: v」となっている点がセット内包表記とは異なります。

次に、使い方のパターンをいくつか見てみます。


いろいろな使い方

内包表記では基本的なループの他にも多重ループやフィルタ処理なども行うことができます。

内包表記以外の機能をあわせて、いくつかのパターンをあげてみます。

基本のループ:
# 通常の1重ループ  map のようなもの
[x ** 2 for x in range(10)]

基本のループ + フィルタ:
# if 節の条件が成り立つもののみをリストに含める filter のようなもの
[x ** 2 for x in range(10) if x % 2 == 0]

複数要素のループ:
# 複数のリストを同時に回す方法  zip を使う
[x * y for x, y in zip([1,2,3], [11,12,13])]

多重ループ:
# 独立した2つのリストを2重ループとして回す
[x + y for x in range(3) for y in [100, 200, 300]]

ネスト:
# 入れ子になった要素を2重ループとして回す
# 順番は、外側のループを先に書き、内側のループを後に書く
[x for inner_list in [[1, 3], [5], [7, 9]] for x in inner_list]

条件によって値を変える:
# 値の部分に if else 式を使う
[x if x % 3 == 0 else 'fizz' for x in range(10)]

条件によって値を変えて fizzbuzz:
# きれいじゃないけど if else の入れ子も可能
[('fizzbuzz' if x % 15 == 0 else ('fizz' if x % 3 == 0 else ('buzz' if x % 5 == 0 else x))) for x in range(1, 30)]

while ループ:
# ジェネレータ式と itertools.takewhile で while 条件の指定も可能
from itertools import takewhile

takewhile(lambda x: x < 30, (n for n in range(100)))

takewhile を使わずに途中で break:
# while ループと同じことを if else 式で実現
def end_of_loop():
    raise StopIteration

list(x if x < 10 else end_of_loop() for x in range(100))
# 次の書き方でもOK
# list(x if x < 10 else next(iter([])) for x in range(100))


最後の StopIteration 例外を使った break なんかはちょっと飛び道具というかトリック的小技になりますが、こういうこともできる、ということは覚えていてもよいかもしれません。

以上です。


参考
generator - python one-line list comprehension: if-else variants - Stack Overflow
python - break list comprehension - Stack Overflow
List Comprehensions in Python. Python Tutorials.
List Comprehensions — Python公式ドキュメント

2014/09/09

Python Tips:ベクトル演算を扱いたい

Python でベクトル演算を行う方法をご紹介します。

結論からいえば「 numpy 」というライブラリを使う方法が最も一般的かと思います。

以下、 numpy を使った基本的なベクトル演算のやり方を見ていきます。

足し算はこんな感じ。
# ライブラリの読み込み
from numpy import array

# ベクトル演算をサポートした array インスタンスの生成
v1 = array([1, 3])
v2 = array([2, 5])

# ベクトル同士の演算
v3 = v1 + v2
print v3  # => array([3, 8])
# ベクトル同士の足し算

足し算と同様に引き算も可能です。
v4 = v1 - v2  # => array([-1, -2])

かけ算も。
v1 * v2  # => array([2, 15])
# 要素同士の掛け算

* 演算子は内積ではなく「要素同士のかけ算」であることに注意が必要です。他のツールで「 * は内積」に馴染んでいる方は要注意です。

内積を使うには * ではなく dot メソッドを使います。
v1.dot(v2)  # => 17 (1*2 + 3*5 の結果)

割り算もサポートされています。こちらも要素同士。
v2 / v1  # => array([2, 1]) 

スカラー値との演算も可能です。
v1 * 2  # => array([2, 6])
2 * v1  # => array([2, 6])

通常のリストとの演算もできてしまいます。これは個人的には気持ち悪いです。。
v1 * [2, 1]  # => array([2, 6])


以上です。

numpy はベクトルだけでなく行列やその他多くの数学的機能を収めたライブラリなので、もっと詳しく知りたい方は公式ページをご参照ください。


参考
Tentative NumPy Tutorial -


2014/09/02

ライブラリ:doctest

Pythonの「 doctest 」というライブラリをご紹介します。

import doctest

doctest は、名前に doc + test とあるとおり、ドキュメントによってテストを行うためのライブラリです。

具体的には、関数やクラスの内部のいちばん最初にあらわれるコメント、いわゆる docstring の中にテストコードを書いてしまおうというものになります。

具体的に見ていきましょう。

以下、 int 型の数値が偶数かどうかをチェックして返す関数を作っていきながら、 doctest を使ってみることにします。


偶数かどうかをチェックチェックする関数

偶数かどうかをチェックする関数、こんな感じになるでしょうか。
def is_even0(number):
    return number % 2 == 0

ここに doctest でテストケースを追加していきます。


doctest 最初の一歩

is_even1 と名前を変えて、 docstring 内に関数の説明とテストを書いてみます。
def is_even1(number):
    """check if number is even or not
    if even, return true, else false.

    >>> is_even1(2)
    True

    >>> is_even1(5)
    False
    """

    return number % 2 == 0


if __name__ == "__main__":
    import doctest  # ライブラリの読み込み
    doctest.testmod()  # このモジュール内のテストの実行

これが doctest の最小単位になります。

docstring 内の
    >>> is_even1(2)
    True
のようなブロックがひとつのテストケースになります。

書式としてはPythonの対話型モードのように >>> のあとにコードを書いて、期待する結果をその次の行に >>> をつけずに書く形になります。

複数のテストケースを書く場合は、空行をはさんでから書いていきます。

ここでは実際に is_even1(2) と is_even(5) 、ふたつのテストケースが書かれています。

この docstring 内に書かれたテストを走らせるには、上記スクリプトを保存して -v オプションをつけて実行します。
$ python even_module.py -v
Trying:
    is_even1(2)
Expecting:
    True
ok
Trying:
    is_even1(5)
Expecting:
    False
ok
ok
1 items had no tests:
    __main__
1 items passed all tests:
   2 tests in __main__.is_even1
2 tests in 2 items.
2 passed and 0 failed.

すると、個別のテスト結果とサマリーが返ってきます。

-v オプションをつけなかった場合は、テストに失敗したときにだけ出力が行われ、成功したときには何も表示しない形になります。

テストを実際に走らせているのは、コードの一番下、 if __name__ == ... 以降の部分です。この、 import doctest と doctest.testmod() のペアは doctest を走らせるための基本パターンです。

また、 if __name__ == ... を書かないで、実行時に doctest を import して走らせることも可能です。そうしたい場合には次のように -m オプションで doctest を読み込みます。
$ python -m doctest even_module.py -v

結果は if __name__ == ... と書いた場合と同じです。

つづいて、テストケースを追加してみます。


doctest 二歩目

is_even1 では int 型の値が渡されることを前提としていました。次はそうではなく、他の型が渡される可能性も考慮した関数を作ってみます。

int 以外の型が渡されたときにはエラーをあげるようにしましょう。そのための doctest のテストコードも追加することにします。

def is_even2(number):
    """check if number is even or not
    if even, return true, else false.

    @param
    number : int

    >>> is_even2(2)
    True

    >>> is_even2(5)
    False

    >>> is_even2("%s")
    Traceback (most recent call last):
    ...
    TypeError: not an integer
    """

    if type(number) != int:
        raise TypeError("not an integer")
    return number % 2 == 0


if __name__ == "__main__":
    import doctest  # ライブラリの読み込み
    doctest.testmod()  # このモジュール内のテストの実行

追加されたコードは
    if type(number) != int:
        raise TypeError("not an integer")

で、追加されたテストケースは
    >>> is_even2("%s")
    Traceback (most recent call last):
    ...
    TypeError: not an integer
です。

新たなテストケースでは、何らかの値が返ってくるかどうかではなく、想定した例外があがるかどうかをチェックしています。

特定の例外はあがることを期待する場合は次のように書きます。
    Traceback (most recent call last):
    ...
    TypeError: not an integer

最初の2行は定型文となっています。2行目は「省略」の意味を込めて ... と書く形になっているようです。


以上です。

ほんのちょっとだけですが、 doctest の基本的な使い方を見てみました。


もっと踏み込んで使いたい場合は、もろもろドキュメントや参考情報をご参照ください。


参考
doctest introduction - Python Testing
25.2. doctest — Test interactive Python examples — Python公式ドキュメント
Pythonで簡単な単体テストをはじめよう - doctest - tomoemonの日記
Python でテスト - Qiita [キータ]

2014/08/25

ライブラリ:operator

Pythonの「 operator 」ライブラリをご紹介します。

operator ライブラリは、その名のとおり「演算子」のライブラリ。組み込みで用意されているさまざまな演算子を関数で実現したものが含まれたライブラリとなっています。

まずは基本的な使い方から。

基本的な使い方

基本的には、本来演算子に渡しているリテラルや変数を operator で用意されている関数にそのまま渡せばOKです。
# ライブラリの読み込み
import operator

# + と同じ処理を行う関数 add と __add__
print operator.add(2, 3)  # => 5
print operator.__add__(2, 3)  # => 5

ここで add と __add__ は同じふるまいをする関数です。 add 以外の関数でも、ほとんどのものには abc というバージョンと __abc__ というアンダースコアつきバーションの2バージョンが用意されています。


以下、代表的な関数をグループ別に見ていきます。

  • 四則演算
  • 数学単項演算
  • 比較演算
  • 論理演算
  • シフト演算
  • 要素アクセス
  • アトリビュートアクセス
  • メソッド呼び出し



四則演算

四則演算その他の数学二項演算はそれぞれ次のような関数として用意されています。
print operator.add(2, 3)  # +
print operator.sub(2, 3)  # -
print operator.mul(2, 3)  # *
print operator.div(2, 3)  # /
print operator.mod(2, 3)  # %
print operator.pow(2, 3)  # **


数学単項演算

+ と - 、数値処理で使うふたつの演算子はそれぞれ pos と neg に相当します。
print operator.pos(-2)  # +
print operator.neg(-2)  # -


比較演算

各種比較演算子の関数版も用意されています。いずれも less than 、 less equal 、 greater than などの略ですね。
print operator.lt(2, 3)  # <
print operator.le(2, 3)  # <=
print operator.eq(2, 3)  # ==
print operator.ne(2, 3)  # !=
print operator.ge(2, 3)  # >=
print operator.gt(2, 3)  # >

print operator.is_([], [])  # is
print operator.is_not([], [])  # is not


論理演算
論理演算を行う演算子として not_ truth などが用意されています。
print operator.not_(False)  # not
print operator.truth(True)  # bool


シフト演算

ビットシフト演算 << >> に相当する関数は lshift rshift という名前です。
print operator.lshift(9, 1)  # <<
print operator.rshift(9, 1)  # >>


要素アクセス 基本版

リストやタプルの要素アクセスに使う [] の関数版も用意されています。セッタ、ゲッタがそれぞれ getitem setitem で、要素を削除する delitem もあります。
li = [7, 5, 3]

print operator.getitem(li, 1)  # []
# => 5

operator.setitem(li, 1, 10)  # [] =
print li  # => [7, 10, 3]

operator.delitem(li, 0)
print li  # => [10, 3]


要素アクセス 関数版

上述の getitem setitem delitem は直接処理を行うものでしたが、処理は直接行わず「アクセスするための関数」を返してくるものも用意されています。
li = [7, 5, 3]

myfunc = operator.itemgetter(0)
print myfunc(li)  # li[0]
# => 7

この itemgetter の使いどころとしては、たとえば、高階関数に渡して使うケースが考えられます。
from operator itemgetter

li = [('C', 1972), ('Java', 1995), ('Go', 2009)]

print map(itemgetter(-1), li)  # => [1972, 1995, 2009]

これを getitem で書こうとすると次のような感じになってしまいます。
from operator itemgetter

li = [('C', 1972), ('Java', 1995), ('Go', 2009)]

print map(lambda x: getitem(x, -1), li)  # => [1972, 1995, 2009]


アトリビュートアクセス 関数版

こちらはオブジェクトのアトリビュートを取得するための関数。
class MyClass(object):
pass
myobj = MyClass()
myobj.name = "p"
myobj.age = 54

mygetter1 = operator.attrgetter("name")  # name を取得する関数
print mygetter1(myobj)  # => "p"

mygetter2 = operator.attrgetter("name", "age")  # name と age を取得する関数
print mygetter2(myobj)  # => ("p", 54)

この attrgetter を使うと、通常は . に続けて直接書かないといけないアトリビュート名を文字列で指定することができます。


メソッド呼び出し

メソッド呼び出しを行うための関数も用意されています。
s1 = "abracadabra"

mycaller = operator.methodcaller("split", "a")  # obj に対して obj.split("a") を行う関数
print mycaller(s1)  # => ['', 'br', 'c', 'd', 'br', '']

上述のアトリビュートの場合と同じく、通常は obj.somemethod(*args) という形で呼び出すメソッドを関数化して、別のスタイルで呼び出すことが可能です


Rubyでいう send メソッドのような感じですかね。


以上です。

用意されている関数は他にもまだまだあるので、詳しくは公式ドキュメントをご参照ください。



参考
9.9. operator — Standard operators as functions — Python公式ドキュメント
演算子と対応する関数の対応表 - Python公式ドキュメント


2014/08/19

Python Tips:クラスの継承関係をチェックしたい

Pythonで「クラス間の継承関係をチェックする方法」をご紹介します。

クラスの継承関係をチェックするために使える関数として、次の2つの関数があります。
issubclass
mro

以下、順番に見ていきます。まずは issubclass から。


issubclass
issubclass は引数を2つ取る関数で、ひとつめにサブクラスを、ふたつめにスーパークラスを受け取ります。

ひとつめの引数に渡したクラスがふたつめに渡したクラスのサブクラスであれば True 、そうでなければ False を返してくれます。

たとえばこんな感じ。
# スーパークラス Dog
class Dog(object):
    pass

# サブクラス BigDog
# Dog を継承しているので継承関係は BigDog < Dog < object
class BigDog(Dog):
    pass

print issubclass(BigDog, Dog)  # => True
print issubclass(BigDog, object)  # => True

BigDog と object のように、ふたつのクラスが直接の親子関係にない場合も、祖先/子孫のどこかにあれば True を返してくれます。


mro
mro は引数にクラスを受け取る関数です。受け取ったクラスの祖先クラスを「名前解決を行う順番に並べた上で」リストに格納して返してくれます。

Rubyでいうなら ancestors メソッドでしょうか。

ちなみに mro というのは Method Resolution Order (メソッド名前解決順序)の略だそうです。そのまんま!

実際の使い方はたとえばこんな感じです。
# スーパークラス その1
class Pug(object):
    pass

# スーパークラス その2
class ShihTzu(object):
    pass

# パグとシーズーを両親に生まれたサブクラス
# パズー
class PugZu(Pug, ShihTzu):
    pass

# PugZu に対して mro() を呼び出す
print PugZu.mro()
# => [__main__.PugZu, __main__.Pug, __main__.ShihTzu, object]
# メソッドの名前解決を行う順番で基底の object までさかのぼって表示する

PugZu をレシーバに mro を呼び出すと、 PugZu の祖先となるクラスがすべて表示されます。

まわりくどいやり方ですが、この mro 関数と in を使えば issubclass と同じ結果を得ることなども可能です。
print ShihTzu in PugZu.mro()
# => True
# issubclass でチェックしたのと同じ結果が現れる


以上です。


参考
python - Test if a class is inherited from another - Stack Overflow
The Python 2.3 Method Resolution Order - Python公式ドキュメント



2014/08/11

Python Tips:文字列を複数の区切り文字で分割したい

Pythonで、複数の区切り文字を使って文字列を分割する方法をご紹介します。

結論としては、 re.split を使うやり方がよろしいかと思います。

例として、次の文章を単語に分けてみます。

"I Have a Dream" is a public speech delivered by American civil rights activist Martin Luther King, Jr. on August 28, 1963, in which he called for an end to racism in the United States. Delivered to over 250,000 civil rights supporters from the steps of the Lincoln Memorial during the March on Washington, the speech was a defining moment of the American Civil Rights Movement.
I Have a Dream - Wikipedia

import re

t1 = '"I Have a Dream" is a public speech delivered by American civil rights activist Martin Luther King, Jr. on August 28, 1963, in which he called for an end to racism in the United States. Delivered to over 250,000 civil rights supporters from the steps of the Lincoln Memorial during the March on Washington, the speech was a defining moment of the American Civil Rights Movement.'

words1 = filter(lambda w: len(w) > 0, re.split(r'\s|"|,|\.', t1))
# => 空白 " , . などを区切り文字として分割された単語のリスト

re.split には、第1引数に区切り文字を正規表現パターンで、第2引数に分割したい文字列を渡します。第1引数に r'\s|"|,|\.' というパターンを渡しているので、空白やカンマ、ピリオドで区切られた文字列を返す形になっています。

re.spilt の結果に filter をかけているのは、区切り文字が連続した場合などに生じる空文字列要素を削除するためです。


以上です。

ちなみに、 str 型にも split というメソッドが用意されているのですが、こちらは単一の文字列パターンのみを受け付けるため、複数の区切り文字を使うことはできないようです。


参考
Python: Split string with multiple delimiters - Stack Overflow

2014/08/08

Python Tips:オブジェクトにメソッドを追加したい

Python で、既存のオブジェクトにメソッドを追加する方法をご紹介します。

既存のオブジェクトにメソッドを追加する方法は 2 通りあります。

  1. そのオブジェクトのクラスのインスタンスメソッドを追加する
  2. そのオブジェクトだけにインスタンスメソッドを追加する

以下そのそれぞれについて方法を見ていきましょう。


そのオブジェクトのクラスのインスタンスメソッドを追加する


こちらはオブジェクト生成の前でも後でもどちらでもよいので、そのオブジェクトが所属するクラスのプロパティを追加します。

次のコードではこのアプローチで Dog クラスのインスタンス pochi の生成後にインスタンスメソッドを追加しています。

# クラスを定義しインスタンスを生成
class Dog(object):
    pass

pochi = Dog()

# 追加したいメソッドを関数として定義しクラスのプロパティに追加
def count(self):
    print("one! one!")

Dog.count = count

# 追加したメソッドが生成済みのオブジェクトからも利用できる
pochi.count()  # => one! one!


そのオブジェクトだけにインスタンスメソッドを追加する


もう一方のこちらは、クラス全体ではなくひとつのオブジェクトだけにメソッドを追加する方法です。

これは Ruby でいうところの「特異メソッド」的な位置づけのものになるでしょうか。

このアプローチを使うには types ライブラリの MethodType を利用します。
次のコードも上掲のコードと同じく pochi オブジェクトにメソッドを追加していますが、このメソッドは pochi 限定のものとなっています。

 
# MethodTypes を利用するために import
import types

# Dog クラスを定義しインスタンス pochi を生成
class Dog(object):
    pass

pochi = Dog()

# pochi に追加したいメソッドを関数として定義
def count(self):
    print("one! one!")

# count メソッドを実際に追加
pochi.count = types.MethodType(count, pochi)

# 追加したメソッドが生成済みのオブジェクトからも利用できる
pochi.count()  # => one! one!

# 同じクラスのインスタンスからはもちろん利用できない
Dog(object).count()  # AttributeError

・・・以上です。


参考

python - Adding a Method to an Existing Object - Stack Overflow
types — Names for built-in types — Python 公式ドキュメント

2014/08/01

Python Tips:既存のクラスにインスタンスメソッドを追加したい

Pythonで、既存のクラスにインスタンスメソッドを追加する方法をご紹介します。

既存のクラスにメソッドを追加するには次の手順を踏みます。
まず関数を別途定義してから
その関数名をクラスのアトリビュートにする

具体例を見てみます。
# __init__ メソッドだけを備えた Dog クラス
class Dog(object):
    def __init__(self, name):
        self.name = name

# 以下で Dog クラスに count_number というインスタンスメソッドを追加する
# 01 まずは関数を定義
def count_number(self):
    print "%s counts: one! one!" % self.name

# 02 定義した関数をクラスのアトリビュートに追加
Dog.count_number = count_number

# 結果
taro = Dog("Taro")
taro.count_number()  # => Taro counts: one! one!
# count_number がインスタンスメソッドとして機能している

最初に Dog クラスを定義したときには存在しなかった count_number というメソッドが、最後にはインスタンスをレシーバとして呼び出せていることがわかります。

定義した関数をクラスのアトリビュートに追加するところは、そのままずばりな setattr という関数を使って書くことも可能です。
setattr(Dog, "count_number", count_number)

関数名をそのままメソッド名にしてもよい場合は、次のように関数化しておくと繰り返しが避けられます。
# 既存のクラスにインスタンスメソッドを追加する関数
def add_instance_method(Klass, method):
    setattr(Klass, method.__name__, method)  # method.__name__ は関数名を表す


このようなふるまいを見ると、「Pythonにおいてインスタンスメソッドというのはレシーバ自身が第一引数に渡されるクラスメソッドにすぎない」ということがよくわかります。

ちなみに、Rubyのように組み込みの型(クラス)にメソッドを追加するということはPythonではできません。このあたりは、どこを重視するかの考え方のちがい、でしょうか。

以上です。


参考
Python - cool things I've discovered
python - Adding a Method to an Existing Object - Stack Overflow

2014/07/28

サンプルコード:Hello World

Pythonのサンプルコードをご紹介します。

サンプルコードシリーズを今後永く継続していければと思います。初回の今回はせっかくなので hello world を。

Pythonの Hello World は次のように書きます。
print "Hello World"

Python3 ならこんな感じ。
print("Hello World")

明示的なライブラリ読み込みを行ったり main 関数を書いたりする必要はありません。

このコードを hello.py などという名前で保存し、コマンドラインから
$ python hello.py
と実行すると、標準出力に Hello World と返ってきます。

また、日本語を使う場合は文字コードの指定が必要です。
# coding: utf-8

print "こんにちは"

以上です。

2014/07/16

Python Tips:ライブラリ・モジュールの場所を調べたい

Pythonでライブラリ(モジュールやパッケージ)がどのディレクトリに入ってるのか、その場所を調べる方法についてご紹介します。

ライブラリの場所は、モジュールの __file__ アトリビュートか __path__ アトリビュートで調べることができます。

import datetime
print datetime.__file__
# => datetimeモジュールの場所

import json
print json.__path__
# => jsonパッケージの場所

__file__ と __path__ のちがいとしては
  • __file__ モジュールの本体か __init__.py の絶対パス
  • __path__ パッケージのディレクトリの絶対パス(の配列)
というところになります。

ですので、 __file__ はそのライブラリがモジュール(1ファイルのライブラリ)の場合でもパッケージ(複数ファイルのライブラリ)の場合でも動作しますが、 __path__ の方はパッケージの場合限定のアトリビュートとなるようです。


参考
[ Python ] モジュールの場所 - memlog
How do I find the location of Python module sources? - Stack Overflow
python - how to get module location - Stack Overflow

2014/07/01

ライブラリ:IPython その1

「 IPython 」という Python のライブラリについてご紹介します。


IPython とは、一言でいうと「 Python の対話型モードの強化版」です。 Python 環境をインストールするとデフォルトで付いてくる対話型 Python にさまざまな便利機能を追加したようなものになります。

Ruby をご存知の方であれば「 Python 版の pry 」と表現するとわかりやすいかもしれません。

基本的には、デフォルトの対話型モードと同じ使い方をします。

IPython には、大きく分けて

  • 純粋な CUI モード
  • ブラウザを使ったモード

の 2 つの使い方があります。

今回はこのうちの前者「純粋な CUI モード」に絞って見ていきたいと思います。詳しい解説はすでに多くの方がされているので、ここでは基本的な部分をざっとご紹介します。


純粋な CUI モード

この CUI モードは、ターミナル/コマンドライン上で利用するものです。

実際に使いはじめる前に、まずはインストールをしましょう。


インストール

インストール方法として、さまざまな方法があります。いちばんカンタンなのはパッケージ管理ツールで入れる方法です。

私の環境では例のごとく pip でインストールしました。
$ pip install ipython 
実際に IPython を走らせてみるとエラーが出て立ち上がらなかったので「エラーが出るごとに、欠けているものを都度都度インストールする」ということを繰り返しました。

pip でパッとやってみてダメなら、ここでハマってしまうと苦しいので、素直に何らかのパッケージ管理ツールを使う方法がおすすめです。

インストールについてはこのあたりが詳しいです。
Installing IPython — IPython
Quickstart — IPython An Afternoon Hack documentation


立ち上げる

インストールが無事終われば、 IPython を立ち上げます。
$ ipython

IPython が立ち上がると、次のような画面になります。


ちなみに、Python3 の場合はコマンド名が ipython3 に変わっています。


便利機能その1 補完機能

IPython の便利な機能のひとつが、「補完機能」です。変数名や何かを途中まで打ってタブキーを押すと、該当するものが自動で補完されます。


候補がひとつしかない場合はそれが入力されますし、複数ある場合は一覧表示されます。

変数名の他に import でファイル名やクラス名、メソッド名を指定したいときなんかにも、バリバリ補完してくれます。

この機能だけでも、IPythonを使う価値はあるかと思います。


便利機能その2 コマンド実行機能

もうひとつ便利な機能に、「コマンド実行機能」です。「 ! 」に続けてコマンドを入力すると、それがコマンドとしてそのまま実行できるというものです。


vimでコマンドを呼び出すのと同じような感じでしょうか。


便利機能その3 マジックファンクション機能

他には「マジックファンクション」という機能もあります。これは「 % 」始まりの文字列を入力すると各種擬似関数が使えるというものです。


たとえば、「 %run 」というコマンドは Python スクリプトを実行する関数、「 %time 」というコマンドはその後に与えられたコードの実行時間を計測する関数です。「 %history 」は直近に入力したコードを返してくれる関数で、「 %paste 」はクリップボードに保存された文字列を Python コードとして実行してくれる関数です。

他にもたくさんのマジックファンクションが用意されています。


便利機能その4 オブジェクト調査機能

オブジェクト名のあとに「 ? 」をつけて「 オブジェクト名? 」とすると、そのオブジェクトの概要を見ることができます。型や中身、 Docstring などをざっと確認することができます。



以上です。

ここにあげた機能はごく一部で、他にもさまざまな機能があります。ひとまず IPython がインストールできたら、 IPython 起動後「 %quickref 」と打てば、かんたんなリファレンスを見ることもできます。さらに詳しく知りたい場合には以下、公式サイトや参考サイトをご覧ください。

今回は冒頭にあげた IPython のふたつの使い方
  • 純粋なCUIモード
  • ブラウザを使ったモード
のうち、前者の「 CUI モード」についてのみご説明しました。ブラウザを使ったモードについてはまた記事を改めます。

参考
公式サイト
Announcements — IPython
Videos and Screencasts — IPython

その他サイト
Ipython-quick-ref-sheets
ITエンジニアのためのデータサイエンティスト養成講座(3):データを取り込む・格納するための方法を理解する (2/4) - @IT
ueBLOG | IPythonを使おう1

YouTube Ipython 検索結果
ipython - YouTube

2014/06/23

ライブラリ:collections.deque

collections の deque というクラスについてご紹介します。

from collections import deque

deque は、キュー・スタック的処理を効率的に行うためのクラスです。

通常のリストでも append pop insert などのキュー・スタック的処理は行えますが、キュー・スタック処理のためだけに設計されたものではないため効率的ではありません。一方この deque はキュー・スタック的処理を行うことを念頭に作られているため、先頭での処理、末尾での処理ともに O(1) のオーダーで高速に実行できるとのことです。

使い方は、そのままキュー・スタック的処理を行う形になります。

以下、基本的な使い方を見ていきます。


オブジェクトの生成 基本編

オブジェクトの生成は、リストの生成時に list を使うのと同じように deque 関数を使います。
from collections import deque

# インスタンス生成
# 何も渡されなければ空のキューを生成する
d1 = deque()


要素の追加

末尾や先頭への要素の追加は append や appendleft を使います。
# 末尾への要素の追加
d1.append(5)
d1.append(10)
print(d1)  # => deque([5, 10])

# 先頭への要素の追加
d1.appendleft("first")
print(d1)  # => deque(['first', 5, 10])


要素の取り出し

末尾や先頭からの要素の取り出しは pop や popleft を使います。
# 末尾の要素の取り出し
d1.pop()
print(d1)  # => deque(['first', 5])

# 先頭の要素の取り出し
d1.popleft()
print(d1)  # => deque([5])


複数要素の一括追加

複数の要素をまとめて追加する場合は extend や extendleft を使います。
# 末尾への複数要素の追加
d1.extend([11, 12, 13])  
print(d1)  # => deque([5, 11, 12, 13])

# 先頭への複数要素の追加 前から順番に追加されるので逆になる
d1.extendleft([-11, -12, -13])
print(d1)  # => deque([-13, -12, -11, 5, 11, 12, 13])


カウント

含まれる要素の数を数えたい場合には count を使います。
# 指定した要素がいくつ含まれているかのカウント
d1.extend([100] * 3)
print(d1.count(100))  # => 3


要素を値で指定しての削除

要素を指定して削除する場合には remove を使います。該当する値がない場合には ValueError があげられます。
# 指定した要素がいくつ含まれているかのカウント
d1.remove(100)  # => 成功した場合は戻り値 None


オブジェクトの生成 応用編

オブジェクト生成に使う deque にイテラブルな要素を渡すと、各要素を持ったキューができあがります。
# list と同じようにイテラブルなオブジェクトを渡すことが可能
d2 = deque("abcd")
print(d2)  #  => deque(['a', 'b', 'c', 'd'])

maxlen というオプション引数を渡すと、キューの最大長さを決めておくことが可能です。
# 最大長をあらかじめ決めておくことも可能
d3 = deque([], maxlen=5)
d3.extend([3] * 10)
d3.append(100)
print(d3)  # => deque([3, 3, 3, 3, 100], maxlen=5)

新たな要素が追加されたとき、長さが maxlen を越えるような場合は追加したのとは逆側の要素がところてん方式的に削除されます。


回転

中身を回転させたい(先頭から要素を取り出して末尾に回したい)場合には rotate を使います。
# 回転
d2 = deque("abcd")
d2.rotate(1)
print(d2)  # => deque(['d', 'a', 'b', 'c'])


通常のリストへの変換

通常のリストに戻したい場合には、そのまま list 関数に渡せばOKです。
# 通常のリストに戻す
d2_list = list(d2)
print(d2_list)  # => ['d', 'a', 'b', 'c']

ちなみに、文字列に戻したい場合も次のやり方で大丈夫かと思います。
# 通常の文字列に戻す
d2_string = "".join(list(d2))
print(d2_string)  # => dabc

deque オブジェクトも list と同じくイテラブルなオブジェクトなので、 for ループに渡して処理することなんかも可能です。


インストール

デフォルトで標準ライブラリに入っているため、インストールは不要です。


以上です。

ちなみに deque の呼び方は「デック」だそうです。名前の由来も「 deque = Double Ended QUEue 」の略だと公式ドキュメントには書かれています。


参考
collections.deque — Python公式ドキュメント

2014/06/16

Python Tips:あるオブジェクトが特定のクラスのインスタンスかチェックしたい

Pythonで、あるオブジェクトが特定のクラスのインスタンスかどうかをチェックする方法をご紹介します。

大きく分けて2つの方法があります。
type
isinstance


type

type 関数は、引数に渡されたオブジェクトのクラスを返す関数です。ですので、 type の戻り値とクラスの is 比較を行うことによってクラス・インスタンスの関係をチェックすることができます。
s = "hello"
print type(s) == str  # => True
# s は str のインスタンスなので True

i = 10
print type(i) == int  # => True
# i は int のインスタンスなので True

f = 7.77
print type(f) == float  # => True
# f は float のインスタンスなので True

もちろん、自作クラスの場合も組み込みの型と同じ形でチェックが可能です。
class MyClass(object):
    pass

m1 = MyClass()

print type(m1) == MyClass  # => True


isinstance

isinstance 関数は、引数をふたつ受け取り、ひとつめにオブジェクト、ふたつめにクラスを受け取ります。ひとつめに渡したオブジェクトがふたつめのクラスのインスタンスである場合は True を返します。
print isinstance("hello", str)  # => True

print isinstance([], list)  # => True

print isinstance({}, dict)  # => True

isinstance が type と異なるのは、クラスが継承元の場合にも True を返す点です。
class Parent(object):
    pass

class Child(Parent):
    pass

c1 = Child()
print isinstance(c1, Parent)  # => True
# 継承元のクラスでも True となる

print isinstance(c1, object)  # => True
# object も同様

また、 isinstance のふたつめの引数をタプルにすることによって、複数のクラスに対して一度にクラス・インスタンス関係を調べることなんかも可能です。
class A(object):
    pass

class B(object):
    pass

b1 = B()
print isinstance(b1, (A, B))  # => True
# b1 は A には属さないがBには属するので True


参考
type() — Python公式ドキュメント
isinstance() — Python公式ドキュメント
Differences between isinstance() and type() in python - Stack Overflow

2014/06/10

Python Tips:自作クラスの演算子のふるまいを定義したい

Pythonで、自分で作ったクラスの演算子のふるまいを定義する方法をご紹介します。

Pythonでは、「特殊メソッド」(special methods/magic methods)と呼ばれるものを使って +-*/ << += などの各種演算子の挙動を定義することができます。

特殊メソッドというのは、「ふるまいは自分で定義できるけれど、その呼び出しタイミングなど使われ方はあらかじめ決められているメソッド」のこと。ことばでの説明を聞くとなんやらよくわかりませんが、具体例を見るとわかりやすいと思います。たとえば、インスタンスを生成したときに呼び出される __init__ メソッドなんかも特殊メソッドです。 __init__ の場合なんかは顕著に、「ふるまいは自分で決められるけれど、呼び出されるタイミングはあらかじめ決まっているメソッド」ですね。

以下、この特殊メソッドを使って演算子のふるまいを定義する方法を具体的に見ていきます。ここでは典型的なものとして次の4つを見ていきたいと思います。
  • __add__
  • __mul__
  • __lshift__
  • __iadd__


__add__

__add__ は + 演算子に対応した特殊メソッドです。 __add__ の中で定義した処理が + 演算子の処理となります。
class Array(object):
    def __init__(self, values):
        """インスタンス生成時に呼び出されるメソッド
           values には数字を格納したリストを渡す
        """
        self.values = values

    def __add__(self, other):
        """+ 演算子を定義するメソッド
           values 内の要素同士を足し合わせた新しい Array インスタンスを返す """
        return Array(list(map(lambda x, y: x + y,
                          self.values,
                          other.values)))

m1 = Array([3, 5])
m2 = Array([10, 11])

m3 = m1 + m2
print(m3.values)
# => [13, 16]
# __add__ メソッドで定義したとおりの結果となっている

このコードでは、 __add__ メソッドの中に values の要素同士を足し合わせて新たなインスタンスを生成する処理を書いています。 m3 の中身を見ると、 + の挙動が __add__ で定めたとおりになっていることが確認できます。


__mul__

__add__ を詳しく見たので、ここからは手短に行ければと思います。 __mul__ は * 演算子に対応したメソッドです。 multiply multiplication の略ですね。
class Array(object):
    # ここに __init__ などの定義
    # ...

    def __mul__(self, other):
        """* 演算子を定義するメソッド
           values 内の要素同士をかけ合わせた新しい Array インスタンスを返す """
        return Array(list(map(lambda x, y: x * y,
                          self.values,
                          other.values)))

m1 = Array([3, 5])
m2 = Array([10, 11])

m4 = m1 * m2
print(m4.values)
# => [30, 55]
# __mul__ メソッドで定義したとおりの結果となっている

こちらも __add__ と同様の結果が得られていることがわかります。


__lshift__

つづいて、 __lshift__ は << 演算子に対応したメソッドです。
class Array(object):
    # ここに __init__ などの定義
    # ...

    def __lshift__(self, new_element):
        """<< 演算子を定義するメソッド
           新しいオブジェクトは生成せず values の末尾に要素を append する(破壊的メソッド) """
        self.values.append(new_element)
        return self

m1 = Array([3, 5])

m1 << 10
print(m1.values)
# => [3, 5, 10]
# こちらも __lshift__ で定義したとおりの結果となっている
<< 演算子なんかも自分で定義することができます。<< を定義すると Ruby の配列みたいですね。


__iadd__

__iadd__ は += 演算子に対応したメソッドです。
class Array(object):
    # ここに __init__ などの定義
    # ...

    def __iadd__(self, element):
        """+= 演算子を定義するメソッド
           values の各要素に渡された値を加算する """
        self.values = list(map(lambda x: x + element, self.values))
        return self

m1 = Array([3, 5])

m1 += 1
print(m1.values)
# => [4, 6]
# こちらも __iadd__ で定義したとおりの結果
# オブジェクト id も不変
こちらも定義したとおりに動いてくれています。ちなみに、戻り値はレシーバ自身にしないと( return self としておかないと)うまく動いてくれません。

以上です。

ここであげたのはごくごく一部です。演算子の挙動を定義できる特殊メソッドは豊富に用意されているので、どういうメソッドがあるのかは一度公式ドキュメントリファレンスをご覧になってみてください。


参考
Python 2.6 Quick Reference
3.4. Special method names - Python公式ドキュメント
Special Method Names - Dive Into Python 3
演算子のオーバーロード - とりあえず

2014/05/26

Python Tips:標準入力から文字列を取得したい

Pythonで入力を取得する方法をご紹介します。

Pythonでは、入力を取得する方法が大きく分けて2種類あります。

  • raw_input
  • sys.stdin.readline readlines read


以下、それぞれについて順に見ていきます。


raw_input

raw_input はコマンドラインからの入力を取得するための関数です。特にライブラリを import しなくても使える組み込みの関数となっています。

input_line1 = raw_input()
print input_line1 + " is written"
# => 入力された文字列 is written

raw_input で得られる文字列は、入力された文字列から自動的に改行文字を取り除いてくれます。

ちなみに Python3 ではこの raw_input は廃止されており、 input という別の名前の組み込み関数が用意されています。

sys.stdin.readline readlines read

sys.stdin.readline のシリーズは、raw_input よりも広い用途で標準入力を取得するための関数群です。

sys ライブラリを import することで使えるようになります。

readline readlines read のちがいを以下順に見ていきます。

import sys
input_line2 = sys.stdin.readline()
print input_line2 + " is writen"
# => 入力された文字列
#  is written

readline は標準入力から1行取得するための関数です。 raw_input とのちがいは、 raw_input が改行文字を自動的に削除するのに対し、 readline は標準入力に与えられた内容をそのまま取得してくる点です。

input_lines1 = sys.stdin.readlines()
print input_lines1
# => 入力された文字列を1行ずつ格納したリスト

readlines は標準入力から複数行取得するための関数です。戻り値はリストで、入力された文字列が1行ずつ要素として格納されています。こちらも改行文字の自動削除はありません。

input_lines2 = sys.stdin.read()
print input_lines2
# => 入力された文字列

read は標準入力から複数行取得するための関数です。 readlines が結果をリストに格納するのに対して、 read は結果をそのまま1つの文字列として取得します。

readline readlines read とそれぞれ少しずつちがうので、用途にあわせて使い分けるとよいかと思います。

以上です。

余談ですが、指定した回数だけ入力を受け付けたいときなんかは
[raw_input() for _ in range(3)]
などと書くと、Pythonらしく(?)書くことができたりします。


参考
27.1. sys — System-specific parameters and functions — Python公式ドキュメント

2014/05/20

Python Tips:リストの中の要素を要素別にカウントしたい

Pythonで、リスト中の要素の数を数える方法をご紹介します。

いちばんかんたんなのは collections ライブラリの Counter クラスを使う方法です。
import collections

以下、基本的な使い方を見ていきます。
import collections

s1 = 'すもももももももものうち'

count_dict = collections.Counter(s1)
# => Counter({'も': 8, 'ち': 1, 'す': 1, 'の': 1, 'う': 1})

Counter クラスのインスタンスは、辞書のような形で要素とその個数を格納したオブジェクトとなります。

上の例では文字列 s1 を渡していますが、リストを渡した場合でも同様に動作してくれます。

この Counter インスタンスから各要素を取り出すには items() keys() values() など辞書型と同名のメソッドを使います。
for k, v in count_dict.items():
    print k, v,
# => ち 1 も 8 す 1 の 1 う 1

順番に取り出すだけでなく、「多い方から◯個」といった取り出し方も可能です。多い方から指定した数だけ取り出すには most_common メソッドを使います。
print count_dict.most_common(2)
# => [('も', 8), ('ち', 1)]

順序は保存されていませんが、元の要素を分解して取り出すことなんかも可能です。
[x for x in count_dict.elements()]
# => ['す', 'も', 'も', 'も', 'も', 'も', 'も', 'も', 'も', 'う', 'の', 'ち']


以上です。


参考
python - How to count the frequency of the elements in a list? - Stack Overflow
8.3. collections — High-performance container datatypes — Python v2.7.6 documentation

2014/05/06

ライブラリ:bisect

Pythonの「 bisect 」というライブラリについてご紹介します。

import bisect

この bisect ライブラリは、名前のとおり bisection search ーーいわゆる二分探索法の関数を提供するライブラリです。

すでにソートされた配列に対して、関数ひとつで二分探索法を行ってくれます。

具体的には、大きく分けて2種類の関数が用意されているので、それらを順番に見ていきます。
bisect_***
insort_***


bisect_***

bisect から始まるメソッドは、二分探索法により指定した値が入るべき箇所の「探索」を行います。探索のみを行い、実際の挿入は行いません。
import bisect

li = [1, 9, 15, 32]
x = 15

print bisect.bisect_left(li, x)
# => 2

print bisect.bisect_right(li, x)
# => 3
bisect_left bisect_right はいずれもふたつの引数を受け取り、ひとつめはソート済みのリスト、ふたつめは単一の値を受け取ります。

いずれも、「ソート済みリストの適切な位置にある値を挿入するとしたら、何番目に挿入することになるか?」というのを調べて返してくれます。元のリストは変更しません。

bisect_left は、同じ値がすでに入っていた場合に、いちばん左に新しい値を挿入すると考えて、その位置を返します。

一方、 bisect_right は、同じ値がすでに入っていた場合に、いちばん右側に挿入するものとして、その位置を返します。

いずれもオプション引数 lo hi を受け取ることができます。 lo はリストの挿入すべき位置の下限を、hiは上限を指定するために使えます。
print bisect.bisect_left(li, x, lo=0, hi=1)
# => 1

left や right のついていない bisect という関数もあり、これは bisect_right と同じ挙動をします。


insort_***

insort から始まるメソッドは、二分探索法により指定した値を適切な位置に「挿入」します。 bisect が探索のみを行うのに対し、こちらの insort は実際の挿入を行います。
bisect.insort_left(li, x)
bisect.insort_right(li, x)

print li  # => [1, 9, 15, 15, 15, 32]
bisect と同様に、 insort_left insort_right もふたつの引数を受け取り、ひとつめにソート済みリストを、ふたつめに挿入したい要素を受け取ります。

いずれも渡されたリストそのものを変更します。

bisect の場合と同様、末尾に left とついている insort_left は挿入できる箇所が複数あったときにいちばん左側に、 insort_right はいちばん右側に挿入します。

left や right のついていない insort というメソッドもあり、こちらは insort_right と同じ挙動をします。
print bisect.insort(li, x)

bisect の場合と同じく insort の場合も挿入する範囲を制限するために lo hi という引数をオプションで与えることができます。

以上です。


参考
8.5. bisect — 配列二分法アルゴリズム — Python 2.7ja1 documentation
The bisect module - (the eff-bot guide to) The Standard Python Library

2014/05/01

ライブラリ:peewee

Pythonの「 peewee 」というライブラリについてご紹介します。

from peewee import *

peewee はPythonでデータベースを扱いやすくするためのライブラリーーいわゆる「ORマッパ」ライブラリです。デフォルトではPosgreSQL、MySQL、SQLiteの3つに対応しており、Ruby on RailsのActiveRecordに似たインタフェースを提供しています。

以下、peeweeの基本的な使い方をひととおり見ていきます。


データベースへの接続

データベースへの接続は、***Databaseというクラスを使って行います。
# データベースを指定して接続
db = SqliteDatabase('db.sqlite')
db.connect()

# さまざまな処理...

# データベース接続を閉じる
db.close()

これはSqliteの場合です。ほかのDBMSの場合はそれに対応したクラスを使います。


モデルの定義

# データベース指定のための設定を格納したベースモデル
class BaseModel(Model):
    class Meta:
        database = db

# モデル Person
# person テーブルに対応する
# カラムとして name birthday を持つ
# データベースの指定は BaseModel を継承する形で行う
class Person(BaseModel):
    name = CharField()
    birthday = DateField()

    def __unicode__(self):
        return self.name


テーブルの作成

# Person クラスに対応した person テーブルを作成する
def create_tables():
    Person.create_table()

create_tables()

この create_table とは逆に、存在するテーブルを削除するメソッドは drop_table です。


レコードの追加 (C in CRUD)

# Person クラスのインスタンスを生成し
# save メソッドでデータベースへ登録する
from datetime import date

def create_person(name, birthday):
    new_person = Person(name=name,
                        birthday=date(*birthday))
    return new_person.save()

create_person(name="name", birthday=(2014, 5, 5))


レコードの取得 (R in CRUD)

# 条件にマッチしたものを1件だけ取り出す
saigo = Person.get(Person.name == 'Saigo')
print saigo.name  # => Saigo

# 条件にマッチしたものを複数件取り出す
saigo_family = Person.filter(Person.name == 'Saigo').execute()
for s in saigo_family:
    print s.name,
# => Saigo Saigo Saigo...

get メソッドは条件にマッチしたものを1件だけ抽出します。後者の filter メソッドと execute メソッドの組み合わせでは、条件にマッチしたものを複数件抽出してきます。 filter で条件を決めてクエリ文を生成し、 execute で実際にデータベースに接続する、といった形です。

ちなみに、 filter で条件を決めたあとに直接 execute でデータベースにアクセスする前に order_by join limit などのメソッドでクエリ文をさらに細かく設定することももちろん可能です。


レコードの削除 (D in CRUD)

# すでにインスタンス化されたレコードを削除する
a_record.delete_instance()

# 条件にマッチしたものをすべて削除する
Person.delete().filter(Person.name == 'Saigo').execute()

delete_instance はすでにインスタンス化されたレコードを削除します。一方で、 delete のあとに filter などで条件を設定し execute とすると、条件にマッチしたものがすべて削除されます。


レコードの更新 (U in CRUD)

# すでにインスタンス化されたレコードを更新する
a_record.name = "new name"
a_record.save()

# 条件にマッチしたものをすべて更新する
Person.update(name = "Saigoh").filter(Person.name == 'Saigo').execute()

save は インスタンス化されたレコードを更新します。一方で、 update のあとに filter などで条件を設定し execute とすると、条件にマッチしたものをすべて update 内の式のとおりに更新します。

以上です。


この他にも、データベース操作をかんたんにしてくれるさまざまなメソッドが用意されています。

詳しくは公式ドキュメントを参照してみてください。


インストール

pip が入っていればインストールは pip から行えます。
$ pip install peewee


参考
SQLAlchemyとpeeweeの比較 - kk6のメモ帳*
紹介マニアどらふと版: Python の ORM 調査:結論
Welcome to Peewee, a lightweight python ORM - IPython Notebook Viewer
peewee - Python is Simple
coleifer/peewee - GitHub
peewee — peewee公式ドキュメント

2014/04/23

Python Tips:スクリプトの実行時間を計測したい

Pythonで、スクリプトの実行時間を計測する方法をご紹介します。

実行時間を計測するには、そのままずばり「 timeit 」という実行時間計測用のライブラリを使う方法がシンプル、かつかんたんです。

timeit の最も基本的な使い方は次のとおりです。
$ python -m timeit "[x ** 3 for x in range(100)]"
# => 10000 loops, best of 3: 39 usec per loop

python コマンドに m オプションを渡し timeit モジュールを読み込んで、その後に計測したいコードを文字列で渡します。すると、渡されたコードの実行時間が標準出力に返ってきます。時間の単位は usec 、ということで単位時間(マイクロセカンド)のようです。

上の例では「与えられたコードを10000回繰り返す」ということを3回試行して、3回のうちのベストタイムが返されています。

渡された文字列が実行されるので、特定のスクリプト(ファイルになっているもの)の実行時間を計測したい場合は、この文字列の部分にコードを入れ込めばOKです。

たとえば、LinuxやMacなら次のようにすることで特定のスクリプトの実行時間を計測することができます。
$ python -m timeit "`cat script_to_time.py`"
# => 10000 loops, best of 3: 7.76 usec per loop
cat script_to_time.py によってスクリプトの中身を出力して、それを `` を使ってコマンドの中に埋め込んでいます。 `` の部分は $() などを使っても大丈夫です。

・・・以上です。


timeit のこの他の使い方については別の投稿にも書いていますのでよろしければご参考にしてください。
ライブラリ:timeit - Life with Python


参考
26.6. timeit — Measure execution time of small code snippets — Python公式ドキュメント

2014/04/16

Python Tips:リストの中から要素をランダムにピックアップしたい

Pythonでリストの中から要素をランダムで抽出する方法をご紹介します。

ランダムで抽出する、というとき、抽出方法は2つあるかと思います。
1つだけ抽出する
複数抽出する

以下、それぞれについて見ていきます。

1つだけ抽出する
1つだけ抽出したいときは random ライブラリの choice 関数を使います。
import random

marks = ['club', 'diamond', 'heart', 'spade']
numbers = range(1, 14)
cards = [(m, n) for m in marks for n in numbers]

random.choice(cards)  # => トランプのカードのいずれか

たとえば、52枚のカードの束から1枚取り出して、そのカードをまた元に戻して、というように繰り返す場合なんかは、 random.choice を繰り返すような形で実現できます。

複数抽出する

複数枚抽出したいときは random ライブラリの sample 関数を使います。
import random

marks = ['club', 'diamond', 'heart', 'spade']
numbers = range(1, 14)
cards = [(m, n) for m in marks for n in numbers]

random.sample(cards, 5)
# => 52枚のカードの中からランダムに5枚

sample 関数は上のように2つの引数を受け取ります。1つめにはリストを、2つめには個数を指定します。

以上です。


上記の一組のトランプを使ったやり方でかんたんなモンテカルロ法なんかもできます。次のコードでは、トランプの束から抜き出した1枚の数が偶数の確率を求めています。
# トランプの束の中からカードを1枚だけ引くのを繰り返す
chosen_cards = []
for i in range(10000):
    c = random.choice(cards)
    chosen_cards.append(c)
    
# 引いたカードのうち数値が偶数となるカードが出た確率を計算して表示
even_cards_num = 0
for card in chosen_cards:
    if card[1] % 2 == 0:
        even_cards_num += 1

print(even_cards_num/len(chosen_cards))
# => 0.45ぐらいの数値


参考
How do I randomly select an item from a list using Python? - Stack Overflow

2014/04/08

Python Tips:実行中のスクリプトの名前を取得したい

Pythonで、実行中のスクリプトの名前を取得する方法をご紹介します。

と構えるまでもなくやり方はかんたんで、組み込みの変数 __file__ を使います。
print __file__
# => 実行中のスクリプト名の絶対パス

次のようにすると、ファイル名の部分だけ切り出すことができます。
import os

print os.path.basename(__file__)
# => 実行中のスクリプト名

逆にファイル名なしのパスだけを得たい場合は dirname を使います。
print os.path.dirname(__file__)
# => 実行中のスクリプトのディレクトリ

以上です。

ちなみに、 __file__ とよく似たものに __name__ があります。こちらは

  • 実行中のスクリプト内では "__main__"
  • 他からimportされたとき 拡張子なしのファイル名(モジュール名)

という値を格納しています。


参考
Get the name of current script with Python - Stack Overflow

2014/04/02

Python Tips:2つのリストの要素同士を演算したい

Python で 2 つのリストの要素同士の演算を行う方法をご紹介します。

要素同士の演算というとき、次の 2 つの方法があるかと思います。

  1. i 番目の要素同士をかけあわせる
  2. すべての組み合わせをかけあわせる

以下、それぞれのやり方を見ていきます。

i 番目の要素同士をかけあわせる

まずは i 番目の要素同士をかけあわせる方法を。こちらは zip と内包表記または map を使う方法が便利です。
li1 = [1, 3, 5]
li2 = [2, 4, 6]

combined1 = [x * y for (x, y) in zip(li1, li2)]
# => [2, 12, 30]

こちらは map を使うやり方です。
from operator import mul
combined2 = map(mul, li1, li2)
# => [2, 12, 30]
ここで、 mul は2項演算子 * と同じ働きをする関数で、引数を2つ取ります。 map には、関数、1つめのリスト、2つめのリストの順番で渡します。

すべての組み合わせをかけあわせる

すべての組み合わせをかけあわせるのは内包表記を使うやり方がシンプルにきれいに書けます。
li1 = [1, 3, 5]
li2 = [2, 4, 6]

combined3 = [(x, y) for x in li1 for y in li2]
# => [(1, 2), (1, 4), (1, 6), (3, 2), (3, 4), (3, 6), (5, 2), (5, 4), (5, 6)]

len(combined3)  #=> 9;

「 for x in 1つめのリスト for y in 2つめのリスト」とすることで、すべての要素の組み合わせを作ることができます。

以上です。


参考
Element-wise Addition of 2 Lists in Python? - Stack Overflow

2014/03/26

Python Tips:辞書のキーとバリューを逆にしたい

Pythonで、辞書型のオブジェクトのキーとバリューを入れ替える方法についてご紹介します。

最もかんたんなやり方は、辞書内包表記を使う方法です。
mydict = {"a": "amembo", "i": "inu", "u": "usagi"}

mydict_inv = {v:k for k, v in mydict.items()}
# => {'amembo': 'a', 'inu': 'i', 'usagi': 'u'}

ちなみに Python 2.6 以前にはこの辞書内包表記がなかったとのことなので、2.6以前でやるとしたら次のやり方になるでしょうか。
mydict_inv = dict([(v, k) for k, v in mydict.items()])


参考
dictionary - Python reverse / inverse a mapping - Stack Overflow

2014/03/17

Python Tips:リストから辞書を作成したい

Pythonでリストから辞書を作成する方法についてご紹介します。

まずは、元のリストが要素をふたつずつ持ったタプルからできている場合。この場合はそのまま dict 関数を使います。
# リストの要素がすでに2個組のタプルとなっている
li1 = [("a", 3), ("b", 2), ("c", 5)]

di1 = dict(li1)
# => {'b': 2, 'c': 5, 'a': 3}

辞書の内包表記を使えば、次のような書き方をすることもできます。
d = {k: v for (k, v) in li1}
# => {'b': 2, 'c': 5, 'a': 3}

次に、元のリストが「キー バリュー キー バリュー ...」というように、キーとバリューを交互に格納したリストの場合。この場合は、いったんキーとバリューがセットになったタプルを作ってから dict 関数に渡す形だときれいに書けます。
# リストの要素が交互に並んだキーとバリューになっている
li2 = ["a", 3, "b", 2, "c", 5]
di2 = dict(zip(li2[0::2], li2[1::2]))
# => {'b': 2, 'c': 5, 'a': 3}

ここで、 li2[0::2] は奇数番目の要素、 li2[1::2] は偶数番目の要素を収めたリストとなっているので、これらを zip 関数に渡すことで奇数番目と空数番目の要素をセットにしたタプルのリストができあがります(正確にはリストではなくイテレータができあがります)。


参考
Python: create a dictionary with list comprehension - Stack Overflow
Python Ordered Dictionary to regular Dictionary - Stack Overflow

2014/03/12

ライブラリ:unittest

PythonのJUnit系のテストライブラリ unittest についてご紹介します。


使い方

まずは最もベーシックな使い方から。

最小の流れは次のようなものになります。
unittest ライブラリの読み込み
unittest.TestCase を継承したクラスの中にテストケースを書く
unittest.main() でテストを実行する

ことばで聞くよりコードを見るのが早いので、例を見てみます。
# unittest ライブラリを読み込んでおく
import unittest


# テスト対象の関数
def factorial(n):
    """factorial function"""
    if n < 2:
        return 1
    return factorial(n - 1)


# テストケースをまとめたクラス
# メソッド名が test で始まるメソッドがひとつのテストとなる
class FactorialTest(unittest.TestCase):

    def test_factorial_with_arg_1(self):
        expected = 1
        actual = factorial(1)
        self.assertEqual(expected, actual)


# 直接実行されたときのみ unittest.main() を呼び出して
# テストケースを回す
if __name__ == "__main__":
    unittest.main()
ここで、 factorial の部分はテストではなくテスト対象となるコードです。簡単化のために、テスト対象コードとテストケースとが同一モジュールに入っている状態にしています。

unittest.main() が呼び出されると、そのスクリプトの中で unittest.TestCase を継承したすべてのクラスがテストケースのかたまりとして認識され、そのメソッドのうち名前の先頭が test で始まるメソッドだけがテストケースとして実行されます。

各テストケースの中にはひとつ以上のアサート用メソッドを書きます。 unittest のアサート用のメソッドは「self.assert***」という形で呼び出します。***の部分には Equal True False などさまざまなアサーションチェックが行える単語が入ります。

具体的なアサート用のメソッドとしては、次のようなものが用意されています。

  • assertEqual(a, b)
  • assertNotEqual(a, b)
  • assertTrue(x)
  • assertFalse(x)
  • assertIs(a, b)
  • assertIsNot(a, b)
  • assertIsNone(x)
  • assertIsNotNone(x)
  • assertIn(a, b)
  • assertNotIn(a, b)
  • assertIsInstance(a, b)
  • assertNotIsInstance(a, b)


このスクリプトを python スクリプト名 で実行すると、テストが実行され、OKやエラーなどの結果が表示されます。

unittest の最小単位はこれだけです。

各テストケースの前後でお決まりの処理を行いたい場合は setUp tearDown メソッドを使います。
class FactorialTest(unittest.TestCase):
    # 各ケースの最初に実行してほしい処理
    def setUp(self):
        self.f = open(targetfile, 'r')

    # 各ケースの終わりに実行してほしい処理
    def tearDown(self):
        self.f.close()
setUp には最初の処理を、tearDown には最後の処理を書いておきます。 python スクリプト名 とするだけでは、アサーションに失敗しないかぎり、具体的にどのテストケースが実行されているのかの詳細は表示されません。テストの詳細を表示してほしい場合はpythonコマンドに -v オプションを渡します。
$ python スクリプト名 -v

スクリプトの中にあるテストケースすべてではなく、特定のテストケース(クラス)だけを指定して実行したい場合は -m オプションで unitest を読み込んだあとにクラス名で指定します。
$ python -m unittest スクリプト名.テストケース名

たとえば、上記の FactorialTest が factorial.py というファイルに入っている場合であれば次のように実行します。
$ python -m unittest factorial.FactorialTest

テストスクリプトを個別に指定せずに、まとめて実行してほしい場合には unittest の discover サブコマンドを使います。
$ python -m unittest discover

discover について詳しくは公式ドキュメントの discover の項をご覧ください。


インストール

unittest はデフォルトでPythonの実行環境に含まれているため、別途インストールは不要です。

import unittest とすることですぐに使い始めることができます。


以上です。


参考
unittest — Unit testing framework — Python公式ドキュメント
Test-Driven Development in Python - O'Reilly Media
Testing Your Code — The Hitchhiker's Guide to Python

2014/03/03

Python Tips:ライブラリをまとめてインストールしたい

Pythonのライブラリをまとめてインストールする方法をご紹介します。

pip がインストールされていれば、 pip install の -r オプションで一括インストールが可能です。
$ pip install -r requirements.txt
$ pip install --require requirements.txt  # このように書いても OK

requirements.txt の中身は次のような形でライブラリの一覧を書きます。
cssselect==0.9.1
lxml==3.2.4
mechanize==0.2.5
pyquery==1.2.6
requests==2.0.1
selenium==2.37.2
wsgiref==0.1.2

この形は pip freeze の出力形式と同じなので、特定のライブラリ環境を別のところに移したい場合なんかにも pip freeze 、 pip install でかんたんに移すことが可能です。

$ # コピー元の環境でライブラリ一覧を作成
$ pip freeze > requirements.txt
$ 
$ # 新しい環境に移ってまとめてインストール
$ pip install -r requirements.txt


以上です。

ちなみに virtualenvwrapper で環境を新規作成する際にも同様のオプションを取ることができます。
$ mkvirtualenv 環境名 -r requirements.txt

こうすれば、新しい環境を生成した直後に特定のライブラリをインストールしてくれます。

ちなみに、ライブラリ指定に加えて「使用するPythonの指定をしたい」といった場合には
$ mkvirtualenv 環境名 --python=/path/to/specific/python -r requirements.txt
とすれば大丈夫です。


参考
Usage — pip 公式ドキュメント

2014/02/27

Python Tips:オブジェクトのアトリビュートを確認したい

Pythonで特定のオブジェクトのアトリビュートを確認する方法についてご紹介します。

オブジェクトのアトリビュートの一覧を取得するには dir() 関数を使います。

s1 = "hello"
n1 = 5

print dir(s1)
# str型のオブジェクトのアトリビュート/メソッド一覧を表示

print dir(n1)
# int型のオブジェクトのアトリビュート/メソッド一覧を表示

dir(obj) は、そのオブジェクトの中にある名前一覧を配列に格納して返してくれます。


dirが具体的にどういう動きをしているかなどの詳細は参考リンクをご覧ください。

参考
python - How to get a complete list of object's methods and attributes? - Stack Overflow

2014/02/24

Pythonの staticmethod と classmethod のちがい

Pythonには staticmethod と classmethod というよく似たふたつのデコレータが存在します。一見わかりづらいこれらのちがいについて今回は見ていきます。

結論からざっくり言うと
  • staticmethod の高機能版が classmethod
  • ふたつのちがいは「引数の扱い」
  • staticmethod ではメソッドは実引数をそのまま受け取る
  • classmethod ではクラス自身が暗黙的に第一引数として挿入される
といったちがいになるかと思います。

ことばだけではわかりづらいので、例を見てみましょう。
class MyClass(object):
    @staticmethod
    def static_method(*args):
        print(*args)

    @classmethod
    def class_method(*args):
        print(*args)

MyClass.static_method(1, 3, 5)
# => 1 3 5
# 渡された引数がそのまま順に表示される

MyClass.class_method(1, 3, 5)
# => <class '__main__.MyClass'> 1 3 5
# 渡された引数の前に「クラスそのもの」が表示される
staticmethod でデコレートした方は、引数を print すると実引数がそのまま順番に表示されています。一方で、 classmethod でデコレートした方のメソッドは、実引数のほかにクラスをあらわすオブジェクが順に表示されます。

・・・ということからわかるように、 classmethod では第一引数に暗黙的にクラスそのものが渡される仕組みとなっています。

この classmethod のふるまいは、インスタンスメソッドの場合とまったく同じです。インスタンスメソッドの場合も暗黙的に第一引数にインスタンスが挿入されるので、定義する際は、第一引数を self とするのがきまりとなっています。 classmethod を使う場合もそれと同じように、第一引数を「cls」とすることがルールとなっています(他の名前をつけても文法的なエラーで出ませんが、慣習として・・・)。

@classmethod
    def class_method(cls, args):
        ...

以上です。

ちなみに staticmethod も classmethod もインスタンスから呼び出すこともできます。


参考
decorator - What is the difference between @staticmethod and @classmethod in Python? - Stack Overflow

2014/02/18

ライブラリ:virtualenvwrapper

Pythonのコマンドラインツールである「virtualenvwrapper」についてご紹介します。

virtualenvwrapper とは、その名前のとおり virtualenv の wrapper で、便利な virtualenv をより使いやすくしてくれるツールです。ちなみにWindowsには対応しておらず、LinuxとMac限定のツールとなっています。

以下に、特徴と初期設定、基本的な使い方を説明します。

特徴

virtualenvwrapper の特徴として次の6つが公式ドキュメントにあげられています(意訳です)。

  • すべての virtualenv 環境を一元管理できる
  • 便利な各種コマンド
  • 環境の切り替えがコマンドひとつで
  • タブによるコマンド補完
  • カスタマイズ可能なフック
  • 拡張機能も自由に開発可


初期設定

まずは virtualenvwrapper そのものをインストールします。その前に virtualenv がインストールされていなければ先にインストールしておきます。

pipがインストールされていれば virtualenvwrapper のインストールは pip install で可能です。
$ pip install virtualenvwrapper

インストールが完了したら virtualenvwrapper を有効化します。具体的には、環境変数 WORKON_HOME を設定し、 virtualenvwrapper.sh を実行します。
$ export WORKON_HOME=$HOME/.virtualenvs
$ source (適切なパス)/virtualenvwrapper.sh

ここで、 WORKON_HOME は virtualenv 環境を一元管理するディレクトリを指定するための変数です。ここではユーザホーム直下の .virtualenvs というディレクトリを使っていますが、場所はどこにおいても大丈夫です。管理の都合を考えると $HOME 直下に専用のディレクトリを作ってそこにまとめるのがよろしいかと思います。

virtualenvwrapper.sh は virtualenvwrapper を有効化するためのシェルスクリプトです。システムのPythonと同じディレクトリに virtualenvwrapper を入れた場合は /usr/local/bin あたりにあることが多いようです。

ここまで無事に準備が済んでいれば「workon」コマンドが使えるようになっています。
$ workon --help

ちなみに、この WORKON_HOME の設定と virtualenvwrapper.sh の読み込みのコマンドは、いつでも使えるようにターミナルの起動スクリプト(.bashrc など)に入れておくと便利です。

基本的な使い方

基本的な使い方として、virtualenv 環境の作成、一覧、切り替え、削除などを見ていきます。

virtualenv 環境の作成は mkvirtualenvwrapper コマンドを使います。
$ mkvirtualenvwrapper 環境名
数多くのオプションがあるため、詳しくは公式ドキュメントの該当箇所をご覧ください。オプションの一部としては、次のようなものがあります。

  • --python=使用するPythonへのパス 使用するPythonのバージョンを指定する
  • --no-site-packages グローバルのパッケージは使わない設定にする


mkvirtualenvwrapper で環境の作成に成功したら、自動的にその環境が有効化されます。どの環境が有効化されているかはターミナルのプロンプトよりわかります。プロンプトの先頭に (環境名) が付いていればその環境に入っている証拠となります。

これまでに作成され現在も存在する環境を一覧するには workon コマンドを使います。
$ workon

virtualenv 環境を複数作っている場合の環境の切り替えも workon コマンドで行います。
$ workon 環境名

有効化された環境から抜けるには deactivate コマンドを使います。
$ deactivate

最後に、環境の削除方法について。存在する環境を削除するには rmvirtualenv コマンドを使います。
$ rmvirtualenv 環境名

基本的な操作はこの4つのコマンドを押さえておけば大丈夫かと思います。ただ、この他にも豊富なコマンドが用意されているので、もっと詳しく知りたい方は公式のコマンドリファレンスをご覧ください。
Command Reference — virtualenvwrapper documentation

以上です。


参考
virtualenvwrapper
virtualenvwrapper — ドキュメント日本語翻訳
virtualenvwrapper documentation
virtualenvwrapper : Python Package Index
virtualenvwrapper | Doug Hellmann

Macでシステム以外のPythonをメインで使う設定にしたい場合は、こちらのページがたいへんわかりやすく参考になります。
Mac で Python の開発環境構築(2013.11) - methaneのブログ

2014/02/11

Pythonのスコープ その3

その1その2に引き続きPythonのスコープについて見ていきます。

みっつめのポイントは「スコープ内で使われる名前はスコープの先頭で作られる」というものです。

スコープ内で使われる名前はスコープの先頭で作られる

これは文章のとおりそのままなのですが、ことばでは説明しづらいので例を見ていただければと思います。

C = 10

def myfunc1():
    print C

def myfunc2():
    print C
    if False:
        C = 100

myfunc1() # => 10
myfunc2()
# => UnboundLocalError: local variable 'C' referenced before assignment

ここで myfunc1() は特に問題なく動作しますが、 myfunc2() は呼び出しのタイミングでエラーが上がってしまいます。

myfunc1() のように print 文のあとに C への代入処理などがなければ print 文は問題なく動くのですが、 myfunc2() のように print 文のあとで C に代入していると「代入の前にCを使ってますよね」ということで怒られてしまいます。

これで怒られるということは print 文のところでは「すでにグローバル空間の C への参照が失われている」ということになります。

この意味で、スコープ内で使われる「名前」は巻き上げられ、スコープの先頭で確保される形になっているようです。

ちなみに、Pythonの場合にこの単語を使うかはわかりませんが、いわゆる「巻き上げ」は英語では「hoisting」という単語に相当します。

以上です。

その1、その2の分とあわせて、この3つのポイントで、Pythonのスコープに関するところは大方押さえられるかと思います。


おまけ
スコープ内の名前とそれにひもづけられた参照をチェックする関数として次のふたつの関数が用意されています。
locals()
globals()

たとえば次のようにするとローカル空間、グローバル空間に存在する名前を辞書として確認することが可能です。
def show_names():
    x = 5
    y = 6
    print locals()  # => {'x': 5, 'y': 6}
    print globals() # => グローバルの名前一覧

2014/02/07

Pythonのスコープ その2

その1につづいて、Pythonのスコープのルールについて見ていきたいと思います。

ふたつめのポイントは「参照の順番は「LEGB」」というものです。

2. 参照の順番は「LEGB」

名前空間が関数やクラスで区切られるのはその1で見たとおりですが、名前を「参照する」という面においては「スコープチェーン」とも言えるような仕組みがPythonには用意されています。

たとえば。
def outer_func():
    Const = 10

    def inner_func():
        # 外側のConstを利用する
        return Const

    return inner_func()

print outer_func()  # => 10
Pythonでは関数内関数ーーいわゆる「関数のネスト」が可能となっていますが、ここで、内側の関数内では、その外側にある関数の変数を「参照」することができます。

具体的には、 inner_func の中で Const という名前が使われていますが、これが呼ばれたときには inner_func の中には Const という名前は存在しません。この場合Pythonインタプリタは inner_func のひとつ外側ーーつまり outer_func の名前空間を探索にいきます。そこには Const という名前が存在するので、その値を利用します。

このようなスコープ拡大、名前探索の順序を表したことばが「LEGB」です。LEGBとは次のことばの頭文字です。

  1. L Local
  2. E Enclosing function local
  3. G Global
  4. B Built-in


意訳すると次のような感じでしょうか。

  1. L ローカル空間
  2. E ひとつ外側にある関数のローカル空間
  3. G グローバル空間(モジュール空間)
  4. B 組み込み空間


意味合いとしては、名前を探索する順番が、最初にローカル空間、続いてひとつ外側にある関数のローカル空間、そこになければグローバル空間(モジュール空間)、それでもダメなら組み込み空間、というところになります。

かんたんな例を見てみます。
sho = 1

def outer():
    chiku = 2

    def inner():
        bai = 3

        print bai    # Lで発見
        print chiku  # Eで発見
        print sho    # Gで発見
        print abs    # Bで発見
innner 関数の中でいろいろな名前を参照しています。baiだけは同じ関数の中(ローカル空間)にその名前があるためそこで解決が済みますが、それ以外の名前はすべて異なる場所で参照を解決しています。

chikuはひとつ外側の関数、shoはモジュールのトップレベル、absは組み込みの名前によって、参照先の値を取得しています。

・・・以上が、Pythonのスコープに関するふたつめのルール「LEGB」です。


ちなみに、 global キーワードを使うと、グローバル空間にある名前を直接指定して参照や代入を行うことが可能となります。
C = 5

def outer():
    C = 10

    def inner():
        global C
        print C  # => 5
        C = 100

    inner()

outer()
print C  # => 100

Python 3では global に加えて、ひとつ外側の関数のローカル空間の名前を指定する nonlocal というキーワードが追加されています。

つづいて、みっつめのポイント「スコープ内で使われる名前はスコープの先頭で作られる」について見ていきます。

Pythonのスコープ その3


参考
scope - Short Description of Python Scoping Rules - Stack Overflow
closures - Python nonlocal statement - Stack Overflow