11/11/2017

[Work out]胸肩

Bench press
 (Warmup set)
 20kg 10rep.
40kg 10rep.

 (Main set)
65kg 5rep 5set.

 Dips
 10rep 3set.

 Shoulder press machine
 15kg 10rep.
 17.25 10rep drop set.


 Front raise and Side raise superset.
4kg 5rep + 3kg 5rep
3kg 8rep
3kg 8rep

5/03/2012

[英語]もういい加減ちゃんとやってみる[つぶやき]


大分間が空きましたが、しぶとく生きています。


ところで、英語ってあるじゃないですか、ええ。
私、昔から適当に理由をつけて、適当にしかやらないので
まぁ、当然ずっと進歩はなかったわけですよ。それでよかったんで。


最近色々あって、いい加減この状況を改善する必要が差し迫ってきたこともあり、
もうこれはアカンと、腹をくくろうと。取りあえず1年継続した取り組みしよ。
となりました。

世の中には色々な学習法やらかんたら、があるようなんですが、
効率を考え出すと、私、その追求に走りだして、それに飽きるとメソッド
のせいにしだすというダメ人間なので、流行りは無視して地味にやることにしました。


自分を甘やかすことにかけては、私はなかなかのモノである。
と自負するところでして。というかそれだけで、
今まで生きてきたといっても過言じゃないんですよ。


なので、簡単なところからやり直してみて、「うんうん簡単。俺ってやっぱり出来る奴だよね。」
と、常にハードルをちょい高めにして、達成感を与え続けないと、投げだしちゃうんので、
とりあえず直近、2か月で以下をやります。そんでブログをちょくちょく書きます。


先ず、読めないと絶対に聞けないし、本当の基礎文法がないと先に進まないので
  • 基礎文法
    • 高校英語までの文法をもう一回復習。
    • 問題集を2冊読む。
高校英語文法問題集

英語を直接イメージに変換する。実はこれが出来ていないのは自覚がある。
訓練のために簡単な文章出来るだけ早く読む。というか視る。
構文、語彙は別でやるから、ただひたすら、すっとばす。
  • 直読直解
    • 24年度の中学英語の教科書を1年から3年までかった。2出版社分。6冊w
    • ペーパーブックを適当に30冊かった。w

語彙。これが一番、今までやらなかったこと。で、結局やらないといけないこと。
これはずっと、継続してしぶとくやる。
  • 語彙習得
    • 何でもよかったのだが、究極の英単語のVol.1からVol.3までやる。
    • Vol.1とか簡単すぎなのだが、それはそれで良し。俺すごいと勘違いしておく。

語彙

6/19/2011

[読書] Python クックブック 第2版 読んでみる。第1章-その2

間があいたけど、第1章-その2。結構、勉強になることあるよね。
肩肘張らず、楽しく、ゆる~くがモットーです。



1.13 文字列の一部にアクセスする
structモジュールを使う。サンプルの方法は3だとエラー。

ドキュメントから
3.x
This module performs conversions between Python values and C structs represented as Python bytes objects.
2.x
This module performs conversions between Python values and C structs represented as Python strings.

ほう、バイト型にですか。
>>> baseformat = "5s 3x 8s 8s"
>>> numremain = len("123456781234567812345678")-struct.calcsize(baseformat)
>>> format = "%s %ds" % (baseformat, numremain)
>>> leading, s1, s2, trailing = struct.unpack(format, b"123456781234567812345678")
>>> s1
b'12345678'
>>> s2
b'12345678'
>>> leading
b'12345'
>>> trailing
b''
>>> 


くっつける
>>> struct.pack(format,leading, s1, s2, trailing)
b'12345\x00\x00\x001234567812345678'


1.14 インデントの変更

例外の部分を3に合わせて

def addSpace(s,numAdd):
 """行頭に指定数の空白を付与する。"""
 white=" "*numAdd
 return white + white.join(s.splitlines(True))
   
