2012-09-26 6 views
10

निष्पादन छोड़ना मैं एक संदर्भ प्रबंधक वर्ग को परिभाषित कर रहा हूं और अगर कुछ शर्तों को तत्कालता के दौरान पूरा किया जाता है तो अपवाद उठाए बिना कोड के ब्लॉक को छोड़ने में सक्षम होना चाहूंगा। उदाहरण के लिए,-with-block

class My_Context(object): 
    def __init__(self,mode=0): 
     """ 
     if mode = 0, proceed as normal 
     if mode = 1, do not execute block 
     """ 
     self.mode=mode 
    def __enter__(self): 
     if self.mode==1: 
      print 'Exiting...' 
      CODE TO EXIT PREMATURELY 
    def __exit__(self, type, value, traceback): 
     print 'Exiting...' 

with My_Context(mode=1): 
    print 'Executing block of codes...' 
+0

मुझे यह मिला, लेकिन मुझे नहीं पता कि इसका अर्थ कैसे बनाया जाए, न ही इसे कैसे कार्यान्वित किया जाए। http://www.python.org/dev/peps/pep-0377/ क्या अन्य और सुरुचिपूर्ण तरीके हैं? –

+0

तथ्य यह है कि यह एक पीईपी है (और अर्थपूर्ण परिवर्तनों की चर्चा) से पता चलता है कि इसे दुभाषिया के व्यवहार को बदलने के बिना लागू नहीं किया जा सकता है। – nneonneo

+2

स्वच्छता के साथ जुनूनी? :) ए(), बी(): जहां बी का __enter__ कुछ बढ़ा सकता है मुझे ठीक लगता है। – swang

उत्तर

8

आप एक तदर्थ समाधान withhacks (AnonymousBlocksInPython से विशेष रूप से) से विचारों का उपयोग करता है चाहते हैं, यह काम करेगा:

import sys 
import inspect 

class My_Context(object): 
    def __init__(self,mode=0): 
     """ 
     if mode = 0, proceed as normal 
     if mode = 1, do not execute block 
     """ 
     self.mode=mode 
    def __enter__(self): 
     if self.mode==1: 
      print 'Met block-skipping criterion ...' 
      # Do some magic 
      sys.settrace(lambda *args, **keys: None) 
      frame = inspect.currentframe(1) 
      frame.f_trace = self.trace 
    def trace(self, frame, event, arg): 
     raise 
    def __exit__(self, type, value, traceback): 
     print 'Exiting context ...' 
     return True 

निम्नलिखित की तुलना करें:

with My_Context(mode=1): 
    print 'Executing block of code ...' 

साथ

with My_Context(mode=0): 
    print 'Executing block of code ... ' 
+0

यही वह है जिसे मैं ढूंढ रहा था। tytytytytyty। –

+1

मैं देखता हूं, इसलिए यह किसी प्रकार का टाइपरर ट्रिगर करता है जिसे पकड़ा जाता है और __exit __() विधि द्वारा दबाया जाता है। चारों ओर दिलचस्प काम! –

+0

मैंने टाइप और मान की जांच करने के लिए विधि __exit __() में एक लूप जोड़ा, ताकि हैक द्वारा उठाए गए अपवाद को दबाया जा सके। –

1

आप जो करने की कोशिश कर रहे हैं, दुर्भाग्यवश संभव नहीं है। यदि __enter__ एक अपवाद उठाता है, तो अपवाद with कथन (__exit__ पर नहीं कहा जाता है) पर उठाया जाता है। यदि यह अपवाद नहीं उठाता है, तो वापसी मूल्य ब्लॉक को खिलाया जाता है और ब्लॉक निष्पादित होता है।

निकटतम बात मैं के बारे में सोच सकता है एक झंडा ब्लॉक द्वारा स्पष्ट रूप से जाँच की है:

class Break(Exception): 
    pass 

