พิจารณาสิ่งต่อไปนี้:
with open(path, mode) as f:
return [line for line in f if condition]
ไฟล์จะปิดอย่างถูกต้องหรือใช้การreturn
ข้ามบริบทตัวจัดการอย่างใดอย่างหนึ่งหรือไม่
พิจารณาสิ่งต่อไปนี้:
with open(path, mode) as f:
return [line for line in f if condition]
ไฟล์จะปิดอย่างถูกต้องหรือใช้การreturn
ข้ามบริบทตัวจัดการอย่างใดอย่างหนึ่งหรือไม่
คำตอบ:
ใช่มันทำหน้าที่เหมือนfinally
บล็อกหลังtry
บล็อกนั่นคือมันจะดำเนินการเสมอ (เว้นแต่ว่ากระบวนการของไพ ธ อนจะยุติลงด้วยวิธีที่ผิดปกติ)
มันถูกกล่าวถึงในหนึ่งในตัวอย่างของPEP-343ซึ่งเป็นข้อกำหนดสำหรับwith
คำสั่ง:
with locked(myLock):
# Code here executes with myLock held. The lock is
# guaranteed to be released when the block is left (even
# if via return or by an uncaught exception).
อย่างไรก็ตามสิ่งที่ควรค่าแก่การกล่าวถึงคือคุณไม่สามารถจับข้อยกเว้นที่เกิดขึ้นจากการopen()
โทรได้โดยง่ายโดยไม่ต้องวางwith
บล็อกทั้งหมดไว้ในtry..except
บล็อกซึ่งโดยปกติจะไม่ใช่สิ่งที่ต้องการ
Process.terminate()
เป็นหนึ่งในไม่กี่สถานการณ์ (เท่านั้น) ที่ไม่รับประกันการเรียกใช้finally
คำสั่ง: "โปรดทราบว่าตัวจัดการทางออกและส่วนท้าย ฯลฯ จะไม่เป็นเช่นนั้น ดำเนินการ."
with
บล็อกการรับประกันจะเก็บไว้ตราบใดที่เครื่องกำเนิดยังคงให้ค่าผล? ตราบใดที่มีการอ้างอิงอะไร คือฉันจำเป็นต้องใช้del
หรือกำหนดค่าที่แตกต่างให้กับตัวแปรที่เก็บวัตถุตัวสร้าง?
ValueError: I/O operation on closed file.
จากไฟล์ที่จะทำให้:
ใช่.
def example(path, mode):
with open(path, mode) as f:
return [line for line in f if condition]
.. มันเทียบเท่ากับ:
def example(path, mode):
f = open(path, mode)
try:
return [line for line in f if condition]
finally:
f.close()
แม่นยำยิ่งขึ้น__exit__
วิธีการในตัวจัดการบริบทจะถูกเรียกเสมอเมื่อออกจากบล็อก (ไม่ว่าจะมีข้อยกเว้นส่งคืน ฯลฯ ) หรือไม่ __exit__
วิธีการของวัตถุไฟล์เพียงแค่เรียกf.close()
(เช่นที่นี่ใน CPython )
finally
keywrod def test(): try: return True; finally: return False
คือ:
ใช่. โดยทั่วไปแล้ว__exit__
วิธีการของWith Context Managerจะถูกเรียกใช้ในกรณีที่มี a return
จากภายในบริบท สิ่งนี้สามารถทดสอบได้ดังต่อไปนี้:
class MyResource:
def __enter__(self):
print('Entering context.')
return self
def __exit__(self, *exc):
print('EXITING context.')
def fun():
with MyResource():
print('Returning inside with-statement.')
return
print('Returning outside with-statement.')
fun()
ผลลัพธ์คือ:
Entering context.
Returning inside with-statement.
EXITING context.
ผลลัพธ์ข้างต้นยืนยันว่า__exit__
ถูกเรียกทั้ง ๆ ที่ก่อนreturn
หน้านี้ ดังนั้นตัวจัดการบริบทจะไม่ถูกข้าม
ใช่ แต่อาจมีผลข้างเคียงบางอย่างในกรณีอื่น ๆ เพราะอาจทำบางสิ่ง (เช่นการล้างบัฟเฟอร์) ใน__exit__
บล็อก
import gzip
import io
def test(data):
out = io.BytesIO()
with gzip.GzipFile(fileobj=out, mode="wb") as f:
f.write(data)
return out.getvalue()
def test1(data):
out = io.BytesIO()
with gzip.GzipFile(fileobj=out, mode="wb") as f:
f.write(data)
return out.getvalue()
print(test(b"test"), test1(b"test"))
# b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff' b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff+I-.\x01\x00\x0c~\x7f\xd8\x04\x00\x00\x00'
else
สามารถเพิ่มwith
เพื่อแก้ไขtry with except
ปัญหานั้นได้ แก้ไข: เพิ่มในภาษา