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

2014/02/04

Pythonのスコープ その1

何回かに分けて、Pythonのスコープのルールについて見ていきたいと思います。

Pythonの名前がどの範囲でアクセスできるかというスコープに関するルールは、まとめると次の3ポイントになるかと思います。

1. 関数/クラス/モジュールで区切られる
2. 参照の順番は「LEGB」
3. 宣言はスコープの先頭に巻き上げられる

順に説明していきます。

1. 関数/クラス/モジュールで区切られる

Pythonには、関数、クラス、モジュールというコードの単位がありますが、それらがスコープの区切り目になります。

具体的には、関数の中と外、クラスの中と外、モジュールの中と外でスコープが異なります。

たとえば。
margin = 10

def add_margin(x):
    margin = 50
    return x + margin
    
print add_margin(30)  # => 80

print margin  # => 10
というコードでは「margin」という名前が add_margin 関数の外と中に存在しますが、関数の外と中は別の名前空間となるため、これらは全くの別ものです。

クラスの場合も同様です。
Const = 3

class MyMath(object):
    Const = 3.14

print Const  # => 3 

モジュールというのは、ここではスクリプトファイルのことを指して言っています。

たとえば、次のようなmoduleA.py、moduleB.pyというファイルがあったときに。
# moduleA.py
greeting = "Hi!"

# moduleB.py
greeting = "Ciao!"

次のmain.pyからそれらのモジュールをimportしてみます。
# main.py
import moduleA
import moduleB

print greeting  # => エラー
print moduleA.greeting  # => Hi!
print moduleB.greeting  # => Ciao!
すると、moduleA、moduleBの中のトップレベルに置かれた greeting という名前は moduleA.greeting 、 moduleB.greeting でそれぞれアクセスすることとなります。つまり、モジュール名で名前空間が区切られます。

もちろん from moduleA import greeting というように単一の名前だけimportしてきた場合は名前空間をひとつにすることができますが、基本的にはモジュールごとに名前空間がわかれます。


つづいて、「2. 参照の順番は「LEGB」」というポイントについて見ていきます。

Pythonのスコープ その2