Trình quản lý bối cảnh Python tự trả về

Trong Python, trình quản lý bối cảnh là một đối tượng có thể được sử dụng trong câu lệnh

with Timer("doing stuff"):
    for i in range(1000000):
        pass
2. Đây là trình quản lý ngữ cảnh báo cáo tổng thời gian đồng hồ treo tường đã sử dụng bên trong khối
with Timer("doing stuff"):
    for i in range(1000000):
        pass
2

import time

class Timer(object):
    def __init__(self, msg):
        self._msg = msg

    def __enter__(self):
        # time.monotonic() requires Python >= 3.3
        self._start = time.monotonic()

    def __exit__(self, exc_type, exc_value, exc_traceback):
        if exc_type:
            print('Failed: {}: {}'.format(self._msg, exc_value))
        else:
            print('{}: {} s'.format(self._msg, time.monotonic() - self._start))

Chúng ta có thể sử dụng nó như thế này

with Timer("doing stuff"):
    for i in range(1000000):
        pass

cái nào tạo ra đầu ra này

doing stuff: 0.04281306266784668 s

Xử lý ngoại lệ

Trình quản lý ngữ cảnh cũng có thể xử lý các ngoại lệ từ bên trong khối mà chúng bảo vệ.

with Timer("doing stuff"):
    for i in range(1000000):
        pass
4 làm điều này. Nếu chúng ta làm

with Timer("doing stuff"):
    raise ValueError('ack')

chúng tôi nhận được

Failed: doing stuff: ack
Traceback (most recent call last):
  File "test.py", line 20, in <module>
    raise ValueError('ack')
ValueError: ack

Bởi vì

with Timer("doing stuff"):
    for i in range(1000000):
        pass
5 không trả lại
with Timer("doing stuff"):
    for i in range(1000000):
        pass
6, ngoại lệ tiếp tục lan truyền, vì vậy chúng tôi thấy cả thông báo
with Timer("doing stuff"):
    for i in range(1000000):
        pass
7 và truy nguyên. Nếu
with Timer("doing stuff"):
    for i in range(1000000):
        pass
5 trả về
with Timer("doing stuff"):
    for i in range(1000000):
        pass
6, ngoại lệ sẽ bị trình quản lý bối cảnh nuốt và chúng tôi sẽ chỉ thấy dòng
with Timer("doing stuff"):
    for i in range(1000000):
        pass
7

Bối cảnh từ trình quản lý bối cảnh

Giả sử chúng ta muốn trình quản lý bối cảnh trả về một số thông tin, có lẽ là mức độ chi tiết của bộ đếm thời gian. Chúng ta có thể sửa đổi

doing stuff: 0.04281306266784668 s
1 như thế này

def __enter__(self):
    # time functions require Python >= 3.3
    self._start = time.monotonic()
    return time.clock_getres(time.CLOCK_MONOTONIC)

Bây giờ chúng ta có thể làm

with Timer("doing stuff") as resolution:
    print('Resolution: {}'.format(resolution))
    for i in range(1000000):
        pass

sản xuất

Resolution: 1e-09
doing stuff: 0.043778783998277504 s

Người trang trí doing stuff: 0.04281306266784668 s 2

Viết trình quản lý bối cảnh liên quan đến một số bản soạn sẵn. các phương thức

doing stuff: 0.04281306266784668 s
1 và
with Timer("doing stuff"):
    for i in range(1000000):
        pass
5 và có thể là một phương thức
doing stuff: 0.04281306266784668 s
5 để xử lý bất kỳ đối số nào. Có một cách dễ dàng hơn. người trang trí
doing stuff: 0.04281306266784668 s
6. Chúng ta có thể viết lại
with Timer("doing stuff"):
    for i in range(1000000):
        pass
4 như thế này

import contextlib
import time

@contextlib.contextmanager
def Timer(msg):
    start = time.monotonic()
    try:
        yield time.clock_getres(time.CLOCK_MONOTONIC)
    except BaseException as e:
        print('Failed: {}: {}'.format(msg, e))
        raise
    else:
        print('{}: {} s'.format(msg, time.monotonic() - start))

Bây giờ

with Timer("doing stuff"):
    for i in range(1000000):
        pass
4 chỉ là một trình tạo ra kết quả một lần (mang lại giá trị bị ràng buộc bởi câu lệnh
with Timer("doing stuff"):
    for i in range(1000000):
        pass
2). Biểu thức
with Timer("doing stuff"):
    raise ValueError('ack')
0 đưa ra bất kỳ ngoại lệ nào được ném ra khỏi khối, sau đó trình quản lý ngữ cảnh có thể xử lý hay không

tự quản lý

Một cách sử dụng cho trình quản lý bối cảnh là đảm bảo rằng một đối tượng (tệp, kết nối mạng, xử lý cơ sở dữ liệu) được đóng khi rời khỏi một khối.

with Timer("doing stuff"):
    raise ValueError('ack')
1 làm điều này. phương thức
with Timer("doing stuff"):
    for i in range(1000000):
        pass
5 của nó gọi một đối tượng khác là
with Timer("doing stuff"):
    raise ValueError('ack')
3. Sử dụng nó như thế này

import contextlib

with contextlib.closing(open("/etc/passwd")) as fh:
    lines = fh.readlines()

Nhưng điều đó có vẻ hơi dài dòng. Một cách tiếp cận tốt hơn. nhiều đối tượng triển khai

doing stuff: 0.04281306266784668 s
1 và
with Timer("doing stuff"):
    for i in range(1000000):
        pass
5, vì vậy bạn có thể sử dụng chúng để tự quản lý. Việc triển khai
with Timer("doing stuff"):
    raise ValueError('ack')
6 (loại được trả về bởi
with Timer("doing stuff"):
    raise ValueError('ack')
7) có nội dung như thế này

Chức năng __ nhập __ trong Python là gì?

__enter__ và [__exit__] đều là các phương thức được gọi khi nhập và thoát khỏi phần thân của "câu lệnh with" (PEP . câu lệnh with có ý định ẩn điều khiển luồng của mệnh đề try last và làm cho mã trở nên khó hiểu.

Điều gì nên __ thoát __ trở lại trong Python?

__exit__() là một phương thức trừu tượng theo mặc định trả về Không có . Xem thêm định nghĩa về các loại trình quản lý ngữ cảnh. Mới trong phiên bản 3. 6. Một lớp cơ sở trừu tượng cho các lớp thực hiện đối tượng.

Những hành động nào được đảm bảo bởi trình quản lý bối cảnh Python?

Nếu bạn đã sử dụng câu lệnh with trong Python thì rất có thể bạn đã sử dụng trình quản lý ngữ cảnh. Trình quản lý bối cảnh thường đảm nhận việc thiết lập một số tài nguyên, chẳng hạn như. g. mở kết nối và tự động xử lý việc dọn dẹp khi chúng tôi hoàn thành việc này . Có lẽ, trường hợp sử dụng phổ biến nhất là mở tệp.

Sự khác biệt giữa trình trang trí và trình quản lý ngữ cảnh trong Python là gì?

trình quản lý bối cảnh là các đối tượng được sử dụng với python với từ khóa. Nó chạy mã khi vào khối và thoát khỏi khối. decorators là những sửa đổi đối với một hàm hoặc định nghĩa lớp. Nó chạy mã thay thế chức năng như nó đang được xác định