def numSpace(s):
 """各行の行頭にあるスペース数を、リスト形式で戻す"""
 return [len(line)-len(line.lstrip()) for line in s.splitlines()]


def delSpace(s,numDel):
 """行頭から指定したスペース分をスライスした(除去した行を返す)"""
 if numDel > min(numSpace(s)):
  raise ValueError("removing more spaces than there are")
 return '\n'.join([ line[numDel:] for line in s.splitlines() ])

 
def unIndntBlock(s):
 """一番インデントの小さいものに合わせて成形する"""
 return delSpace(s,min(numSpace(s)))

試してみる。
空白が3,2,4個行頭にあるとする。
>>> s=' Hello\n world!\n goodbye'
>>> min(numSpace(s))
2
>>> print(unIndntBlock(s))
Hello
world!
goodbye
>>>
各行の行頭からスペースが2個削除。


1.15 タブとスペースの変換

スペースをタブに変更する。
サンプルだとダブルバイトが入ると変になったので、str.encode()のlen()を取得するように変更してみた。
def unexpand(astring, tablen=2):
    import re
    #スペースと非スペースに切断する。
    pices = re.split(r'( +)', astring.expandtabs(tablen))
    #全体の長さを初期化
    lensofar = 0
    for i,piece in enumerate(pices):
        #要素の長さ
        thislen = len(str.encode(piece))
        #全体の長さ
        lensofar += thislen
        if piece.isspace():
            #要素の長さをタブ1個のスペース数で割る。余りがタブに出来ない分なのでスペースになる。
            numblanks = thislen % tablen
            numtabs = (thislen - numblanks + tablen - 1)//tablen
            pices[i] = '\t'*numtabs + ' '*numblanks
    return ''.join(pices)

2個の空白があえばタブにする。
>>> unexpand("1234 567   890  あ あ   い")
'1234 567\t 890\tあ あ\t い'

1.18 一度に複数のパターンを置換する
import re
def multiple_replace(txt,adict):
#1.辞書の内容にメタキャラが含まれる可能性がるので、escapeする。
#mapでキーを取りだし|で結合。検索パターンの作成。
rx = re.compile('|'.join(map(re.escape,adict)))
#引数はマッチオブジェクト
def one_xlat(match):
return adict[match.group(0)]
#検索にヒットするたびに、マッチオブジェクトを引数に関数をコールバック。
return rx.sub(one_xlat,txt)

まず、検索パターンを作成する。縦棒で検索文字列をつなぎ、compileする。
そして、re.subに置換文字列の代わりに、コールバック関数を渡す。
こうした場合re.subではマッチが起きるたびにコールバック引数オブジェクトをコールする。
その際、コールバック引数オブジェクトへの唯一の引数は、re.MatchObjectインスタンスが自動的に渡される。

簡単な例だと、以下な感じ。
>>> import re
>>> rx = re.compile('a|b|c')
>>> def hoge(match):
return "x"

>>> print(rx.sub(hoge,'abc45'))
xxx45
>>> def hoge(match):
print(match.group(0))
return "x"

>>> print(rx.sub(hoge,'abc45'))
a
b
c
xxx45
>>>

multiple_replaceはコールされるたびに、正規表現の再計算とone_xlat補助関数の再定義が走るので、
クロージャ・アプローチの方が良い。
元サンプルの可変長引数 *argsは不要というか、結局辞書化する必要が出てくるしなぁ。
dictに*args,**kwdsと2個渡すところでエラーになったので辞書だけにした。
import re
def make_xlat(**kwds):
adict = dict(**kwds)
rx = re.compile('|'.join(map(re.escape ,adict)))
def one_xlat(match):
return adict[match.group(0)]
def xlat(text):
return rx.sub(one_xlat, text)
return xlat
動かしてみよう。
>>> adict={
"Larry Wall":"Hoge",
"creator":"killer",
"Perl":"World",
}
>>> text="Larry Wall is the creator of Perl"

