はここに1つの方法です:ここではこれを理解しようとするための基本的なテンプレートがあります
from __future__ import with_statement
import inspect
class button(object):
def __enter__(self):
# keep track of all that's already defined BEFORE the `with`
f = inspect.currentframe(1)
self.mustignore = dict(f.f_locals)
def __exit__(self, exc_type, exc_value, traceback):
f = inspect.currentframe(1)
# see what's been bound anew in the body of the `with`
interesting = dict()
for n in f.f_locals:
newf = f.f_locals[n]
if n not in self.mustignore:
interesting[n] = newf
continue
anf = self.mustignore[n]
if id(newf) != id(anf):
interesting[n] = newf
if interesting:
print 'interesting new things: %s' % ', '.join(sorted(interesting))
for n, v in interesting.items():
if isinstance(v, type(lambda:None)):
print 'function %r' % n
print v()
else:
print 'nothing interesting'
def main():
for i in (1, 2):
def ignorebefore():
pass
with button():
def testing(i=i):
return i
def ignoreafter():
pass
main()
編集は:コードはもう少し、いくつかの説明を追加伸ばし...:
呼び出し元のローカルユーザを__exit__
にキャッチするのは簡単です。すでに定義されているローカルを避けるのは難しいですのブロックwith
のブロックですwith
が無視すべきローカル関数。私は少し複雑に見えるこの解決策に100%満足しているわけではありませんが、==
またはis
のどちらかで同等性テストを正しく行うことができませんでした。
私はループを追加しました(def
の前/内/後が適切に処理されていることを確認するため)、タイプチェックと関数呼び出しにより、testing
が正しいものであることを確認しましたそれは識別されている(すべてうまくいくようです) - もちろんコードは書かれている通り、with
の中のdef
は引数なしで呼び出し可能な関数であるため、それに対抗するためにinspect
で署名を得ることは難しくありません正しい関数オブジェクトが識別されているかどうかを確認する目的でのみ呼び出しを行っていますが、この最後の改良については気にしませんでした。
ラブリー、ありがとう。 – llimllib
あなたは大歓迎です!取り組むのが楽しい問題だったので、それをポーズするためのtx ;-)。 –
興味がある場合に備えて、私が与えたコードを使用してブログエントリを投稿しました: – llimllib