2016-01-12 12 views
23

मैं एक साधारण संदर्भ प्रबंधक अजगर में इकाई परीक्षण से निपटने के लिए लिखा था (और संदर्भ प्रबंधकों को जानने के लिए प्रयास करने के लिए):अजगर ... कस्टम संदर्भ प्रबंधक के लिए के रूप में

class TestContext(object): 
    test_count=1 
    def __init__(self): 
     self.test_number = TestContext.test_count 
     TestContext.test_count += 1 

    def __enter__(self): 
     pass 

    def __exit__(self, exc_type, exc_value, exc_traceback): 
     if exc_value == None: 
      print 'Test %d passed' %self.test_number 
     else: 
      print 'Test %d failed: %s' %(self.test_number, exc_value) 
     return True 

मैं एक परीक्षण लिखते हैं इस प्रकार है, सबकुछ ठीक काम करता है।

test = TestContext() 
with test: 
    print 'running test %d....' %test.test_number 
    raise Exception('this test failed') 

हालांकि, अगर मैं इसका उपयोग करने की कोशिश करता हूं ... जैसा कि मुझे TestContext() ऑब्जेक्ट का संदर्भ नहीं मिलता है। इसे चलाना:

with TestContext() as t: 
    print t.test_number 

अपवाद 'NoneType' object has no attribute 'test_number' उठाता है।

मैं गलत कहां जा रहा हूं?

उत्तर

26

यह मानते हुए कि आप में बनाए गए संदर्भ प्रबंधक में पहुंच प्राप्त करने की आवश्यकता है with कथन, __enter__ needs to return self। यदि आपको इसे एक्सेस करने की आवश्यकता नहीं है, तो __enter__ जो भी आप चाहें वापस कर सकते हैं।

बयान यदि कोई हो, बयान के रूप में खंड में निर्दिष्ट लक्ष्य (लक्ष्यों) के लिए इस विधि द्वारा दिया गया मान बाँध होगा साथ

यह काम करेगा।

class TestContext(object): 
    test_count=1 
    def __init__(self): 
     self.test_number = TestContext.test_count 
     TestContext.test_count += 1 

    def __enter__(self): 
     return self 

    def __exit__(self, exc_type, exc_value, exc_traceback): 
     if exc_value == None: 
      print 'Test %d passed' % self.test_number 
     else: 
      print 'Test %d failed: %s' % (self.test_number, exc_value) 
     return True 
+0

ध्यान दें कि संदर्भ प्रबंधक के लिए 'स्वयं' वापस करने के लिए कोई * आवश्यकता * नहीं है। यह एक बहुत ही आसान डिफ़ॉल्ट है, ताकि आप 'प्रबंधक' कथन में संदर्भ प्रबंधक बना सकें, लेकिन संदर्भ प्रबंधक '__enter__' से जो कुछ भी पसंद करता है उसे वापस करने के लिए स्वतंत्र है। ओपी के विशिष्ट उपयोग के लिए, जहां 'टेस्टकॉन्टेक्स्ट() '' कथन' में बनाया गया है, 'स्वयं' लौटने का वास्तव में जाने का तरीका है। –

+0

@MartijnPieters आप पूरी तरह से सही हैं। मैंने इसके बारे में एक अस्वीकरण जोड़ा। –

7
def __enter__(self): 
    return self 

इसे काम करेगा। इस विधि से लौटाया गया मान as चर को सौंपा जाएगा।

भी the Python doc देखें:

लक्ष्य with बयान में शामिल किया गया था, __enter__() से वापसी मान में डाला गया है।

आप केवल संख्या की जरूरत है, तो आप भी संदर्भ प्रबंधक के तर्क

class TestContext(object): 
    test_count=1 
    def __init__(self): 
     self.test_number = TestContext.test_count 
     TestContext.test_count += 1 

    def __enter__(self): 
     return self.test_number 

    def __exit__(self, exc_type, exc_value, exc_traceback): 
     if exc_value == None: 
      print 'Test %d passed' % self.test_number 
     else: 
      print 'Test %d failed: %s' % (self.test_number, exc_value) 
     return True 

को बदल सकते हैं और उसके बाद

with TestContext() as test_number: 
    print test_number 
4

PEP 343,with EXPR as VAR बयान के अनुसार VAR लिए परिणाम EXPR की आवंटित नहीं करता, बल्कि EXPR.__enter__() का परिणाम है। पहला उदाहरण काम करता था क्योंकि आपने test वैरिएबल स्वयं का संदर्भ दिया था।

संबंधित मुद्दे