Вот один способ:
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 __
- это проще - сложнее избегать тех локальных переменных, которые уже были определены до блока с
, поэтому я добавил к основным две локальные функции, которые с
должны игнорировать . Я не на 100% доволен этим решением, которое выглядит немного сложным, но я не смог правильно выполнить проверку равенства с помощью ==
или is
, поэтому я прибег к этому довольно сложный подход.
I '
Чтобы ответить на ваш вопрос, да, это интроспекция фрейма.
Но синтаксис, который я бы создал, чтобы сделать то же самое,
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
(идея состоит в том, что подобно тому, как ярлык состоит из текста, кнопка состоит из текста и функции)