سؤال

هنا بعض الكود من ريتشارد جونز بلوق:

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

سؤالي هو: كيف هيك يفعل هذا؟ كيف يمكن للمدير السياق الوصول إلى النطاق داخل كتلة؟ إليك قالب أساسي لمحاولة معرفة ذلك:

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, ، لذلك لجأت إلى هذا النهج المعقد إلى حد ما.

لقد أضفت أيضا حلقة (لجعل أكثر متأكدا بقوة defs قبل / داخل / بعد التعامل معها بشكل صحيح) والتحقق من نوع ووظيفة الدالة للتأكد من التجسد الصحيح ل testing هو الشخص الذي تم تحديده (يبدو أن كل شيء يعمل بشكل جيد) - بالطبع التعليمات البرمجية كما هو مطلوب فقط إذا def داخل with هو لوظيفة Callable بدون حجج، ليس من الصعب الحصول على التوقيع 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

(الفكرة التي تكون بها تشابها حول كيفية تصريف التسمية من النص، يتم إجراء زر خارج النصوص والوظيفة)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top