こうでも良いし。
>>> fnc=make_xlat(**adict)
>>> fnc(text)
'Hoge is the killer of World'
>>>

こうしてもいいわけね。
>>> fnc=make_xlat(Perl="World",the="ssss")
>>> fnc(text)
'Larry Wall is ssss creator of World'
>>>

置換方法にバリエーションを持たせたい->(単語単位)場合に置換したいとか。
クラス化して継承を利用する。
import re
"""
基底クラス
"""
class make_xlat():
def __init__(self, **kwds):
self.adict = dict(**kwds)
self.rx = self.make_rx()
def make_rx(self):
return re.compile('|'.join(map(re.escape,self.adict)))
def one_xlat(self,match):
return self.adict[match.group(0)]
def __call__(self,text):
return self.rx.sub(self.one_xlat,text)
import make_xlat
import re
"""
派生クラス
"""
class make_xlat_by_wh_word(make_xlat.make_xlat):
def make_rx(self):
return re.compile(r'\b%s\b' % r'\b|\b'.join(map(re.escape,self.adict)))

単語単位にマッチしているので、PerlsはWorldに置換されない。
>>> fnc=make_xlat_wh_word.make_xlat_by_wh_word(**adict)
>>> fnc(text)
'Hoge is the killer of Perls'



1.24 一部の文字列のみ大文字小文字無関係にする

strを継承したクラスを作成。

class iStr(str):
    """
    str継承。検索と比較は大文字小文字を無視。
    """
    def __init__(self,*args):
        self._lowered = str.lower(self)
    def __repr__(self):
        return '%s(%s)' % (type(self).__name__,str.__repr__(self))
    def __hash__(self):
        return hash(self._lowered)
    def lower(self):
        return self._lowered

strのメソッドをラップ。
def _make_case_insensitive(name):
    str_meth = getattr(str,name)
    def x(self,other,*args):
        try: other = other.lower()
        except(TypeError ,AttributeError ,ValueError ): pass
        return str_meth(self._lowered,other,*args)
    #Python2.4 late add x.func_name=name
    x.func_name=name
    setattr(iStr, name, x)

case insensitiveとして扱うものを属性に追加
for name in 'eq lt le gt ne contains'.split():
    _make_case_insensitive('__%s__' % name)

for name in 'count endswith find index rfind rindex startswith'.split():
    _make_case_insensitive(name)

こうなるものが、
>>> HOGE="Test"
>>> HOGE.startswith("t")
False

こうなるよと。
>>> FOO=iStr("Test")
>>> FOO.startswith("t")
True

このレシピは、ケースインセンシティブなコンテナ型などを作る際に応用が利く。

ケースインセンシティブなリスト。iListの各itemがiStrでラップされるだけ。
class iList(list):
 def __init__(self,*args):
  self[:] = self
 wrap_each_item = iStr
 def __setitem__(self,i,v):
  if isinstance(i,slice): v = map(self.wrap_each_item,v)
  else: v = self.wrap_each_item(v)
  list.__setitem__(self,i,v)
 def append(self,item):
  list.append(self,self.wrap_each_item(item))
 def extend(self,seq):
  list.extend(self,map(self.wrap_each_item,seq))

>>> WARA=iList()
>>> WARA
[]
>>> WARA.append("a")
>>> WARA.append("b")
>>> WARA.append("c")
>>>
>>> WARA
[iStr('a'), iStr('b'), iStr('c')]
>>> WARA.append("A")
>>> WARA
[iStr('a'), iStr('b'), iStr('c'), iStr('A')]
>>>
>>> WARA.count("a")
2
>>>

6/15/2011

[Python][翻訳]続・関数デコレータ

前回に続いて、Ariel OrtizのBlogからの翻訳ネタ。
初心者にも理解しやすい素敵な内容。

