다음과 함께 정의 된 기능 찾기 : 블록
-
12-09-2019 - |
문제
다음은 몇 가지 코드입니다 Richard Jones의 블로그:
with gui.vertical:
text = gui.label('hello!')
items = gui.selection(['one', 'two', 'three'])
with gui.button('click me!'):
def on_click():
text.value = items.value
text.foreground = red
내 질문은 : 도대체 어떻게 이것을 했습니까? Context Manager가 With Block 내부의 범위에 어떻게 액세스 할 수 있습니까? 다음은 이것을 알아 내기위한 기본 템플릿입니다.
from __future__ import with_statement
class button(object):
def __enter__(self):
#do some setup
pass
def __exit__(self, exc_type, exc_value, traceback):
#XXX: how can we find the testing() function?
pass
with button():
def testing():
pass
해결책
다음은 다음과 같습니다.
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
s 전 / 내 / 후 / 후에 올바른 화신을 확인하기위한 유형-점검 및 함수- testing
식별 된 것입니다 (모든 것이 잘 작동하는 것 같습니다) - 물론 작성된 코드는 다음과 같은 경우에만 작동합니다. def
내부 with
인수없이 호출 할 수있는 함수를위한 것입니다. 서명을 얻는 것은 어렵지 않습니다. inspect
그것에 반대하는 경우 (그러나 올바른 함수 객체가 식별되는지 확인하기 위해서만 전화를하고 있기 때문에이 마지막 개선에 대해 신경 쓰지 않았습니다 .-).
다른 팁
귀하의 질문에 답하기 위해, 예, 프레임 내성입니다.
그러나 내가 같은 일을하기 위해 만들려고 할 구문은
with gui.vertical:
text = gui.label('hello!')
items = gui.selection(['one', 'two', 'three'])
@gui.button('click me!')
class button:
def on_click():
text.value = items.value
text.foreground = red
여기서 구현하겠습니다 gui.button
일부 매개 변수와 이벤트가 주어진 버튼 인스턴스를 반환하는 데코레이터로서 button = gui.button('click me!', mybutton_onclick
괜찮습니다).
나도 떠날 것입니다 gui.vertical
내성없이 구현할 수 있기 때문에. 구현에 대해 잘 모르겠지만 설정이 포함될 수 있습니다. gui.direction = gui.VERTICAL
~하도록 하다 gui.label()
다른 사람들은 그것을 좌표를 계산하는 데 사용합니다.
이제 이것을 보면 구문을 시도 할 것 같아요.
with gui.vertical:
text = gui.label('hello!')
items = gui.selection(['one', 'two', 'three'])
@gui.button('click me!')
def button():
text.value = items.value
foreground = red
(아이디어는 레이블이 텍스트로 만들어지는 방식과 유사하게 텍스트와 기능으로 버튼이 만들어집니다)