床长人工智能教程——使用语句上下文管理器
声明:本人只是分享一些床长的免费杂文而已,并非床长人工智能网校的收费文章。
甲上下文管理器是一个对象,执行当定义了运行时上下文被建立with语句。上下文管理器处理执行代码块所需的运行时上下文的入口和出口。通常使用with语句(在with语句部分中描述)调用上下文管理器,但是也可以通过直接调用其方法来使用上下文管理器 。
上下文管理器的典型用法包括保存和还原各种全局状态,锁定和解锁资源,关闭打开的文件等。
有关上下文管理器的更多信息,请参见上下文管理器类型。
object.__enter__(自我)
输入与此对象相关的运行时上下文。该with语句会将此方法的返回值绑定到as该语句的子句中指定的目标( 如果有)。
object.__exit__(self,exc_type,exc_value,traceback )
退出与此对象相关的运行时上下文。参数描述导致上下文退出的异常。如果上下文无例外地退出,则所有三个参数均为None。
如果提供了异常,并且该方法希望抑制该异常(即,防止其传播),则它应返回一个真值。否则,将在退出此方法后正常处理异常。
注意,__exit__()方法不应该引发传入的异常。这是呼叫者的责任。
也可以看看
PEP 343- “ with”声明
Python with 语句的规范,背景和示例。
3.3.10。特殊方法查找
对于自定义类,只有在对对象的类型(而不是在对象的实例字典中)进行定义的情况下,才能保证对特殊方法的隐式调用可以正常工作。该行为是以下代码引发异常的原因:
>>>
>>> class C:
... pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type "C" has no len()
此行为背后的原理在于许多特殊方法,例如__hash__()和__repr__()由所有对象(包括类型对象)实现。如果这些方法的隐式查找使用常规查找过程,则在对类型对象本身进行调用时它们将失败:
>>>
>>> 1 .__hash__() == hash(1)
True
>>> int.__hash__() == hash(int)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: descriptor "__hash__" of "int" object needs an argument
以这种方式错误地尝试调用类的未绑定方法有时被称为“元类混淆”,通过在查找特殊方法时绕过实例可以避免这种情况:
>>>
>>> type(1).__hash__(1) == hash(1)
True
>>> type(int).__hash__(int) == hash(int)
True
除了出于准确性的考虑绕过任何实例属性之外,隐式特殊方法查找通常还绕过该 __getattribute__()方法,甚至对象的元类也是如此:
>>>
>>> class Meta(type):
... def __getattribute__(*args):
... print("Metaclass getattribute invoked")
... return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print("Class getattribute invoked")
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
__getattribute__()以这种方式绕过机器为解释器内的速度优化提供了很大的空间,但以牺牲一些特殊方法的灵活性为代价(必须在类对象本身上设置特殊方法,以便由解释器一致地调用) 。