流暢的python學習筆記-第15章

第15章 上下文管理器和else塊

<!-- TOC -->python

<!-- /TOC -->code

try..except..finally

看一個例子:對象

def get_result():
    a = 3
    b = 0
    try:
        b = 3 / 0
    except Exception as e:
        print("ERROR=", e)
    finally:
        print("a=", a)


if __name__ == "__main__":
    get_result()

返回結果是:字符串

ERROR= division by zero
a= 3



總結:get

try..except..else沒有捕獲到異常,執行else語句
try..except..finally無論是否捕獲到異常,都執行finally語句

with語句

python文本文件讀寫的3種方法it

# 第一種方法:
file1 = open("test.txt")
file2 = open("output.txt", "w")
while True:
    line = file1.readline()
    # 這裏能夠進行邏輯處理
    file2.write(line)
    if not line:
        break

# 記住文件處理完,關閉是個好習慣
file1.close()
file2.close()

# 讀文件有3種方法:
# - read()將文本文件全部行讀到一個字符串中。
# - readline()是一行一行的讀
# - readlines()是將文本文件中全部行讀到一個list中,文本文件每一行是list的一個元素。

# 優勢:readline()能夠在讀行過程當中跳過特定行。

# 第二種方法:文件迭代器,用for循環的方法
file2 = open("output.txt", "w")
for line in open("test.txt"):
    # 這裏能夠進行邏輯處理
    file2.write(line)

# 第三種方法: 推薦使用這個方法文件上下文管理器
with open('somefile.txt', 'r') as f:
    data = f.read()

with open('somefile.txt', 'r') as f:
    for line in f:
        print(line)

with open('somefile.txt', 'w') as f:
    f.write("hello")

這裏重點說說第三種方法io

打開文件在進行讀寫的時候可能會出現一些異常情況,若是按照常規的f.open
寫法,咱們須要try,except,finally,作異常判斷,而且文件最終無論遇到什麼狀況,都要執行finally f.close()關閉文件,with方法幫咱們實現了finally中f.closefor循環

上下文管理器

上下文管理器協議包含__enter__ 和 __exit__ 兩個方法。class

with 語句開始運行時,會在上下文管理器對象上調用 __enter__ 方法。
with 語句運行結束後,會在上下文管理器對象上調用 __exit__ 方法,以此扮演 finally 子句的角色。

最多見的例子是確保關閉文件對象

class T(object):
    def __enter__(self):
        print('T.__enter__')
        return '我是__enter__的返回值'

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('T.__exit__')


with T() as t:
    print(t)

返回結果:

T.__enter__
我是__enter__的返回值
T.__exit__

with之於上下文管理器,就像for之於迭代器同樣。with就是爲了方便上下文管理器的使用。

@contextmanager 裝飾器

下文管理器就不得不提一下@contextmanager 裝飾器,它能減小建立上下文管理器的樣板代碼量,

由於不用編寫一個完整的類,定義 __enter__和 __exit__ 方法,而只需實現有一個 yield 語句的生成器,生成想讓 __enter__ 方法返回的值。

@contextmanager 裝飾器優雅且實用,把三個不一樣的 Python 特性結合到了一塊兒:函數裝飾器、生成器和 with 語句。

在使用 @contextmanager 裝飾的生成器中,yield 語句的做用是把函數的定義體分紅兩部分:

1. yield 語句前面的全部代碼在 with 塊開始時(即解釋器調用` __enter__` 方法時)執行
2. yield 語句後面的代碼在with 塊結束時(即調用 `__exit__` 方法時)執行。

例子:

import sys
import contextlib


@contextlib.contextmanager
def WoHa(n):
    original_write = sys.stdout.write

    def reverse_write(text):
        original_write(text[::-1])

    sys.stdout.write = reverse_write
    yield n
    sys.stdout.write = original_write
    return True


obj1 = WoHa('你手機拿反了')
with obj1 as content:
    print('哈哈鏡花緣')
    print(content)

print('#### with 執行完畢後,在輸出content: ####')
print(content)

返回結果:

緣花鏡哈哈
了反拿機手你
#### with 執行完畢後,在輸出content: ####
你手機拿反了

這裏咱們須要注意的是:

代碼執行到yield時,會產出一個值,這個值會綁定到 with 語句中 as 子句的變量上。執行 with 塊中的代碼時,這個函數會在yield這裏暫停。

相關文章
相關標籤/搜索