2017-08-27 54 views
2

在完成with部分后,我在下面的代码中收到AttributeError: __exit__的错误。元素对象已在with中返回,并已定义了__exit__,所以我很困惑。正在接收AttributeError:__exit__,即使WITH对象已定义EXIT

class Builder: 
    def __init__(self): 
     print("Builder init fires") 

    def __getattr__(self, name): 
     return Element(name, self) 

class Element: 
    def __init__(self, name, builder): 
     self.name = name 
     self.builder = builder 
     print("Element init fires for name of", self.name) 
    def __call__(*args, **kargs): 
     print("CALL fires, now with attributes listed:") 
     for attr, value in sorted(kargs.items()): 
      print(' %s=>%s' % (attr, value)) 

    def __enter__(self): 
     return self 

    def __exit__(self, type, value, traceback): 
     pass 

aa = Builder()   
with aa.feed(xmlns='http://www.w3.org/2005/Atom'): 
    print("INSIDE THE WITH") 
+4

当我运行代码时,由于'__call_'返回None,我得到了一个'__enter__'的AttributeError。 – BrenBarn

+1

似乎在python 3.5.2下,它接收'__exit__'的'AttributeError',但在python 3.6.1下为__enter__'。我看你是正确的,'__call __()'确定'with'返回的内容,它需要'return self'。谢谢。 – markhern

回答

0

with关键字后的表达式值必须是有效的上下文管理器。这意味着expresion的必须具有属性__enter____exit__和在文档With Statement Context Managers描述这些必须接受的参数。您可以轻松验证部分aa.feed是否可以接受,但整个表达式的值是None并且它没有必要的属性。 Python 3.5和3.6之间的区别在于,失败时丢失了__exit__,后者失踪__enter__。没什么意外的

你也忘记了selfdef __call__(self, *args, **kargs):这行,这将是一个问题,如果你会使用参数,它也是一个pythonic模式也与未使用的参数。

相关问题