هل يمكنني استخدام بيثون مع بيان للتنفيذ الشرطي؟
-
29-09-2019 - |
سؤال
أحاول كتابة رمز يدعم الدلالات التالية:
with scope('action_name') as s:
do_something()
...
do_some_other_stuff()
يجب أن يقرر النطاق ، من بين أشياء أخرى (الإعداد ، التنظيف) ما إذا كان يجب تشغيل هذا القسم.
على سبيل المثال ، إذا قام المستخدم بتكوين البرنامج لتجاوز "Action_Name" من ، بعد تقييم Scope () ، سيتم تنفيذ do_some_other_stuff () دون استدعاء do_something () أولاً.
حاولت القيام بذلك باستخدام مدير السياق هذا:
@contextmanager
def scope(action):
if action != 'bypass':
yield
لكن حصلت RuntimeError: generator didn't yield
استثناء (متى action
هو 'bypass'
).
أبحث عن طريقة لدعم هذا دون العودة إلى التنفيذ الاختياري الأكثر مطولاً:
with scope('action_name') as s:
if s.should_run():
do_something()
...
do_some_other_stuff()
هل يعرف أحد كيف يمكنني تحقيق ذلك؟
شكرًا!
ملاحظة أنا أستخدم Python2.7
تعديل:
لا يتعين على الحل بالضرورة الاعتماد عليه with
صياغات. أنا فقط لم أكن أعرف بالضبط كيف أعبر عنها بدونها. في جوهرها ، أريد شيئًا في شكل سياق (دعم الإعداد والتنظيف التلقائي ، لا علاقة له بالمنطق المحتوى) والسماح بالتنفيذ الشرطي بناءً على المعلمات التي يتم تمريرها إلى طريقة الإعداد وتحديدها في التكوين.
لقد فكرت أيضًا في حل ممكن باستخدام الديكورات. مثال:
@scope('action_name') # if 'action_name' in allowed actions, do:
# setup()
# do_action_name()
# cleanup()
# otherwise return
def do_action_name()
do_something()
لكنني لا أريد تطبيق الكثير من الهيكل الداخلي (أي ، كيف يتم تقسيم الكود إلى وظائف) بناءً على هذه النطاقات.
هل لدى أي شخص بعض الأفكار الإبداعية؟
المحلول
أنت تحاول تعديل السلوك المتوقع لبناء اللغة الأساسية. هذه ليست فكرة جيدة أبدًا ، إنها ستؤدي فقط إلى الارتباك.
لا حرج في عملك ، ولكن يمكنك تبسيطه قليلاً.
@contextmanager
def scope(action):
yield action != 'bypass'
with scope('action_name') as s:
if s:
do_something()
...
do_some_other_stuff()
لك scope
يمكن بدلاً من ذلك أن يكون فئة __enter__
الطريقة تُرجع إما كائن مفيد أو None
وسيتم استخدامه بنفس الطريقة.
نصائح أخرى
يبدو أن ما يلي يعمل:
from contextlib import contextmanager
@contextmanager
def skippable():
try:
yield
except RuntimeError as e:
if e.message != "generator didn't yield":
raise
@contextmanager
def context_if_condition():
if False:
yield True
with skippable(), context_if_condition() as ctx:
print "won't run"
اعتبارات:
- يحتاج شخص ما للتوصل إلى أسماء أفضل
context_if_condition
لا يمكن استخدامه بدونskippable
ولكن لا توجد طريقة لفرض ذلك/إزالة التكرار- يمكن أن يصطاد وقمع وقت التشغيل من وظيفة أعمق من المقصود (يمكن أن يساعد استثناء مخصص هناك ، ولكن هذا يجعل البناء كله أكثر فوضى)
- إنه ليس أكثر وضوحًا من مجرد استخدام إصدار Ransom
لا أعتقد أن هذا يمكن القيام به. حاولت تنفيذ مدير سياق كصف وليس هناك طريقة ل فرض الكتلة لرفع استثناء من شأنه أن يتم سحقه لاحقًا __exit__()
طريقة.
لدي نفس حالة الاستخدام مثلك ، وصادف مكتبة مشروطة أن شخص ما قد تطور بشكل مفيد في الوقت منذ أن نشرت سؤالك.
من الموقع ، استخدامه هو:
with conditional(CONDITION, CONTEXTMANAGER()):
BODY()