我在Python中编写了一个简单的上下文管理器来处理单元测试(并尝试学习上下文管理器):
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')
但是,如果我尝试使用... as,我不会获得对TestContext()对象的引用。运行这个:
with TestContext() as t:
print t.test_number
引发异常'NoneType' object has no attribute 'test_number'
。
我哪里错了?
答案 0 :(得分:26)
假设您需要访问with
语句__enter__
needs to return self
中创建的上下文管理器。如果您不需要访问它,__enter__
可以返回您想要的任何内容。
with语句将此方法的返回值绑定到语句的as子句中指定的目标(如果有)。
这样可行。
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
答案 1 :(得分:8)
def __enter__(self):
return self
会让它发挥作用。从此方法返回的值将分配给as
变量。
如果目标包含在
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
答案 2 :(得分:4)
根据PEP 343,,with EXPR as VAR
语句不将VAR
的结果分配给EXPR
,而是EXPR.__enter__()
的结果test
。第一个示例有效,因为您自己引用了if myListTags.contains({(($0 as? NSString)?.localizedCaseInsensitiveCompare(searchBar.text!) ?? .OrderedAscending) == .OrderedSame }) {
}
变量。