このBlogは移転しました。今後は aish.dev を御覧ください。

Re:Python とクロージャ

@kumagi: @shomah4a 記法をちょっと改める事で回避出来るというのも謎ですし、なぜリストならクロージャ出来るのかわからないのですがどういう哲学でこんな設計になってるのでしょうorz

http://d.hatena.ne.jp/shomah4a/20110909/1315542720

関数をネストできるようなプログラミング言語でスコープの扱いをどうするかという話だが、現実に可能な解決手段というのはそれほどないもので、いろんなパターンを考えてみて、それぞれのメリット・デメリットを考えてみれば、同意はできないにしろ理解はできるんじゃないかと思う。

ちなみにPythonのスコープ設計の論拠は PEP 227 -- Statically Nested Scopes にまとめられていて、この文書によれば親スコープの変数の再設定ができないのは主にGuidoの反対が理由だったようだ。私の記憶では、Pythonクロージャが実装されたとき、たしか最初のころは親スコープの変数の再定義が可能になっていたと思うが、その後の議論で再定義は廃止という流れになったはずだ。

で、なぜ廃止されたか、一応解説しておくと、

Since classes seem to achieve the same effect in a more
straightforward manner, they are preferred.

http://www.python.org/dev/peps/pep-0227

お前なに親スコープのローカル変数に状態を記録しようとしてるんだよ。そんなんするんだったらクラス作れよ。手抜きすんなよ。

def bank_account(initial_balance):
    balance = [initial_balance]
    def deposit(amount):
        balance[0] = balance[0] + amount
        return balance
    def withdraw(amount):
        balance[0] = balance[0] - amount
        return balance
    return deposit, withdraw

SICPかぶれのScheme野郎みたいなコード書くな!こんなもの、野良猫の糞に含まれる寄生虫の卵ほどの価値もない!Pythonistaならこうだ!こう書け!

class BankAccount:
    def __init__(self, initial_balance):
        self._balance = initial_balance
    def deposit(self, amount):
        self._balance += amount
        return self._balance
    def withdraw(self, amount):
        self._balance -= amount
        return self._balance

ということだ。まあ、異論はあるだろうし、結局はPython3で見直されたわけだけど。