RE:RE:*hogeとか**mapとか

  • March 11, 2009 08:03

RE:pythonの引数にある*hogeとか**mapとか - Djangoへの片思い日記 より

http://d.hatena.ne.jp/jYoshiori/20090310/1236685438

僕は

>>> import datetime
>>> import time
>>> datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3])
datetime.datetime(2008, 3, 10, 0, 0)

のようにやっていたのですが、strptimeだかstrftimeだか忘れがちだったので

>>> value = '2008-03-10'
>>> datetime(*map((lambda x: int(x)),value.split('-')))
datetime.datetime(2008, 3, 10, 0, 0)

の方が分りやすいかもしれない。Python使いの人はmapよりリスト内包記法の方が馴染みやすいので自分で書くなら

>>> datetime.datetime(*[int(i) for i in value.split('-')])
datetime.datetime(2008, 3, 10, 0, 0)

かな、、

もっともformatを指定してもらうなら最初のやりかたが必要

>>> def str_to_date(datestring, format="%Y-%m-%d"):
....     return datetime.date(*time.strptime(datestring, format)[:3])
....
>>> str_to_date('2008-03-10')
datetime.date(2008, 3, 10)
>>> str_to_date('080310', '%y%m%d')
datetime.date(2008, 3, 10)

ちなみに*argsと**kwargsの有意義な使い方は関数デコレーターではないでしょうか?

中でも引数を束縛した関数を返してくれる(カリー化)のfunctools.partialは良い例だと思います。

6.6 functools -- 高階関数と呼び出し可能オブジェクトの操作 (python2.5以上)

実際のコードはもっと複雑なようですが、ドキュメントの説明にもあるように

def partial(func, *args, **keywords):
    def newfunc(*fargs, **fkeywords):
        newkeywords = keywords.copy()
        newkeywords.update(fkeywords)
        return func(*(args + fargs), **newkeywords)
    newfunc.func = func
    newfunc.args = args
    newfunc.keywords = keywords
    return newfunc

と等価なコードになっています。

実際つかってみると、

>>> basic_str_to_date = partial(str_to_date, format="%Y-%m-%d")
>>> custom_str_to_date = partial(str_to_date, format="%y%m%d")
>>> basic_str_to_date('2008-10-01')
datetime.date(2008, 10, 1)
>>> basic_str_to_date('2008-11-01')
datetime.date(2008, 11, 1)
>>> custom_str_to_date("081001")
datetime.date(2008, 10, 1)
>>> custom_str_to_date("081101")
datetime.date(2008, 11, 1)

のようにformatを束縛した関数を返してくれます。*argsと**kwordsを使うことで、第一引数がどんな関数でも対処できるようになっています。

ちなみにdjango.utils.functional.curryもほぼ同じコードです。

よくよく良く考えたら、この例えは

django.utils.functional - スコトプリゴニエフスク通信 そのままでした。すみません。

Comments

March 11, 2009 15:16 by voluntas

最近はずるばかりしています。

>>> from dateutil.parser import *
>>> parse('2008-03-10')
datetime.datetime(2008, 3, 10, 0, 0)

March 11, 2009 17:56 by uemura

@voluntas

dateutilは便利ですよね。

必須モジュールといってもいいかもしれない。