Pythonで関数名を安全に変更する
Pythonのような動的な言語では、Javaのように「メソッドの名前を呼び出しも含めて変更」というリファクタリングが簡単ではありません。整合性をチェックするフェーズがないので、不用意に名前を変更すると実行時に「そんな名前の関数はない」と怒られてしまいます。
追記: 毎回こういうことを書くのも面倒なので関数にまとめました。
そこで「一度deprecated(非推奨)にする」という方法を考えました。
まず下のようにfooという関数と、それを読んでいるcallerという関数を作りました。今からこのfooをbarという名前に変更したいと思います。 しかし、実際にはcallerは大量のソースの中に散らばっているものとします。
>>> def foo(): return 1 >>> def caller(): return foo()fooの名前を変更します。ここではbar = fooとしていますが、もちろんdef foo...をdef bar...に書き換えるのでもOKです。実際は後者になるでしょう。 そして、fooという名前で改めて警告メッセージを出してbarを呼ぶ関数を定義します。
>>> bar = foo >>> def foo(): import inspect print "'foo' is deprecated: called from", inspect.stack()[1][3] return bar()こうすると、うっかりcallerの中のfooの呼び出しをbarの呼び出しに変え忘れても:
>>> caller() 'foo' is deprecated: called from caller 1変える値は変わらず、警告メッセージだけが表示されるようになります。警告は今はprintで出していますが、ログに出すなりなんなりするといいと思います。
追記: 毎回こういうことを書くのも面倒なので関数にまとめました。
>>> def deprecated(f): def deprecated_func(*args, **kw): import inspect print "'%s' is deprecated:" % f.func_name, print "line %s in '%s'" % tuple(inspect.stack()[1][2:4]) return f(*args, **kw) return deprecated_func >>> def nibai(x): return x * 2 >>> def foo(): print nibai(10) print nibai(20) >>> foo() 20 40 >>> nibai = deprecated(nibai) >>> foo() 'nibai' is deprecated: line 2 in 'foo' 20 'nibai' is deprecated: line 3 in 'foo' 40
フィードバック
deprecatedをデコレイタにすると更によし?
Pythonライブラリの "3.20 warnings -- 警告の制御" を使うのが良いと思います。