内容に少しでもオカシイところがあれば、 それは私の責です。
原文あたって下さいませ。突っ込みもお願いします。
More On Function Decorators


More On Function Decorators

前回の投稿で、Pythonでどのように、関数デコレータを使うか2,3の例をあげたが、これらの例は、未だかなり制限されて例示されている。まず第一に、その関数は一つだけの位置引数を受け取ってデコレートされると仮定していた。もし、2つ以上の位置引数や、一つかそれ以上のキーワード引数をとる関数をデコレートしたい場合、何ができるだろう?
第二に、任意の特別な方法で設定するデコレータを許可していなかった。 では、その動作を変える事が出来るように、どうやってデコレータ自身に入力引数を渡せばよいのだろう?

今から、もう少し複雑な例で詳しく説明する。その例は、上記のいずれの制限も持たない、もっと一般的な関数デコレータをどの様に定義するのか?について、より良い知見を与えてくれるだろう。

 NOTE:ここで例示する、すべてのPythonコードはPython3に基づいている。
ソースコードの全文は以下

デコレートされた関数が実行中にraiseする、一つか、それ以上の種類の例外に対して、「例外の飲み込み」ができる関数デコレーターが欲しいとする。

もし、特定の一つの例外が実際に生成されたら、例外が実行スタックを伝播して、プログラム終了の原因になることを許可する代わりに、返されるデフォルト値を指定できるようにしたい。デコレーターのクライアントは、基本的に、明示的なtry節を書くための努力をしなくてもよくなる。

どのようにこれが動くか、デモンストレートするために、我々にはこれのような関数があるとしよう。:
def divide(dividend=0, divisor=1):
    return dividend / divisor
この関数を呼んだ場合、ZeroDivisionError と TypeErrorの、最低2つの例外が発生する可能性がある。最初の例外はdivisorパラメーターがゼロの時に発生する。
2番目の例外は、2つのパラメータのどれかが、数値タイプではない時、2つより多いパラメータが送られた時、存在しないキーワードパラメーターを使おうとした場合、に発生する。

例としては
>>> divide(1, 2)
0.5

>>> divide(1, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in divide
ZeroDivisionError: int division or modulo by zero

>>> divide("hello")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in divide
TypeError: unsupported operand type(s) for /: 'str' 
and 'int' 

>>> divide(whatever=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: divide() got an unexpected keyword 
argument 'whatever'
我々の”例外飲み込み”デコレーターは2つのキーワードパラメータを受け取る。

* exceptions:一つの例外クラスまたは、いくつかの例外クラスを含む一つのタプル。これらは”飲み込まれる”べき例外をあらわしている。
それ以外の全ての例外は通常通り、伝播する。もし、明示的な指定がなければ、デフォルトはBaseException(Pythonの例外階層のルート)。
* default: もし、指定した例外が発生した場合に返される値。明示的な指定がなければ、デフォルトはNoneである。

さあ、3つの使用例を見てみよう。
Example 1: もし、ゼロ除算がおこなわれたら、0を返す。

@swallow(exceptions=ZeroDivisionError, default=0)
def divide(dividend=0, divisor=1):
    return dividend / divisor

Example 2:もし、ZeroDivisionErrorか、TypeErrorが発生したら、0を返す。
@swallow(
    exceptions=(ZeroDivisionError, TypeError), 
    default=0)
def divide(dividend=0, divisor=1):
    return dividend / divisor

Example 3:二つの、デコレーターを連鎖させる。そうすることで、それぞれの指定した例外に、独自のデフォルト値を持たせることができる。

@swallow(exceptions=TypeError, default='Huh?')
@swallow(exceptions=ZeroDivisionError, default=0)
def divide(dividend=0, divisor=1):
    return dividend / divisor

これが、最後の例における、デコレートされたdivide関数を使う方法だ。
>>> divide(1, 2)
0.5
>>> divide(1, 0)
0
>>> divide("hello")
'Huh?'

”例外飲み込み”デコレーターを実装するために、我々はどのように@構文が動くのか、よく見なければならない。@記号の後に、評価時に呼び出し可能なオブジェクトを生成する一つの式を、実際に指定する必要がある。この呼び出し可能なオブジェクトを効果的に呼ぶと、唯一の引数として、デコレートされる関数を受け取る。そして同じ関数か、いくつかの新しい呼び出し可能なものを返す。

@記号の後ろの式は、一般的には関数の名前(デコレータ関数)だけだが、1)と2)も、また可能だ。
1)__call__メドッドの実装を含んだ、一つの新しいクラスのインスタンス。
2)他の関数の呼び出し。
これらの両方のオプションで、インプットパラメータを介して指定することにより、デコレーターに追加の情報を渡すことができる。

