特集

UNIX USER2005年2月号特別企画より転載:

2.4への機能強化で広がるPythonの世界 (3/4)

2005年01月24日 16時00分 更新

前のページ | 1 2 3 4 | 次のページ

関数やメソッドの修飾構文

 関数やメソッドの修飾構文の機能向上は、Python 2.4の拡張のうち、目玉ともいえる部分です。この構文については開発者メーリングリストにおいて、長期間にわたって議論が繰り返されました。関数やメソッドに対する修飾機能そのものはPython 2.2から存在していましたが、専用の構文は用意されていませんでした。

 たとえば、クラスメソッドを定義する場合、従来はリスト1のように記述していました。この方法はクラスの記述が複雑になったり、メソッドのコード量が増えると、メソッドの定義部分とクラスメソッドとしての登録部分が離れてしまい、可読性が低下する問題がありました。

リスト1 クラスメソッドを定義する場合の従来の記述例
class foo:
   def method(args):
       :
       :
   method = classmethod(method)

 Python 2.4では、「@」という記号を使って、メソッドを修飾する構文が提供され、リスト2のように書くことが可能になりました。この@を使った構文は、クラスメソッドを定義する場合以外にも、自由に使用できます。

リスト2 Python 2.4では、「@」という記号を使って、メソッドを修飾する構文が提供されている
class foo:
   @classmethod
   def method(args):
       :
       :

 実行例12では、関数オブジェクトにcreatedTimeという属性を作成し、その値として、時刻を代入する修飾用の関数createdTimeを定義しています。関数fooとbarを定義する際にこの修飾を指定しています。結果として、それぞれの関数オブジェクトにはcreatedTimeという属性が作られ、それを参照すれば定義された時刻が分かります。このような関数を修飾する関数のことをデコレータといいます。

実行例12 関数オブジェクトにcreatedTimeという属性を作成し、その値として時刻を代入する修飾用の関数createdTimeを定義している
>>> import time
>>> def createdTime(funcObj):
...     funcObj.createdTime = time.time()
...     return funcObj
...
>>> @createdTime
... def foo(x):
...     print x + 1
...
>>> @createdTime
... def bar(name):
...     print "Hello %s" % name
...
>>> foo.createdTime
1103025973.760793
>>> bar.createdTime
1103026042.8535249
>>> foo(10)
11
>>> bar("World")
Hello World

 ここで重要なのは、修飾用の関数が適用されるのは実行時ではなく、定義時である点です。つまり、デコレータによって複数の関数に共通したシグネチャを持たせる操作を簡単に記述できるようになったわけです。

 デコレータには引数を与えることもでき、これを利用するといろいろと面白いことができます。リスト3は関数の引数の型をチェックするデコレータの例です。実行結果は実行例13のようになり、正しく引数の型チェックが行われていることが分かります。

リスト3 関数の引数の型をチェックするデコレータの例
赤字の部分にマウスカーソルをあてると内容を確認できます

import math

def declareArgs(*argTypes):
 def checkArguments(func):
  assert func.func_code.co_argcount == len(argTypes)
  def wrapper(*args, **kwargs):
   pos = 1
   for (arg, argType) in zip(args, argTypes):
    assert isinstance(arg, argType), \
       "Value %r dose not match %s at %d" % (arg, argType, pos)
    pos += 1
   return func(*args, **kwargs)

  wrapper.func_name = func.func_name
  return wrapper

 return checkArguments


@declareArgs(float, float)
def calcDistance(x, y):
 return math.sqrt(x * x + y * y)

print calcDistance(3.14, 1.592)
print calcDistance(2.0, 4)



実行例13 リスト3の実行結果。正しく引数の型チェックが行われていることが分かる
$ /opt/Python-2.4/bin/python DecoratorTest.py
3.52052041607
Traceback (most recent call last):
  File "DecoratorTest.py", line 27, in ?
    print calcDistance(2.0, 4)
  File "DecoratorTest.py", line 11, in wrapper
    assert isinstance(arg, argType), \
