assert
ผมได้อ่านรหัสที่มาบางส่วนและในหลายสถานที่ที่ฉันได้เห็นการใช้งานของ
มันหมายความว่าอะไรกันแน่? การใช้งานคืออะไร?
assert
ผมได้อ่านรหัสที่มาบางส่วนและในหลายสถานที่ที่ฉันได้เห็นการใช้งานของ
มันหมายความว่าอะไรกันแน่? การใช้งานคืออะไร?
คำตอบ:
assert
คำสั่งที่มีอยู่ในเกือบทุกภาษาการเขียนโปรแกรม มันช่วยตรวจจับปัญหาในช่วงต้นของโปรแกรมของคุณโดยที่สาเหตุชัดเจนมากกว่าในภายหลังซึ่งเป็นผลข้างเคียงของการทำงานอื่น ๆ
เมื่อคุณทำ ...
assert condition
... คุณกำลังบอกโปรแกรมให้ทดสอบเงื่อนไขนั้นและเรียกใช้ข้อผิดพลาดทันทีหากเงื่อนไขเป็นเท็จ
ใน Python มันเทียบเท่ากับสิ่งนี้:
if not condition:
raise AssertionError()
ลองในเปลือก Python:
>>> assert True # nothing happens
>>> assert False
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
การยืนยันสามารถรวมข้อความที่เป็นทางเลือกและคุณสามารถปิดใช้งานได้เมื่อใช้ล่าม
หากต้องการพิมพ์ข้อความหากการยืนยันล้มเหลว:
assert False, "Oh no! This assertion failed!"
อย่าได้ใช้วงเล็บต่อการเรียกร้องassert
เช่นฟังก์ชั่น มันเป็นคำสั่ง หากคุณเป็นเช่นนั้นassert(condition, message)
คุณจะเรียกใช้assert
ด้วย(condition, message)
tuple เป็นพารามิเตอร์แรก
สำหรับการปิดการใช้งานพวกเขาเมื่อทำงานpython
ในโหมดปรับให้เหมาะสมที่ไหน__debug__
คือFalse
คำสั่งยืนยันจะถูกละเว้น เพิ่งผ่าน-O
ธง:
python -O script.py
ดูที่นี่สำหรับเอกสารที่เกี่ยวข้อง
if not condition: raise AssertError()
มันทำไมฉันต้องใช้ยืนยัน? มีเงื่อนไขใดบ้างที่ยืนยันได้ดีกว่าการเป็นข้อความสั้น ๆif not condition
?
if
) อ่านเอกสารสำหรับข้อมูลเพิ่มเติม :)
assert
แต่หลังจากอ่านคำตอบทั้งหมดฉันไม่มีอะไรที่ฉันต้องการ!
ระวังวงเล็บ ดังที่ได้กล่าวไว้ข้างต้นใน Python 3 assert
ยังคงเป็นคำสั่งดังนั้นเมื่อเปรียบเทียบกับสิ่งprint(..)
หนึ่งอาจคาดการณ์ถึงassert(..)
หรือไม่raise(..)
แต่คุณไม่ควร
สิ่งนี้สำคัญเนื่องจาก:
assert(2 + 2 == 5, "Houston we've got a problem")
จะไม่ทำงานไม่เหมือน
assert 2 + 2 == 5, "Houston we've got a problem"
เหตุผลที่คนแรกที่จะไม่ทำงานที่ประเมินbool( (False, "Houston we've got a problem") )
True
ในคำสั่งassert(False)
เหล่านี้เป็นวงเล็บที่ซ้ำซ้อนFalse
ซึ่งประเมินถึงเนื้อหา แต่ด้วยassert(False,)
วงเล็บตอนนี้เป็นสิ่งอันดับและสิ่งอันดับที่ไม่ว่างจะประเมินTrue
เป็นบริบทบูลีน
assert (2 + 2 = 5), "Houston we've got a problem"
ควรจะตกลงใช่ไหม
assert (2 + 2 = 5), "Houston we've got a problem"
จะไม่ทำงาน ... แต่มันไม่มีส่วนเกี่ยวข้องกับคำสั่งยืนยันซึ่งใช้ได้ เงื่อนไขของคุณจะไม่ทำงานเพราะไม่ใช่เงื่อนไข =
หายไปเป็นครั้งที่สอง
ดังที่คำตอบอื่น ๆ ระบุไว้assert
นั้นคล้ายกับการโยนข้อยกเว้นหากเงื่อนไขที่กำหนดไม่เป็นความจริง -O
ความแตกต่างที่สำคัญคือว่างบยืนยันได้รับการละเว้นถ้าคุณรวบรวมรหัสของคุณมีตัวเลือกในการเพิ่มประสิทธิภาพ เอกสารบอกว่าassert expression
ดีขึ้นสามารถอธิบายได้ว่าเป็นเทียบเท่ากับ
if __debug__:
if not expression: raise AssertionError
สิ่งนี้มีประโยชน์หากคุณต้องการทดสอบรหัสของคุณอย่างละเอียดจากนั้นปล่อยรุ่นที่ปรับปรุงแล้วเมื่อคุณพอใจที่กรณีการยืนยันของคุณล้มเหลว - เมื่อเปิดใช้งานการปรับให้เหมาะสม__debug__
ตัวแปรจะกลายเป็นเท็จและเงื่อนไขจะหยุดประเมิน ฟีเจอร์นี้สามารถติดตามคุณได้หากคุณเชื่อมั่นในการยืนยันและไม่ทราบว่าพวกเขาหายตัวไป
if Not Error: raise Exception(“ this is a error”)
? ด้วยวิธีนี้โปรแกรมจะยังคงแสดงแหล่งที่มาของข้อผิดพลาดเมื่อผู้ใช้รัน ..
assert
คำสั่งหรือไม่ สมมติฐานที่นี่คือเมื่อโปรแกรมถูกปล่อยให้กับผู้ใช้คุณกำลังใช้แฟล็ก -O ดังนั้นสมมติว่าข้อบกพร่องทั้งหมดได้ถูกลบออก ดังนั้นข้อผิดพลาดหรือความผิดพลาดของโปรแกรมเกิดจากการป้อนข้อมูลไปยังโปรแกรมที่ถูกต้องตามสัญญา แต่โปรแกรมไม่สามารถจัดการได้ ดังนั้นควรแจ้งเตือนผู้ใช้เช่นนี้
เป้าหมายของการยืนยันใน Python คือการแจ้งให้นักพัฒนาทราบถึงข้อผิดพลาดที่ไม่สามารถกู้คืนได้ในโปรแกรม
การยืนยันไม่ได้มีวัตถุประสงค์เพื่อส่งสัญญาณเงื่อนไขข้อผิดพลาดที่คาดไว้เช่น "ไม่พบไฟล์" ซึ่งผู้ใช้สามารถดำเนินการแก้ไขได้ (หรือลองอีกครั้ง)
อีกวิธีในการดูคือการยืนยันว่าเป็นการตรวจสอบภายในด้วยตนเองในรหัสของคุณ พวกเขาทำงานโดยการประกาศเงื่อนไขบางอย่างที่เป็นไปไม่ได้ในรหัสของคุณ หากเงื่อนไขเหล่านี้ไม่ถือหมายความว่ามีข้อผิดพลาดในโปรแกรม
หากโปรแกรมของคุณปราศจากข้อผิดพลาดเงื่อนไขเหล่านี้จะไม่เกิดขึ้น แต่ถ้าหนึ่งของพวกเขาไม่ได้เกิดขึ้นโปรแกรมจะผิดพลาดด้วยข้อผิดพลาดการยืนยันบอกคุณว่าที่“เป็นไปไม่ได้” สภาพถูกเรียก สิ่งนี้ทำให้ง่ายต่อการติดตามและแก้ไขข้อบกพร่องในโปรแกรมของคุณ
นี่เป็นบทสรุปจากการสอนเกี่ยวกับการยืนยันของ Python ที่ฉันเขียน:
ข้อความยืนยันของ Python เป็นเครื่องช่วยในการดีบั๊กไม่ใช่กลไกสำหรับจัดการข้อผิดพลาดขณะทำงาน เป้าหมายของการใช้การยืนยันคือเพื่อให้นักพัฒนาค้นหาสาเหตุที่เป็นไปได้ของข้อผิดพลาดได้เร็วขึ้น ข้อผิดพลาดในการยืนยันไม่ควรถูกยกขึ้นหากมีข้อผิดพลาดในโปรแกรมของคุณ
assert
คำแถลงและเวลาใช้งาน ฉันพยายามทำความเข้าใจกับคำศัพท์หลายคำที่คุณแนะนำไว้ในบทความ
assert store.product_exists(product_id), 'Unknown product id'
ไม่ใช่วิธีปฏิบัติที่ดีเพราะหากปิดการดีบักแล้วuser
แม้ว่าจะไม่admin
สามารถลบผลิตภัณฑ์ได้ คุณถือว่าassert user.is_admin()
เป็นunrecoverable
ข้อผิดพลาดหรือไม่? นี่คือเหตุผลที่ไม่ได้เป็นself-check
?
assert statement
, ไม่price
สามารถพิจารณาอินพุตของผู้ใช้ได้เช่นกัน? ทำไมคุณพิจารณาassert user.is_admin()
เป็นการตรวจสอบข้อมูล แต่ไม่assert price
?
คนอื่น ๆ ได้มอบลิงก์ไปยังเอกสารให้คุณแล้ว
คุณสามารถลองสิ่งต่อไปนี้ในเชลล์แบบโต้ตอบ:
>>> assert 5 > 2
>>> assert 2 > 5
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
builtins.AssertionError:
คำสั่งแรกไม่ทำอะไรเลยในขณะที่คำสั่งที่สองยกข้อยกเว้น นี่คือคำใบ้แรก: การยืนยันมีประโยชน์ในการตรวจสอบเงื่อนไขที่ควรเป็นจริงในตำแหน่งที่กำหนดของโค้ดของคุณ (โดยปกติคือจุดเริ่มต้น (เงื่อนไขเบื้องต้น) และจุดสิ้นสุดของฟังก์ชัน (postconditions)
Asserts นั้นผูกติดอยู่กับการเขียนโปรแกรมโดยสัญญาซึ่งเป็นวิธีปฏิบัติทางวิศวกรรมที่มีประโยชน์
จากเอกสาร:
Assert statements are a convenient way to insert debugging assertions into a program
คุณสามารถอ่านเพิ่มเติมได้ที่นี่: http://docs.python.org/release/2.5.2/ref/assert.html
คำสั่งยืนยันมีสองรูปแบบ
รูปแบบที่เรียบง่ายassert <expression>
เทียบเท่ากับ
if __debug__:
if not <expression>: raise AssertionError
แบบฟอร์มเพิ่มเติมassert <expression1>, <expression2>
, เทียบเท่ากับ
if __debug__:
if not <expression1>: raise AssertionError, <expression2>
การยืนยันเป็นวิธีที่เป็นระบบในการตรวจสอบว่าสถานะภายในของโปรแกรมเป็นไปตามที่โปรแกรมเมอร์คาดไว้โดยมีเป้าหมายในการจับข้อบกพร่อง ดูตัวอย่างด้านล่าง
>>> number = input('Enter a positive number:')
Enter a positive number:-1
>>> assert (number > 0), 'Only positive numbers are allowed!'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: Only positive numbers are allowed!
>>>
นี่คือตัวอย่างง่ายๆบันทึกสิ่งนี้ในไฟล์ (สมมติว่า b.py)
def chkassert(num):
assert type(num) == int
chkassert('a')
และผลเมื่อ $python b.py
Traceback (most recent call last):
File "b.py", line 5, in <module>
chkassert('a')
File "b.py", line 2, in chkassert
assert type(num) == int
AssertionError
ถ้าคำสั่งหลังจากยืนยันเป็นจริงแล้วโปรแกรมจะดำเนินการต่อ แต่ถ้าคำสั่งหลังจากยืนยันเป็นเท็จโปรแกรมจะแจ้งข้อผิดพลาด เรียบง่ายเหมือนที่
เช่น:
assert 1>0 #normal execution
assert 0>1 #Traceback (most recent call last):
#File "<pyshell#11>", line 1, in <module>
#assert 0>1
#AssertionError
assert
คำสั่งที่มีอยู่ในเกือบทุกภาษาการเขียนโปรแกรม มันช่วยตรวจจับปัญหาในช่วงต้นของโปรแกรมของคุณโดยที่สาเหตุชัดเจนมากกว่าในภายหลังซึ่งเป็นผลข้างเคียงของการทำงานอื่น ๆ พวกเขาคาดหวังTrue
เงื่อนไขเสมอ
เมื่อคุณทำสิ่งที่ชอบ:
assert condition
คุณกำลังบอกโปรแกรมให้ทดสอบเงื่อนไขนั้นและเรียกใช้ข้อผิดพลาดทันทีหากเป็นเท็จ
ใน Python assert
นิพจน์เทียบเท่ากับ:
if __debug__:
if not <expression>: raise AssertionError
คุณสามารถใช้นิพจน์แบบขยายเพื่อส่งข้อความเพิ่มเติม :
if __debug__:
if not (expression_1): raise AssertionError(expression_2)
ลองใช้ใน Python interpreter:
>>> assert True # Nothing happens because the condition returns a True value.
>>> assert False # A traceback is triggered because this evaluation did not yield an expected value.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
มีคำเตือนบางอย่างที่จะเห็นก่อนที่จะใช้เป็นหลักสำหรับผู้ที่คิดจะสลับไปมาระหว่างคำสั่งassert
และ if
มีจุดมุ่งหมายที่จะใช้assert
ในบางโอกาสเมื่อโปรแกรมตรวจสอบเงื่อนไขและส่งคืนค่าที่ควรหยุดโปรแกรมทันทีแทนที่จะใช้วิธีอื่นเพื่อหลีกเลี่ยงข้อผิดพลาด:
ดังที่คุณอาจสังเกตเห็นว่าassert
คำสั่งใช้สองเงื่อนไข ดังนั้นจะไม่ใช้วงเล็บ englobe พวกเขาเป็นหนึ่งในคำแนะนำที่ชัดเจน หากคุณทำเช่น:
assert (condition, message)
ตัวอย่าง:
>>> assert (1==2, 1==1)
<stdin>:1: SyntaxWarning: assertion is always true, perhaps remove parentheses?
คุณจะถูกเรียกใช้assert
ด้วย(condition, message)
ซึ่งหมายถึง tuple เป็นพารามิเตอร์แรกและสิ่งนี้เกิดขึ้นสาเหตุ tuple ไม่ว่างเปล่าในหลามเป็นเสมอ True
อย่างไรก็ตามคุณสามารถแยกกันได้โดยไม่มีปัญหา:
assert (condition), "message"
ตัวอย่าง:
>>> assert (1==2), ("This condition returns a %s value.") % "False"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: This condition returns a False value.
หากคุณสงสัยว่าเมื่อใช้assert
คำสั่ง นำตัวอย่างที่ใช้ในชีวิตจริง:
* เมื่อโปรแกรมของคุณมีแนวโน้มที่จะควบคุมแต่ละพารามิเตอร์ที่ป้อนโดยผู้ใช้หรือสิ่งอื่น:
def loremipsum(**kwargs):
kwargs.pop('bar') # return 0 if "bar" isn't in parameter
kwargs.setdefault('foo', type(self)) # returns `type(self)` value by default
assert (len(kwargs) == 0), "unrecognized parameter passed in %s" % ', '.join(kwargs.keys())
* อีกกรณีอยู่ในวิชาคณิตศาสตร์เมื่อ 0 หรือไม่บวกเป็นสัมประสิทธิ์หรือค่าคงที่ในสมการบางอย่าง:
def discount(item, percent):
price = int(item['price'] * (1.0 - percent))
print(price)
assert (0 <= price <= item['price']),\
"Discounted prices cannot be lower than 0 "\
"and they cannot be higher than the original price."
return price
* หรือแม้แต่ตัวอย่างง่ายๆของการนำบูลีนไปใช้:
def true(a, b):
assert (a == b), "False"
return 1
def false(a, b):
assert (a != b), "True"
return 0
ความสำคัญสูงสุดคือการไม่ใช้assert
คำสั่งเพื่อดำเนินการประมวลผลข้อมูลหรือการตรวจสอบความถูกต้องของข้อมูลเนื่องจากคำสั่งนี้สามารถปิดการเริ่มต้น Python ด้วย-O
หรือ-OO
ตั้งค่าสถานะ - หมายถึงค่า 1, 2 และ 0 (เป็นค่าเริ่มต้น) ตามลำดับ - หรือPYTHONOPTIMIZE
ตัวแปรสภาพแวดล้อม .
ค่า 1:
การยืนยัน * ถูกปิดใช้งาน
* ไฟล์ bytecode สร้างขึ้นโดยใช้.pyo
นามสกุลแทน.pyc
;
* sys.flags.optimize
ตั้งไว้ที่ 1 ( True
);
* และ__debug__
ตั้งค่าเป็นFalse
;
ค่า 2:ปิดใช้งานอีกหนึ่งสิ่ง
* เอกสารถูกปิดใช้งาน
ดังนั้นการใช้assert
คำสั่งเพื่อตรวจสอบประเภทของข้อมูลที่คาดว่าจะเป็นอันตรายอย่างยิ่งหมายถึงแม้กระทั่งปัญหาด้านความปลอดภัยบางอย่าง จากนั้นหากคุณต้องการตรวจสอบสิทธิ์บางอย่างฉันขอแนะนำให้คุณraise AuthError
แทน ในฐานะที่เป็นเงื่อนไขที่มีประสิทธิภาพ, assert
มักจะถูกใช้โดยโปรแกรมเมอร์ในไลบรารีหรือโมดูลที่ไม่มีผู้ใช้โต้ตอบโดยตรง
ดังสรุปโดยสรุปในC2 Wiki :
การยืนยันเป็นนิพจน์บูลีนที่จุดเฉพาะในโปรแกรมซึ่งจะเป็นจริงเว้นแต่ว่ามีข้อผิดพลาดในโปรแกรม
คุณสามารถใช้assert
คำสั่งเพื่อบันทึกความเข้าใจของโค้ดที่จุดโปรแกรมเฉพาะ ตัวอย่างเช่นคุณสามารถจัดทำเอกสารสมมติฐานหรือการรับประกันเกี่ยวกับอินพุต (เงื่อนไขเบื้องต้น) สถานะโปรแกรม (ค่าคงที่) หรือเอาต์พุต (โพสต์เงื่อนไข)
หากการยืนยันของคุณล้มเหลวนี่คือการแจ้งเตือนสำหรับคุณ (หรือผู้สืบทอดของคุณ) ว่าความเข้าใจในโปรแกรมของคุณนั้นผิดเมื่อคุณเขียนมันและอาจมีข้อผิดพลาดเกิดขึ้น
สำหรับข้อมูลเพิ่มเติม John Regehr มีโพสต์บล็อกที่ยอดเยี่ยมเกี่ยวกับการใช้การยืนยันซึ่งใช้กับassert
คำสั่งPython เช่นกัน
หากคุณต้องการทราบว่าฟังก์ชั่นที่สงวนไว้ทำอะไรในไพ ธ อนให้พิมพ์ help(enter_keyword)
ตรวจสอบให้แน่ใจว่าคุณกำลังป้อนคำหลักที่สงวนไว้ซึ่งคุณป้อนไว้เป็นสตริง
Python assertนั้นเป็นตัวช่วยในการดีบักซึ่งเงื่อนไขการทดสอบสำหรับการตรวจสอบตัวเองของโค้ดของคุณ Assert ทำให้การดีบักง่ายมากเมื่อรหัสของคุณเข้าสู่กรณีที่เป็นไปไม่ได้ ยืนยันการตรวจสอบกรณีที่เป็นไปไม่ได้
สมมติว่ามีฟังก์ชั่นในการคำนวณราคาของสินค้าหลังหักส่วนลด:
def calculate_discount(price, discount):
discounted_price = price - [discount*price]
assert 0 <= discounted_price <= price
return discounted_price
ที่นี่ลดราคา _ ไม่น้อยกว่า 0 และสูงกว่าราคาจริง ดังนั้นในกรณีที่เงื่อนไขข้างต้นถูกละเมิด assert จะทำให้เกิดข้อผิดพลาดในการยืนยันซึ่งช่วยให้ผู้พัฒนาสามารถระบุได้ว่ามีสิ่งที่เป็นไปไม่ได้เกิดขึ้น
หวังว่าจะช่วย :)
assert
มีประโยชน์ในบริบทการตรวจแก้จุดบกพร่อง แต่ไม่ควรเชื่อถือนอกบริบทการตรวจแก้จุดบกพร่อง
คำอธิบายสั้น ๆ ของฉันคือ:
assert
ยกAssertionError
ถ้าการแสดงออกเป็นเท็จมิฉะนั้นเพียงดำเนินการต่อรหัสและหากมีเครื่องหมายจุลภาคสิ่งที่มันจะเป็นAssertionError: whatever after comma
และรหัสเป็นเช่น:raise AssertionError(whatever after comma)
บทแนะนำที่เกี่ยวข้องเกี่ยวกับเรื่องนี้:
https://www.tutorialspoint.com/python/assertions_in_python.htm
assert
แต่ไม่เมื่อใช้ (หรือไม่ใช้) และassert
; ก็สังเกตว่าassert
จะสามารถปิดการใช้งานถ้า__debug__
มีFalse
จะเป็นประโยชน์
ใน Pycharm ถ้าคุณใช้assert
พร้อมกับisinstance
ประกาศประเภทของวัตถุมันจะช่วยให้คุณเข้าถึงวิธีการและคุณสมบัติของวัตถุแม่ในขณะที่คุณกำลังเข้ารหัสมันจะทำการเติมให้อัตโนมัติโดยอัตโนมัติ
ตัวอย่างเช่นสมมติว่าself.object1.object2
เป็นMyClass
วัตถุ
import MyClasss
def code_it(self):
testObject = self.object1.object2 # at this point, program doesn't know that testObject is a MyClass object yet
assert isinstance(testObject , MyClasss) # now the program knows testObject is a MyClass object
testObject.do_it() # from this point on, PyCharm will be able to auto-complete when you are working on testObject
ตามที่เขียนไว้ในคำตอบอื่น ๆ คำassert
สั่งที่ใช้ในการตรวจสอบสถานะของโปรแกรมที่จุดที่กำหนด
ฉันจะไม่พูดซ้ำเกี่ยวกับข้อความวงเล็บหรือ-O
ตัวเลือกและ__debug__
ค่าคงที่ที่เกี่ยวข้อง ตรวจสอบเอกสารสำหรับข้อมูลมือแรกด้วย ฉันจะมุ่งเน้นไปที่คำถามของคุณ: การใช้งานassert
คืออะไร? แม่นยำยิ่งขึ้นเมื่อไร (และเมื่อไม่) ควรใช้assert
?
assert
งบเป็นประโยชน์ในการแก้ปัญหาโปรแกรม แต่ท้อแท้ในการตรวจสอบผู้ใช้ป้อน ผมใช้กฎต่อไปนี้ของหัวแม่มือ: ยืนยันเก็บในการตรวจสอบนี้ไม่ควรเกิดขึ้นกับสถานการณ์ การป้อนข้อมูลของผู้ใช้อาจไม่ถูกต้องเช่นรหัสผ่านที่สั้นเกินไป แต่นี้ไม่ได้เป็นนี้ไม่ควรเกิดขึ้นกรณี ถ้าเส้นผ่าศูนย์กลางของวงกลมที่ไม่ได้เป็นใหญ่เป็นสองเท่าของรัศมีของคุณอยู่ในนี้ไม่ควรเกิดขึ้นกรณี
สิ่งที่น่าสนใจที่สุดในใจของฉันคือการใช้assert
แรงบันดาลใจจากการ
เขียนโปรแกรมตามสัญญาตามที่อธิบายโดย B. Meyer ใน [การก่อสร้างซอฟต์แวร์เชิงวัตถุ] (
https://www.eiffel.org/doc/eiffel/Object-Oriented_Software_Construction%% 2C_2nd_Edition
) และดำเนินการใน [Eiffel programming language] (
https://en.wikipedia.org/wiki/Eiffel_(programming_language ) คุณไม่สามารถเลียนแบบการเขียนโปรแกรมโดยใช้สัญญาโดยใช้assert
คำสั่ง แต่น่าสนใจที่จะรักษาเจตนา
นี่คือตัวอย่าง ลองนึกภาพคุณต้องเขียนhead
ฟังก์ชั่น (เช่น [ head
function in Haskell] (
http://www.zvon.org/other/haskell/Outputprelude/head_f.html ) ข้อมูลจำเพาะที่คุณได้รับคือ: "ถ้ารายการไม่ว่างให้ส่งคืนรายการแรกของรายการ" ดูการใช้งานต่อไปนี้:
>>> def head1(xs): return xs[0]
และ
>>> def head2(xs):
... if len(xs) > 0:
... return xs[0]
... else:
... return None
(ใช่นี้สามารถเขียนเป็นreturn xs[0] if xs else None
แต่ที่ไม่ได้จุด)
หากรายการไม่ว่างทั้งสองฟังก์ชั่นจะมีผลลัพธ์เหมือนกันและผลลัพธ์นี้ถูกต้อง:
>>> head1([1, 2, 3]) == head2([1, 2, 3]) == 1
True
ดังนั้นการใช้งานทั้งสองอย่าง (ฉันหวัง) ถูกต้อง พวกเขาแตกต่างกันเมื่อคุณพยายามที่จะนำรายการหัวของรายการที่ว่างเปล่า:
>>> head1([])
Traceback (most recent call last):
...
IndexError: list index out of range
แต่:
>>> head2([]) is None
True
อีกครั้งการใช้งานทั้งสองถูกต้องเพราะไม่มีใครควรส่งรายการว่างไปยังฟังก์ชั่นเหล่านี้ (เราออกจากสเปค ) นั่นคือการโทรที่ไม่ถูกต้อง แต่ถ้าคุณโทรเช่นนั้นจะมีอะไรเกิดขึ้น ฟังก์ชันหนึ่งยกข้อยกเว้นอีกฟังก์ชันหนึ่งคืนค่าพิเศษ สิ่งสำคัญที่สุดคือ: เราไม่สามารถพึ่งพาพฤติกรรมนี้ได้ หากxs
ว่างเปล่าสิ่งนี้จะทำงาน:
print(head2(xs))
แต่จะทำให้โปรแกรมขัดข้อง:
print(head1(xs))
เพื่อหลีกเลี่ยงความประหลาดใจฉันอยากรู้ว่าเมื่อฉันผ่านการโต้แย้งที่ไม่คาดคิดไปยังฟังก์ชั่น กล่าวอีกนัยหนึ่ง: ฉันอยากจะรู้ว่าเมื่อพฤติกรรมที่สังเกตได้ไม่น่าเชื่อถือเพราะมันขึ้นอยู่กับการใช้งานไม่ใช่ในสเปค แน่นอนฉันสามารถอ่านข้อกำหนด แต่โปรแกรมเมอร์ไม่ได้อ่านเอกสารอย่างละเอียด
ลองนึกภาพถ้าฉันมีวิธีแทรกข้อมูลจำเพาะลงในรหัสเพื่อให้ได้ผลดังต่อไปนี้: เมื่อฉันละเมิดข้อกำหนดเช่นส่งรายการที่ว่างเปล่าไปhead
ฉันจะได้รับคำเตือน นั่นจะเป็นความช่วยเหลือที่ดีในการเขียนโปรแกรมที่ถูกต้อง (เช่นสอดคล้องกับข้อกำหนด) และนั่นคือสิ่งที่assert
เข้าสู่ฉาก:
>>> def head1(xs):
... assert len(xs) > 0, "The list must not be empty"
... return xs[0]
และ
>>> def head2(xs):
... assert len(xs) > 0, "The list must not be empty"
... if len(xs) > 0:
... return xs[0]
... else:
... return None
ตอนนี้เรามี:
>>> head1([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
และ:
>>> head2([])
Traceback (most recent call last):
...
AssertionError: The list must not be empty
โปรดทราบว่าhead1
พ่นไม่ใช่AssertionError
IndexError
นั่นเป็นสิ่งสำคัญเพราะAssertionError
ไม่ได้ใด ๆผิดพลาด runtime: มันส่งสัญญาณการละเมิดข้อกำหนดที่ ฉันต้องการคำเตือน แต่ฉันได้รับข้อผิดพลาด โชคดีที่ฉันสามารถปิดการใช้งานเช็ค (โดยใช้-O
ตัวเลือก) แต่เป็นความเสี่ยงของฉันเอง ฉันจะทำมันผิดพลาดมีราคาแพงมากและหวังว่าจะดีที่สุด ลองนึกภาพโปรแกรมของฉันฝังอยู่ในยานอวกาศที่เดินทางผ่านหลุมดำ ฉันจะปิดการใช้งานการยืนยันและหวังว่าโปรแกรมจะแข็งแกร่งพอที่จะไม่ผิดพลาดได้นานที่สุด
ตัวอย่างนี้เป็นเพียงเกี่ยวกับปัจจัยพื้นฐานเท่านั้นคุณสามารถใช้assert
เพื่อตรวจสอบ postconditions (ค่าส่งคืนและ / หรือสถานะ) และค่าคงที่ (สถานะของคลาส) โปรดทราบว่าการตรวจสอบ postconditions และ invariants ด้วยassert
อาจยุ่งยาก:
คุณจะไม่มีอะไรซับซ้อนเหมือนไอเฟล แต่คุณสามารถปรับปรุงคุณภาพโดยรวมของโปรแกรมได้
เพื่อสรุปที่assert
คำสั่งเป็นวิธีที่สะดวกในการตรวจสอบนี้ไม่ควรเกิดขึ้นกับสถานการณ์ การละเมิดข้อกำหนด (เช่นส่งรายการว่างไปhead
) เป็นชั้นหนึ่งซึ่งไม่ควรเกิดขึ้นในสถานการณ์ ดังนั้นในขณะที่assert
คำสั่งอาจถูกใช้เพื่อตรวจสอบสถานการณ์ที่ไม่คาดคิดใด ๆ มันเป็นวิธีที่มีสิทธิพิเศษเพื่อให้แน่ใจว่าข้อมูลจำเพาะเป็นจริง เมื่อคุณแทรกassert
คำสั่งลงในรหัสเพื่อแสดงสเปคเราหวังว่าคุณจะได้ปรับปรุงคุณภาพของโปรแกรมเนื่องจากการขัดแย้งที่ไม่ถูกต้องค่าส่งคืนที่ไม่ถูกต้องสถานะที่ไม่ถูกต้องของคลาส ... จะถูกรายงาน
format: assert Expression [, arguments] เมื่อยืนยันการพบคำสั่ง Python จะประเมินการแสดงออกหากคำสั่งนั้นไม่เป็นความจริงข้อยกเว้นจะถูกยกขึ้น (assertionError) หากการยืนยันล้มเหลว Python ใช้ ArgumentExpression เป็นอาร์กิวเมนต์สำหรับ AssertionError ข้อยกเว้น AssertionError สามารถถูกดักจับและจัดการเหมือนกับข้อยกเว้นอื่น ๆ โดยใช้คำสั่ง try-exception แต่หากไม่ได้รับการจัดการพวกเขาจะยุติโปรแกรมและสร้าง traceback ตัวอย่าง:
def KelvinToFahrenheit(Temperature):
assert (Temperature >= 0),"Colder than absolute zero!"
return ((Temperature-273)*1.8)+32
print KelvinToFahrenheit(273)
print int(KelvinToFahrenheit(505.78))
print KelvinToFahrenheit(-5)
เมื่อรันโค้ดข้างต้นมันจะสร้างผลลัพธ์ดังต่อไปนี้:
32.0
451
Traceback (most recent call last):
File "test.py", line 9, in <module>
print KelvinToFahrenheit(-5)
File "test.py", line 4, in KelvinToFahrenheit
assert (Temperature >= 0),"Colder than absolute zero!"
AssertionError: Colder than absolute zero!
def getUser(self, id, Email):
user_key = id and id or Email
assert user_key
สามารถใช้เพื่อให้แน่ใจว่าพารามิเตอร์ถูกส่งผ่านในการเรียกใช้ฟังก์ชัน
if not user_key: raise ValueError()
ตรวจสอบ 2 ย่อหน้าล่าสุดที่นี่: wiki.python.org/moin/UsingAssertionsEffectively
assert
ไม่ควรนำมาใช้สำหรับการตรวจสอบการป้อนข้อมูลเนื่องจากการตรวจสอบจะถูกปล้นว่าเป็น__debug__
False
การใช้การยืนยันเพื่อจุดประสงค์ที่ไม่ใช่การดีบักอาจทำให้คนจับผลลัพธ์ที่AssertionError
ได้ซึ่งทำให้การดีบักยากขึ้นแทนที่จะเป็นน้อย
>>>this_is_very_complex_function_result = 9
>>>c = this_is_very_complex_function_result
>>>test_us = (c < 4)
>>> #first we try without assert
>>>if test_us == True:
print("YES! I am right!")
else:
print("I am Wrong, but the program still RUNS!")
I am Wrong, but the program still RUNS!
>>> #now we try with assert
>>> assert test_us
Traceback (most recent call last):
File "<pyshell#52>", line 1, in <module>
assert test_us
AssertionError
>>>
โดยทั่วไปความหมายคีย์เวิร์ด assert คือถ้าเงื่อนไขไม่เป็นจริงคำสั่ง assertionerror ก็จะดำเนินต่อไปเช่นในไพ ธ อน
รหัส-1
a=5
b=6
assert a==b
เอาท์พุท:
assert a==b
AssertionError
รหัส-2
a=5
b=5
assert a==b
เอาท์พุท:
Process finished with exit code 0
assert
แต่ไม่ตอบเมื่อใช้ (หรือไม่ใช้) assert
และ