__call__ メソッドを定義した、クラスを使う最初の実装は、次のようにして実現できる。
class swallow:
    
    class helper:
        
        def __init__(self, outer, fun):
            self.outer = outer
            self.fun = fun            
            
        def __call__(self, *args, **kwargs):
            try:
                return self.fun(*args, **kwargs)
            except self.outer.exceptions:
                return self.outer.default
    
    def __init__(self, 
                 default=None, 
                 exceptions=BaseException):
        self.default = default
        self.exceptions = exceptions
        
    def __call__(self, fun):                            
        return swallow.helper(self, fun)

どうやってこれが、動くか理解しよう。コードは以下。
@swallow(exceptions=ZeroDivisionError, default=0)
def divide(dividend=0, divisor=1):
    return dividend / divisor
上記は、基本的に以下と同じものである。
def divide(dividend=0, divisor=1):
    return dividend / divisor     
divide = swallow(exceptions=ZeroDivisionError,default=0).__call__(divide)
上記のコードの最後の行で、我々のニーズに応じて、”例外飲み込み”クラスの一つのインスタンスが作られ、初期化されている。
それから、__call__ メソッドがまさしく同じインスタンス上で実行される。それは順番に新しいswallow.helperネストクラスを作成し、返す。

その最終的な効果として、divide変数は、この特定のクラスのインスタンスを参照する。

swallow.helperクラスはいくつでも引数、キーワード引数を受ける __call__ メソッドを実装している。
それゆえに、このクラスのインスタンスは、効果的に、必要に応じた任意の引数をとる、どんな任意の関数でもデコレートすることができる。
__call__メソッド自身は、全ての作業を行うtry節を含んでいる。
デコレートされた関数を呼び出し、返される値を送り返す。
指定された例外以外が、キャッチされた場合には、指定されたデフォルト値を返す。
swallow と swallow.helper クラスのインスタンス変数を使うことで、仕事をする為の全ての変数が便利に格納され、共有される事に注意してほしい。

”例外の飲み込み”デコレーターの2通り目の実装方法としては、関数定義(及びそれに対応するlexicalクロージャー)だけで記述することができる。
それはとても短いものだが、最初は理解する事が少し難しいかもしれない。
def swallow(default=None, exceptions=BaseException):
    def helper1(fun):
        def helper2(*args, **kwargs):
            try:
                return fun(*args, **kwargs)
            except exceptions:
                return default
        return helper2
    return helper1

見てきたように、swallow関数はデコレータに設定する為の、二つの入力パラメータをとって、
@構文が期待するように、ただ、ネストされた関数、helper1を返す。
helper1関数は、そのただ一つの引数としてデコレートされた関数を伴って、直ぐに呼ばれる。そして、その結果としてhelper2関数を返す。
これは、もし、私たちが関数fをデコレートする場合、変数fはhelper2への参照を保持することを意味する。
だから今、fが呼ばれる度に、helper2が呼ばれて、前述したようにtry節が、自身のjobを正確に実行する。

Note
1 例外の飲み込み、特定の状況下においては便利になるが、見境なくこのテクニックを使うのは避けるべきだ。
具体的には、コードのデバッグが困難になる。

