こんな書き方があったのか!
先日の、順列を再帰で書く、というエントリの続き
インスパイヤ先↓
2008-02-26 - rindai87の日記
のid:morchin氏によるコメント(morchinさん、毎度コメントありがとうございます。)
> これをグローバル変数使わずに書けないものか思案中。 以下のようにローカル側に一階層シフトするのはどうでしょう? def permutation(n, m = 0): def _permutation(n, m, numList): if n == m: print numList else: for x in range(1, n+1): if x in numList: continue numList.append(x) _permutation(n, m + 1, numList) numList.pop() return _permutation(n, m, [])
Python初心者には
def _permutation(n, m, numList):
という書き方に面食らってしまった。
手元の「みんなのPython」には
Pythonでは、名前の先頭にアンダースコア(_)が一つついたアトリビュートやメソッドはクラスの内部だけで利用するためにある、というルールのようなものがります。
と、あるので恐らくは関数内部で関数を定義するために必要なのかな、と推測しつつ、id:morchi氏による関数を実装。
def permutation(n, m = 0): def permutation2(n, m, numList): if n == m: print numList else: for x in range(1, n+1): if x in numList: continue numList.append(x) _permutation(n, m + 1, numList) numList.pop() return permutation2(n, m, []) def main(): print permutation(5) if __name__ == "__main__": main()
そして実行
D:\workspace\Python\2-28>python test.py Traceback (most recent call last): File "test.py", line 20, in ? main() File "test.py", line 16, in main print permutation(3) File "test.py", line 12, in permutation return permutation2(n, m, []) File "test.py", line 10, in permutation2 _permutation(n, m + 1, numList) NameError: global name '_permutation' is not defined
!!!!!!!!!!!!!!
怒られた!?????
何でだ?
id:morchi氏の書いてくれたコードは、僕が最初に書いたコードの作業用配列と関数permitation()の関係を、関数permitation()の中に関数_permitation()を定義することで実現していると思われる。
納得できるだけに、何で動かないのか不明。
「みんなのPython」の記述によると、クラスにおけるメソッドについてだから、僕が考えてることと挙動がちょっと違うのかな。
で、いろいろ考えた末、導き出した一つの答え。
def permutation(n, numList, m=0): if n == m: print numList numList = [] else: for x in range(1, n+1): if x in numList: continue numList.append(x) permutation(n, numList, m+1) numList.pop() def main(): permutation(3, []) if __name__ == "__main__": main()
かなりid:morchi氏のアイデアをパクっている…
実行結果
D:\workspace\Python\2-26>python permutation.py [1, 2, 3] [1, 3, 2] [2, 1, 3] [2, 3, 1] [3, 1, 2] [3, 2, 1]
一応うまく動いている。
作業用配列を渡しているだけ。
あんまりかっこよくはないけど、目標であった「グローバル変数を使わない」は達成。