class MyContext(object): 
    def __init__(self,mode=0): 
     """ 
     if mode = 0, proceed as normal 
     if mode = 1, do not execute block 
     """ 
     self.mode=mode 
    def __enter__(self): 
     if self.mode==1: 
      print 'Exiting...' 
     return self.mode 
    def __exit__(self, type, value, traceback): 
     if type is None: 
      print 'Normal exit...' 
      return # no exception 
     if issubclass(type, Break): 
      return True # suppress exception 
     print 'Exception exit...' 

with MyContext(mode=1) as skip: 
    if skip: raise Break() 
    print 'Executing block of codes...' 

यह भी मदद से आप एक with ब्लॉक के बीच एक सामान्य break बयान अनुकरण में Break() बढ़ा।

+0

ध्वज काम करता है, लेकिन मैं संदर्भ प्रबंधक के भीतर सभी चेक रखना चाहता हूं और कोडों के ब्लॉक को साफ रखना चाहता हूं। यदि यह असंभव है, तो मुझे इसके अलावा एक और रास्ता खोजना पड़ सकता है। बहुत बहुत धन्यवाद! –

10
PEP-343 के अनुसार

, एक with बयान से अनुवाद:

with EXPR as VAR: 
    BLOCK 

रहे हैं:

mgr = (EXPR) 
exit = type(mgr).__exit__ # Not calling it yet 
value = type(mgr).__enter__(mgr) 
exc = True 
try: 
    try: 
     VAR = value # Only if "as VAR" is present 
     BLOCK 
    except: 
     # The exceptional case is handled here 
     exc = False 
     if not exit(mgr, *sys.exc_info()): 
      raise 
     # The exception is swallowed if exit() returns true 
finally: 
    # The normal and non-local-goto cases are handled here 
    if exc: 
     exit(mgr, None, None, None) 

जैसा कि आप देख सकते हैं, वहाँ स्पष्ट कुछ भी नहीं की __enter__() विधि के लिए आप कॉल से क्या कर सकते हैं संदर्भ प्रबंधक जो बयान के साथ शरीर को छोड़ सकता है ("BLOCK")।

लोगों ने withhacks जैसी परियोजनाओं में __enter__() के अंदर कॉल स्टैक में हेरफेर करने जैसे पायथन-कार्यान्वयन-विशिष्ट चीजें की हैं। मुझे एलेक्स मार्टेलि को एक साल या दो बार स्टैक ओवरफ्लो पर एक बहुत ही रोचक-हैक पोस्ट करना याद है (खोजने के लिए पोस्ट ऑफ-हाथ को पर्याप्त याद नहीं है)।

लेकिन आपके प्रश्न/समस्या का सरल जवाब यह है कि आप जो भी पूछ रहे हैं वह नहीं कर सकते हैं, तथाकथित "गहरे जादू" का उपयोग किए बिना, कथन के शरीर को छोड़कर, जो कि पाइथन के बीच जरूरी नहीं है कार्यान्वयन)। गहरे जादू के साथ, आप इसे करने में सक्षम हो सकते हैं, लेकिन मैं यह देखने में एक अभ्यास के रूप में ऐसी चीजों को करने की सलाह देता हूं कि यह कैसे किया जा सकता है, कभी भी "उत्पादन कोड" में नहीं।

+1

ओह मेरे भगवान 'withhacks' पागल है, वे पाइथन में रूबी शैली ब्लॉक बना दिया ... – nneonneo

+0

ठीक है, यह बहुत समझाता है। मैंने बहिष्कार की जांच की। सोचो कि यह इस बिंदु पर मेरे बाहर है .... सुनिश्चित नहीं है कि मैं अभी भी स्किप करने के लिए कोड का उपयोग कैसे कर सकता हूं लेकिन कोड का निश्चित रूप से दिलचस्प स्निपेट मैं उपयोग कर सकता हूं। (अद्यतन: रूबी स्टाइल ब्लॉक? मैं देखता हूं, हाहाह। यह वास्तव में पागल है) अन्यथा, मुझे वास्तव में एक और दृष्टिकोण के बारे में सोचना होगा। धन्यवाद! –