2 呼び出し可能なオブジェクトは__call__という名前の特別な属性を含んでいる。もし、xが呼び出し可能なオブジェクトならば
構文
x(arg1, arg2, arg3) は
x.__call__(arg1, arg2, arg3) と等しい。
呼び出し可能なオブジェクトは、ユーザー定義関数、ビルトイン関数、ビルトインオブジェクトのメソッド、クラスインスタンスのメソッドと、自身の__call__メソッドで定義もしくは継承したクラスのインスタンスを含んでいる。

3 もし、*args や **kwargs ノーテーションに親しくなければ、Pythonチュートリアルで詳細をチェックすること。


正直、これは勉強になった。Thunks Ariel Ortiz!
訳がおかしいところは随時修正していこう・・・

5/08/2011

[Python][翻訳]関数デコレータ

Pythonの関数デコレータについて調べていたところ、
Dive Into Python 3 Appendix.C 「ここからどこへ進むのか」にて、Ariel Ortizによる 関数デコレータ、続関数デコレータ が紹介されていた。
早速見てみると、分かり易くて初学者には良いなと思った。
どうせ、記憶力がない私のこと、何度も忘れて見に行くことを考えると、
一度、勉強がてら、翻訳しておこかなぁ?と思い、
作者のAriel Ortizに翻訳とブログへの掲載・コメント
許可を求めたところ「OK」とのお返事を頂きました。

Ariel Ortizのブログページ ProgrammingBits

英語もPythonもアレな私が翻訳しているので、少しでもオカシイところがあれば、
それは私の責です。原文をあたって下さいませ。突っ込みお願いします。


関数デコレーター

プログラミング言語Pythonは、デコレーターと呼ばれる興味深い
シンクタックス上の機能を備えている。

どうやって、そしてどうしてPythonのでデコレーター
を使うのか?さあ、例題を1個使って説明しよう。

NOTE:ここで例示する、すべてのPythonコードはPython3に基づいている。
ソースコードの全文は以下。
http://programmingbits.pythonblogs.com/gallery/27/function_decorators.py

再帰関数を使って、フィボナッチ数を計算したいとする。
次の関数定義で、うまくいく。(1)

def fib(n):
    if n in (0, 1):
        return n
    else:
        return fib(n - 1) + fib(n - 2)

これで異なる入力値で関数をテストすることができる。

>>> fib(0)
0
>>> fib(1)
1
>>> fib(4)
3
>>> fib(10)
55
>>> fib(30)
832040
>>> fib(35)
9227465

あなたが、正確にこれらサンプルをPython shellにタイプしたならば
入力値が大きいほど、結果を得るのに時間がかかることに気がついただろう。

高速に動かすために、memoizationと呼ばれるテクニックを使うことができる。
memoizeされた関数は、特定の入力値に該当する結果を、キャッシュに格納する。
呼び出しの後、前回の入力値に対する計算結果として、結果をリターンすると共に、
キャッシュに格納する。すなわち、再び計算するのを避けるのだ。

このことは、特定のパラメータでの関数コールにかかる主要コストは、
次に同じパラメータでよばれた関数に最初にかかるコストを、
肩代わりしていることになる。

fib関数を直接変更するかわりに、再利用可能なmemoizing関数を書くほうがよいだろう。

def memoize(f):
    cache = {}
    def helper(x):
        if x not in cache:            
            cache[x] = f(x)
        return cache[x]
    return helper

memoize関数は別のhelper関数をラップしている。
そしてパラメータ f として受け取った関数に追加機能をする。

helper関数は実際にレキシャルクロージャーだ。レキシャルクロージャーとは、関数自身が作成された時の、自身のスコープ内にある変数を記憶している関数オブジェクトである。

このケースでいうと、helperは変数 fとcache(関数オブジェクトと辞書をそれぞれ保持する)を覚えていて最後の行では、memoize関数の呼び出し元にhelper lexicalクロージャーを返している。