AssertionError: Value 4 dose not match at 2

 また、この一連の動作はリスト4のようにコードを書いた場合とまったく同じです。リスト4で、print calcDistance(3.14, 1.592)を実行すると、実際に起動する関数本体はwrapper(*args, **kwargs)ということになります。wrapper関数の引数argsは(3.14, 1.592)になっています。この実引数がargTypesで与えられている型に対応しているかを順番にチェックし、すべて正しければ func(*args, **kwargs)が実行され、結果を返します。変数funcは、上位の関数checkArgumentsでオリジナルのcalcDistanceオブジェクトが代入されていますので、結果としてオリジナルのcalcDistance(3.14, 1.592)が実行されることになります。

リスト4 リスト3と同様の動作をするコード
def calcDistance(x, y):
    return math.sqrt(x * x + y * y)

checkArgFuncObj = declareArgs(float, float)
wrapperFuncObj = checkArgFuncObj(calcDistance)
calcDistance = wrapperFuncObj

 このような関数のカスタマイズは、従来も行えましたが、デコレータを使うことでさらに簡潔に記述できるようになったわけです。デコレータはこれ以外にも多くの利用法がありますので、研究してみると面白いと思います。

10進数演算モジュール

 Python 2.4から、10進数演算の機能を提供するDecimalモジュールが標準になりました。これで、1.1を10回足すと正しく11になる計算ができるようになりました(リスト5)。浮動小数点数による計算では、丸め誤差のため計算結果は11.0になりませんが、decimalを使った10進数計算では正しい結果が得られます。

リスト5 10進数演算の機能を提供するDecimalモジュールを利用すると、浮動小数点数を含む数値の10進数計算で正しい結果が得られる
>>> import decimal
>>> dnum = decimal.Decimal("1.1")
>>> dsum = decimal.Decimal("0")
>>> rnum = 1.1
>>> rsum = 0.0
>>> for i in range(10):
...   dsum = dsum + dnum
...   rsum = rsum + rnum
...
>>> rsum
10.999999999999998
>>> dsum
Decimal("11.0")
>>> str(dsum)
'11.0'

前のページ | 1 2 3 4 | 次のページ

[磯 蘭水,UNIX USER]

Copyright(c)2010 SOFTBANK Creative Inc. All rights reserved.




キャリアアップ



エンタープライズ・ピックアップ

news004.jpg 世界で勝つ 強い日本企業のつくり方:利用契約の検討――グローバルクラウドで失敗しないために(前編)
2010年以降、クラウドサービスの利用がさらに加速する。サービスを利用する企業はプロバイダーのデータセンターに預けた自社情報を保護するために、法的な要素を理解しておかなければならない。企業が注意を払うべき法的な検討事項を整理する。

news001.jpg IT投資の新方程式:「Twitter使ってます」――現役MS社員が“社員力”を語る(前編)
マイクロソフトが掲げるプロモーションメッセージ「社員にチカラを。ITで企業力を。(以下、BIEB)」からは、ITで社員の生産性を向上することが業績の拡大につながる、といったニュアンスを感じる。そこで気になるのが「じゃあ、マイクロソフトの社員自身はどうなのよ?」ということ。3人の現役MS社員により実態が明らかになる……?

news010.jpg 産業構造を変えるか:「住宅クラウド」の衝撃
住宅都市工学研究所が進める「住宅クラウド」は、クラウドが企業のIT領域にとどまらず、ビジネスのやり方自体を変える可能性を示している。

news010.jpg オルタナティブな生き方 栗原進さん:ネットでリアルを楽しくしたい
SE出身の企業広報マンでありながら、趣味は落語で憧れの人はインディ・ジョーンズとアナログ全開の栗原さんに、ブログを書く理由やネットからはじまるコミュニケーションについて伺った。

news001.jpg 最強最速アルゴリズマー養成講座:トップクラスだけが知る「このアルゴリズムがすごい」――「探索」基礎最速マスター
プログラミングにおける重要な概念である「探索」を最速でマスターするために、今回は少し応用となる探索手法などを紹介しながら、その実践力を育成します。問題をグラフとして表現し、効率よく探索する方法をぜひ日常に生かしてみましょう。