"""
#[Notes]
#1?? Try: Run an else block only if no exception is thrown in the try block.
#2?? For: only if the For Loop has finished running (that is, the for loop has not been terminated by the break statement) Else
#while: Runs only if the while loop exits because the condition is a pseudo-implant (that is, the while loop is not terminated by a break statement) else
#即在所有情况下, if an exception or return, break, or continue statement causes control to jump beyond the main block of a compound statement, the ELSE clause is also skipped
#15. 2 Context Manager and with block
#上下文管理协议包含__enter__和__exit__两个方法. When the With statement starts running, the __enter__ method is called on the context manager object. When the WITH statement finishes running, the __exit__ method is called on the context Manager object to play the role of the finally clause
#例子15-1
With open (' __init__.py ') as FP:
src = fp.read (60)
Print (len (src)) #4
Print (FP) #<_io. Textiowrapper name= ' __init__.py ' mode= ' r ' encoding= ' UTF-8 ' >
Print (fp.closed,fp.encoding) #True UTF-8
Print (fp.read) #ValueError: I/O operation on closed file.
#例子15-2 emphasizes the difference between the context manager and the objects returned by the __enter__ method
Class Lookingclass:
def __enter__ (self): # In addition to self, Python does not pass in other parameters when calling the __enter__ method
Import Sys
Self.original_write = Sys.stdout.write #往标准输出里写入数据, equivalent to print
Sys.stdout.write = Self.reverse_write #为sys. Stdout.write Play Monkey Patch
Return ' Jabberwocky '
def reverse_write (Self,text):
Self.original_write (Text[::-1])
def __exit__ (self, exc_type, Exc_val, EXC_TB): #exc_type Exception Class (for example, Zerodivisionerror) Exc_value exception instance. Sometimes arguments are passed to the exception construction method, such as error messages, which can be used to get the Traceback:traceback object using Exc_value.args.
Import SYS # repeated pouring into the module does not consume a lot of resources because Python caches imported modules
Sys.stdout.write = Self.original_write #还原原来的sys. Stdout.write method
If Exc_type is zerodivisionerror:
Print (' Divide by zero! ')
Return True #告诉解释器, exception has been resolved
#如果__exit__方法返回None, or a value other than true, any exception in the With block will bubble up
With Lookingclass () as What: #上下文管理器是LookingClass类的实例, Python calls the __enter__ method on the context manager to bind the result to what
Print (' Alice,kigtty and Snowdrop ') #pordwonS DNA Yttgik,ecila
Print (what) #YKCOWREBBAJ
Print (what) #JABBERWOCKY output is no longer reversed
Print (' Back to normal. ') #Back to normal. Output is no longer reversed
#例子15-4 using the Lookingclass class outside of the With block
Manager = Lookingclass ()
Print (manager) #<__main__. Lookingclass Object at 0x10d593be0>
Monster = manager.__enter__ ()
Print (Monster = = ' Jabberwocky ') #eurT
Print (Monster) #YKCOWREBBAJ
Print (manager) #>8abfca001x0 ta tcejbo ssalcgnikool.__niam__<
manager.__exit__ (None,none,none)
Print (Monster) #JABBERWOCKY
# #15.3 utilities in the Contextlib module
#closing: If the object provides a close () method, but does not implement the __ENTER__/__EXIT__ protocol, then you can use this function to build the context Manager
#suppress construct a context manager that temporarily ignores the specified exception
# @contextmanager This decorator turns a simple generator function into a context manager, so you don't have to create a class fetch implementation manager protocol.
#15.4 using @contextmanager
#例子15-5 Context manager implemented using the generator
Import Contextlib
@contextlib. ContextManager
Def looking_glass ():
Import Sys
Original_write = Sys.stdout.write
def reverse_write (text):
Original_write (Text[::-1])
Sys.stdout.write = Reverse_write
Yield ' Jabberwocky '
Sys.stdout.write = Original_write
#例子15-6 Test
With Looking_glass () as What:
Print (' Alice,kitty and Snowdrop ') #pordwonS DNA Yttik,ecila
Print (what) #YKCOWREBBAJ
Print (what) #JABBERWOCKY
#[analysis] In fact, the Contextlib.contextmanager decorator will wrap the function into classes that implement __enter__ and __exit__ methods. The __enter__ method of this class has the following effect
#... 1?? Call the generator function to save the generator object (this is called Gen)
#... 2?? Call Next (gen) and execute to the location where the yield keyword is located
#... 3?? Returns the value of the next (gen) output to bind the output value to the target variable in the With/as statement.
When the #...with block terminates, the __exit__ method will do several things
#... 1?? Check that the exception is passed to Exc_type; if there is, call Gen.throw (Exception), the line that contains the yield keyword in the generator function definition body throws an exception
#... 2?? Otherwise, the whine continues with next (Gen) to execute the code after the yield in the body of the generator function definition
# "Note" The above example has a serious error: If an exception occurs, the Python interpreter captures it and then throws it again in the yield expression of the Looking_glass function. However, there is no code to handle the error, so the Looking_glass function aborts and can never revert to the original Sys.stdout.write method, causing the system to be in an invalid state
# example 15-7 the context manager based on the generator, and exception handling is implemented-
"""
Import Contextlib
@contextlib. ContextManager
Def looking_glass ():
Import Sys
Original_write = Sys.stdout.write
def reverse_write (text):
Original_write ([text[::-1]])
Sys.stdout.write = Reverse_write
msg = "
Try
Yield ' Jabberwocky '
Except Zerodivisionerror:
msg = ' Please don't divede by zero! '
Finally
Sys.stdout.write = Original_write
If msg:
Print (msg)
"Python" "Control Flow" "Two" "Context manager"