以下のコードをタイプしてみると
fibをコールしたときに、すぐにスピードがアップしていることに気がつくだろう。

すごく初期のコール時でさえも、スピードアップを認めることができる。
何故なら、直ぐにfibの内部に再帰呼び出しを積み上げるからだ。

>>> fib = memoize(fib)
>>> fib(50)
12586269025

最初の行はfibをmemoizeでデコレートしていると読むことができる。
何故なら、これはPythonにおける、共通のプログラミングのイディオムのようなもので、
それを単純に利用するために、特別なデコレータシンクタックスがある。
このシンクタックスはJavaのアノテーションにインスパイアされたもので、
デコレートされる関数の定義の前に、@につづけてデコレータ関数の名前を記述する。

別の言い方をすると、このPythonのシンクタックスは

@some_decorator
def some_function():
    # function body.

以下と同じ意味である。

def some_function():
    # function body...
some_function = some_decorator(some_function)

ほとんどの場合は
@ノーテーションの方が読みやすくエラーになりにくいと同意すべきだろう。

フィボナッチ、memoization関数の例で、Pythonデコレーターを
利用するために、次のように書き直さなくてはならないだろう。

def memoize(f):
    # 前出のコード...
 
@memoize 
def fib(n):
    # 前出のコード

memoize関数は典型的な関数デコレータが持っているべき一般的な構造をみせてくれる。
一つの関数 f をインプットパラメータとして受け取り、関数 f に追加の責務(出来ること)を追加する
別の関数を戻り値とするのだ。

Pythonデコレータの別の面白い点としては、2つ以上のそれを連結することができるというものだ。
それでは、 デコートされた関数が呼ばれる前と、戻り値を返す前にメッセージを出力するような
トレース・デコレータを加えるためにサンプルを拡張してみよう。

def memoize(f):
    # 前出のコード...
 
def trace(f):
    def helper(x):
        call_str = "{0}({1})".format(f.__name__, x)
        print("Calling {0} ...".format(call_str))
        result = f(x)
        print("... returning from {0} = {1}".format(
              call_str, result))
        return result
    return helper
 
@memoize
@trace
def fib(n):
    # 前出のコード...

@memoizeと@traceはfibの直前に定義している。
さっそく、fibを実行してみると最初にmemoizeデコレータが呼ばれる。それからtraceデコレータが呼ばれ
最後に、オリジナルのfibコードが呼ばれる。例を確認してみよう。

>>> fib(5)
Calling fib(5) ...
Calling fib(4) ...
Calling fib(3) ...
Calling fib(2) ...
Calling fib(1) ...
... returning from fib(1) = 1
Calling fib(0) ...
... returning from fib(0) = 0
... returning from fib(2) = 1
... returning from fib(3) = 2
... returning from fib(4) = 3
... returning from fib(5) = 5
5

Pythonは関数デコレータとして使用されることを意図した、3種類のビルトイン関数を持っている。

  • classmethod: デコレータメソッドが、クラスメソッドであることを指す為に使用される。SmalltalkやRubyのそれに似ている。
  • staticmethod: デコレータメソッドが、スタティックメソッドであることを指す為に使用される。C++、C#やJAVAのそれに似ている。
  • property: オブジェクトのプロパティを取得、設定、削除するために使用される。

Python3.0は関数をデコレータするだけでなく、クラスをデコレートすることも許可することは、注意しておく価値がある。
うまくいけば、こんどのポストでこれらの特定種類のデコレータについて書くために時間を取るつもりだ。。

Notes
(1) 再帰を用いたフィボナッチ数列の実装はとても効率が悪いのは、知っている。
だけど、それが私の意図だ。
遅さを体感できるよう、私は単純なアルゴリズムがほしかった。



以上です。アホな私にも理解できたような気がする。分かりやすいです。
続・関数デコレータも読も。

