Python デコレータを学ぶ 3

デコレータで引数を取るのではなく、デコレートされる関数の方で引数を取って、それをデコレータ側でも使用する場合については以下のようになるようです。

# デコレータ
def how_are_you(func):
    def wrapper(arg1, arg2):
        print('I got args! Look:', arg1, arg2)
        func(arg1, arg2)
        print('how are you,', arg1, '?')
    return wrapper


# デコレートされる関数
@how_are_you
def greeting(first_name, last_name):
    print('hello,', first_name, last_name)

# 実行する
greeting('Jude', 'Law')

実行した結果はこうなります。

$ python decolate.py

I got args! Look ...
more ...

Python デコレータを学ぶ 2

デコレータに引数を渡す場合について「パーフェクト Python」に説明がありました。デコレータをさらにラップする関数を用意してそこで引数を受け取るようにすればよいみたいです。

# デコレータをラップした関数。引数 text を取る。
def show_message(text):
    def deco(func):
        def wrapper():
            print(text)
            return func()
        return wrapper
    return deco

デコレートされる関数を定義します。

@show_message('spam() called.')
def spam():
    print("Spam!")

# 実行する
spam()

すると引数で渡したテキスト 'spam() called.' を使ってデコレートできていることがわかります。

$ python decolate.py
spam() called.
Spam!

ふむふむ。

more ...

Python デコレータを学ぶ 1

Python で関数に機能を追加する仕組みとしてデコレータというものがあります。Flask のチュートリアル で @ を使ったシンタックスがあって、どういう意味か調べるとこれがデコレータというものでした。

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()

ある関数をラップして、その関数にもともと定義されている振る舞いに別な動作を追加することができます。ラッパーの部分は別途定義されているので、動作を追加したい対象の関数が複数あっても記述が煩雑になりません。

例えば以下の様な関数を定義して実行してみます。

def sandwich(food='--ham--'):
    print(food)


sandwich()

実行結果は以下のようになります。

$ python decolate.py

--ham--

これに bread() というデコレータを定義して sandwich() をデコレートしてみます。デコレータは関数を引数に取り、処理を追加した上で関数を返す関数です ...

more ...

Python ファイル作成時のテンプレートを設定

以前に .rst ファイルのテンプレートを作成したのと同じ要領で .py ファイルにも autoinsert を使って、必要な部分が最初から挿入されているように設定しました。

Python の本や他人のコードなどでよく見られるお約束的な部分(__name__ が __main__ かどうかを見る)について、これまでは何となく避けていましたが、今後は基本に忠実に、真似るべきところは真似るようにしていきます。

#!/usr/bin/env python
#-*- coding: utf-8; -*-


def main():
    pass


if __name__ == '__main__':
    main()

こういうテンプレートファイル(template.py)を用意して init.el を少し編集します。

;; 各ファイルによってテンプレートを切り替える
(setq auto-insert-alist
      (nconc '(
               ("\\.rst$" . ["template.rst" my-template])
               ("\\.py ...
more ...

Python からシステムのコマンドを利用する

Python の os モジュールを使って Python からシステムのコマンドを利用することができます。Python のスクリプトから ls や cp などのMac のシェルで使うコマンドを実行できるのです。 os.system( コマンド名 ) とすれば OK でした。

In [1]: import os

In [2]: os.system('pwd')
/Users/ryosuke/Dropbox/Projects/PyStudy
Out[2]: 0
more ...

Python でファイル名と拡張子を分離する

Python の os モジュールでファイル名の拡張子とそれ以外の部分とを分けることができます。 os.path.splitext( ファイル名 ) という形で指定するとファイル名と拡張子のタプルが返ってきます。ファイルのリネーム処理を Python からする場合などに役立ちそうですね。

In [15]: file = 'pelicanconf.py'

In [16]: a = os.path.splitext(file)

In [17]: a
Out[17]: ('pelicanconf', '.py')

In [18]: type(a)
Out[18]: builtins.tuple
more ...

IPython をインストールする

この Pelican を利用している virtualenv 環境で IPython をインストールしようとしたら下記のエラーが表示されました。 IPython 自体は起動するのですが、プロンプトの表示が崩れていて正常ではない状態です。

/Users/ryosuke/Projects/pelican/lib/python3.3/site-packages/IPython/utils/rlineimpl.py:94: RuntimeWarning:
******************************************************************************
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 ...
more ...

Python スクリプトを改修する 2 (ファイル読み書き)

仕事で使用しているスクリプトで、テキストファイルを読み込んで文中の URL を a タグで囲んで HTML ファイルに書き出すものがあります。

pandoc か何かを使えばより高い次元で実現することができるような気もしますが、必要なのは URL の処理くらいであとはテキストそのままの体裁で十分なこともあり、自作スクリプトで対応しています。

書いたのはもう 2 年くらい前で、その後私自身の Python に対する理解も(わずかずつとはいえ)深まってきたようで、読み返すといくつか書き直したい部分が出てきました。

そのうちの一つがファイルの読み書きの部分でこれまでは

f = open('hoge.txt', 'r')
for line in f:
    rawtext = line.rstrip(os.linesep)
    print(rawtext)
f.close()

という感じで書いていたのですが、「パーフェクト Python」や「Dive into Python 3 ...

more ...