6/11 修正

5/05/2011

[読書] Python クックブック 第2版 読んでみる。第1章-その1

内容は2.x系向けに書かれてる。3.x系ではどうするの?と考えながら読んでみるなどする。
いつも通り、間違ってても、車輪の再発明になっても気にしない。娯楽なので。
作戦:ガンガンいこうぜ。




1.3 オブジェクトが文字列のようなものかテストする

Python2では文字列の方が、Unicode型と非Unicode型があり、スーパクラスとしてbasestring型があった。
これをisinstance()に渡すと、Unicodeか否かの判別ができた。
basestringデータ型 はPython3にはないので、素直にisinstance(anobj,str)でよい。


1.6 文字列の連結

Pythonの文字列はイミュータブル。Javaで文字列を+連結するのと同じ問題を孕む。
''.joinを使うのが正解だよね。



1.8 文字列にキャラクタセットの文字が含まれるか調べる

itertools.ifilter() はPython 3では 標準ビルトイン関数 filter() になっている

書き変えてみる
def containsAny2(seq, aset):
  for item in filter(aset.__contains__,seq):
  return True
 return False

not の結果がemptyだとTrueが戻ることを利用。
def containsAll(seq,aset):
 return not set(aset).difference(seq)


>>> not set()
True
>>> not set('a')
False


>>> not ''
True
>>> not 'a'
False

Python 3 では Python 2 の string.maketrans とそっくりのスタティックメソッド maketrans がバイト列型に加わっている。
そしてユニコード文字列型にも maketrans スタティックメソッドが追加された。
これはユニコード文字列型の translate に渡せる辞書を返す。

調査対象文字列に、任意の文字列を1つでも含むか?
def containsAny(astr,strset):
 notrans = str.maketrans('','',astr)
 return len(strset) != len(strset.translate(notrans))


1.9 文字列クラスのtranslateメソッドを簡単に使う。

クロージャーを使ったラッパを作っているが、3.xではサンプルは動かない。
練習がてらユニコード文字列の maketransメソッドを使ったコードを書いてみた。

削除とkeepを2者択一にしてたりして機能縮小版。とりあえず。

def translator(frm='',to='',delete='',keep=None):
 if len(to) == 1:
  to = to * len(frm)
 if keep is not None:
  trans = str.maketrans('','',keep)
 else:
  trans = str.maketrans(frm,to,delete)
  
 def translate(s):
  if keep is not None:
   return s.translate(str.maketrans('','',s.translate(trans)))
  else:
   return s.translate(trans)
 return translate

a,dをbに変換して、数字だけ削除
>>> import string
>>> test = translator(frm='ad',to='b',delete=string.digits)
>>> test('aaaaaccccdddd123456789')
'bbbbbccccbbbb'

数字だけ残す
>>> test = translator(frm='ad',to='b',keep=string.digits)
>>> test('aaaaaccccdddd123456789')
'123456789'
>>>

ダブルバイト。愛は嘘なり。
>>> test = translator(frm='愛',to='嘘',delete=string.digits)
>>> test('愛愛愛123456789')
'嘘嘘嘘'
>>>

1/24/2011

[読書]Head First Python 読んでみる。 Chapter3

Chapter3は File & Exception : Dealing with Errors.


全章通じてそうだけど、小さな例題アプリを少しづつ、お話と共に作りながら進んでいく形式。
いつもながらこのHead Firstのやり方はうまい。猫でもわかるようになっている。

ただ、猫でない人にとっては冗長、そういう人は対象読者ではないにしても。

英語を読み進めるスピードが遅いのと、オンラインで読んでいるせいもあって
だんだん、面倒になってきたぞ。どんどん飛ばして読んでもいいのだが。。うーむ。

この内容ならこの章は2~3ページでいいじゃない。というのは野暮なのでしょう。たぶん。

もうちょっと頑張ってみよう。