การใช้“ ยืนยัน” ใน Python คืออะไร


960

assertผมได้อ่านรหัสที่มาบางส่วนและในหลายสถานที่ที่ฉันได้เห็นการใช้งานของ

มันหมายความว่าอะไรกันแน่? การใช้งานคืออะไร?


คำตอบ:


1082

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

ดูที่นี่สำหรับเอกสารที่เกี่ยวข้อง


92
Nit: การยืนยันเป็นข้อความและไม่ใช่ฟังก์ชั่น และแตกต่างจากการพิมพ์ในหลาม 3 ก็ยังคงคำสั่ง
Bob Stein

2
@Chaine assert หมายถึง "ตรวจสอบให้แน่ใจว่า * สิ่งที่" เป็นจริง "ดังนั้นยืนยัน a == 3 จะทำให้แน่ใจว่า a เท่ากับ 3 หาก a ไม่เท่ากับ 3 (เช่น a == 3 เป็นเท็จ) จากนั้นจะ แจ้งข้อผิดพลาด
Ant

5
ถ้าฉันสามารถใช้if not condition: raise AssertError()มันทำไมฉันต้องใช้ยืนยัน? มีเงื่อนไขใดบ้างที่ยืนยันได้ดีกว่าการเป็นข้อความสั้น ๆif not condition?
alpha_989

6
@ alpha_989 a) สั้นกว่าและอ่านง่ายกว่า b) คุณสามารถปิดการใช้งานข้อความยืนยันเมื่อใช้ล่าม (ไม่ได้ใช้กับคู่มือif) อ่านเอกสารสำหรับข้อมูลเพิ่มเติม :)
slezica

9
โดยสิ้นเชิงไม่สามารถหาได้ว่าคำตอบนี้ได้รับคะแนนโหวตมากขึ้นอย่างไรจริง ๆ แล้วคำตอบอื่น ๆ ก็เช่นกัน คำถามคือ "การใช้" ยืนยัน "ใน Python คืออะไร" ดังนั้นจึงมีการถาม: เมื่อใช้หรือมากกว่า: สถานการณ์การใช้งานของอะไรassertแต่หลังจากอ่านคำตอบทั้งหมดฉันไม่มีอะไรที่ฉันต้องการ!
lnshi

423

ระวังวงเล็บ ดังที่ได้กล่าวไว้ข้างต้นใน 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เป็นบริบทบูลีน


18
ฉันมาที่นี่เพื่อค้นหาข้อมูลที่แน่นอนเกี่ยวกับ parens และข้อความติดตาม ขอบคุณ
superbeck

6
แต่assert (2 + 2 = 5), "Houston we've got a problem"ควรจะตกลงใช่ไหม
SherylHohman

4
@SherylHohman คุณยังสามารถลองเรียกใช้ด้วยตัวคุณเองและดูว่ามันใช้งานได้หรือไม่
DarkCygnus

2
อย่าลืมว่าคนมักจะใช้วงเล็บสำหรับการต่อบรรทัด PEP ที่สอดคล้องกับ PEP 8 นอกจากนี้ยังอย่าลืมว่าสิ่งอันดับ tuples ไม่ได้ถูกกำหนดโดยวงเล็บ แต่โดยการมีอยู่ของเครื่องหมายจุลภาค (tuples ไม่มีส่วนเกี่ยวข้องกับ parens ยกเว้นวัตถุประสงค์ของ ลำดับความสำคัญของผู้ประกอบการ)
cowbert

4
assert (2 + 2 = 5), "Houston we've got a problem"จะไม่ทำงาน ... แต่มันไม่มีส่วนเกี่ยวข้องกับคำสั่งยืนยันซึ่งใช้ได้ เงื่อนไขของคุณจะไม่ทำงานเพราะไม่ใช่เงื่อนไข =หายไปเป็นครั้งที่สอง
n1k31t4

133

ดังที่คำตอบอื่น ๆ ระบุไว้assertนั้นคล้ายกับการโยนข้อยกเว้นหากเงื่อนไขที่กำหนดไม่เป็นความจริง -Oความแตกต่างที่สำคัญคือว่างบยืนยันได้รับการละเว้นถ้าคุณรวบรวมรหัสของคุณมีตัวเลือกในการเพิ่มประสิทธิภาพ เอกสารบอกว่าassert expressionดีขึ้นสามารถอธิบายได้ว่าเป็นเทียบเท่ากับ

if __debug__:
   if not expression: raise AssertionError

สิ่งนี้มีประโยชน์หากคุณต้องการทดสอบรหัสของคุณอย่างละเอียดจากนั้นปล่อยรุ่นที่ปรับปรุงแล้วเมื่อคุณพอใจที่กรณีการยืนยันของคุณล้มเหลว - เมื่อเปิดใช้งานการปรับให้เหมาะสม__debug__ตัวแปรจะกลายเป็นเท็จและเงื่อนไขจะหยุดประเมิน ฟีเจอร์นี้สามารถติดตามคุณได้หากคุณเชื่อมั่นในการยืนยันและไม่ทราบว่าพวกเขาหายตัวไป


นี่หมายความว่าหากตัวแปรบางตัวหรืออินพุตที่ถูกต้อง (ตามสัญญาที่โปรแกรมถูกเขียน) อาจนำไปสู่การทำงานล้มเหลวของโปรแกรมเมื่อผู้ใช้เรียกใช้ (สมมติว่าแฟล็ก -O ถูกใช้เมื่อผู้ใช้รัน โปรแกรม) คุณควรจะใช้if Not Error: raise Exception(“ this is a error”)? ด้วยวิธีนี้โปรแกรมจะยังคงแสดงแหล่งที่มาของข้อผิดพลาดเมื่อผู้ใช้รัน ..
alpha_989

ในทางกลับกันหากคุณคาดหวังว่าโปรแกรมอาจผิดพลาดเนื่องจากตรรกะ / การนำรหัสไปใช้ไม่ถูกต้อง (แต่ไม่ใช่เนื่องจากการป้อนข้อมูลซึ่งเป็นไปตามสัญญาของผู้ใช้โปรแกรม) คุณควรใช้assertคำสั่งหรือไม่ สมมติฐานที่นี่คือเมื่อโปรแกรมถูกปล่อยให้กับผู้ใช้คุณกำลังใช้แฟล็ก -O ดังนั้นสมมติว่าข้อบกพร่องทั้งหมดได้ถูกลบออก ดังนั้นข้อผิดพลาดหรือความผิดพลาดของโปรแกรมเกิดจากการป้อนข้อมูลไปยังโปรแกรมที่ถูกต้องตามสัญญา แต่โปรแกรมไม่สามารถจัดการได้ ดังนั้นควรแจ้งเตือนผู้ใช้เช่นนี้
alpha_989

@ alpha_989 นั่นถูกต้องแล้ว ฉันชอบที่จะคิดว่าการยืนยันเป็นการตรวจสุขภาพที่จะช่วยให้คุณเป็นนักพัฒนาเพื่อให้แน่ใจว่าสิ่งที่คุณคิดว่าเป็นความจริงเป็นจริงในขณะที่คุณพัฒนา
Christopher Shroba

52

เป้าหมายของการยืนยันใน Python คือการแจ้งให้นักพัฒนาทราบถึงข้อผิดพลาดที่ไม่สามารถกู้คืนได้ในโปรแกรม

การยืนยันไม่ได้มีวัตถุประสงค์เพื่อส่งสัญญาณเงื่อนไขข้อผิดพลาดที่คาดไว้เช่น "ไม่พบไฟล์" ซึ่งผู้ใช้สามารถดำเนินการแก้ไขได้ (หรือลองอีกครั้ง)

อีกวิธีในการดูคือการยืนยันว่าเป็นการตรวจสอบภายในด้วยตนเองในรหัสของคุณ พวกเขาทำงานโดยการประกาศเงื่อนไขบางอย่างที่เป็นไปไม่ได้ในรหัสของคุณ หากเงื่อนไขเหล่านี้ไม่ถือหมายความว่ามีข้อผิดพลาดในโปรแกรม

หากโปรแกรมของคุณปราศจากข้อผิดพลาดเงื่อนไขเหล่านี้จะไม่เกิดขึ้น แต่ถ้าหนึ่งของพวกเขาไม่ได้เกิดขึ้นโปรแกรมจะผิดพลาดด้วยข้อผิดพลาดการยืนยันบอกคุณว่าที่“เป็นไปไม่ได้” สภาพถูกเรียก สิ่งนี้ทำให้ง่ายต่อการติดตามและแก้ไขข้อบกพร่องในโปรแกรมของคุณ

นี่เป็นบทสรุปจากการสอนเกี่ยวกับการยืนยันของ Python ที่ฉันเขียน:

ข้อความยืนยันของ Python เป็นเครื่องช่วยในการดีบั๊กไม่ใช่กลไกสำหรับจัดการข้อผิดพลาดขณะทำงาน เป้าหมายของการใช้การยืนยันคือเพื่อให้นักพัฒนาค้นหาสาเหตุที่เป็นไปได้ของข้อผิดพลาดได้เร็วขึ้น ข้อผิดพลาดในการยืนยันไม่ควรถูกยกขึ้นหากมีข้อผิดพลาดในโปรแกรมของคุณ


ขอบคุณสำหรับบทความ มีประโยชน์มากในการทำความเข้าใจassertคำแถลงและเวลาใช้งาน ฉันพยายามทำความเข้าใจกับคำศัพท์หลายคำที่คุณแนะนำไว้ในบทความ
alpha_989

ฉันคิดว่าฉันจะโพสต์ความคิดเห็นที่นี่เพื่อให้ผู้คนจำนวนมากอาจได้รับประโยชน์จากการชี้แจง ขออภัยถ้าคำถามไร้เดียงสาเกินไป
alpha_989

ในบล็อกของคุณที่เชื่อมโยงคุณให้ตัวอย่างที่คุณกล่าวว่า `ยืนยัน 0 <= ราคา <= ผลิตภัณฑ์ ['ราคา'] 'ถูกต้อง แต่ใช้` ยืนยันผู้ใช้ isisadad ()' ต้องมีสิทธิ์ผู้ดูแลระบบเพื่อลบ '`และassert store.product_exists(product_id), 'Unknown product id'ไม่ใช่วิธีปฏิบัติที่ดีเพราะหากปิดการดีบักแล้วuserแม้ว่าจะไม่adminสามารถลบผลิตภัณฑ์ได้ คุณถือว่าassert user.is_admin()เป็นunrecoverableข้อผิดพลาดหรือไม่? นี่คือเหตุผลที่ไม่ได้เป็นself-check?
alpha_989

หากคุณพิจารณาว่า 'user.is_admin () `เป็นอินพุตของผู้ใช้ดังนั้นจึงไม่ควรใช้ในassert statement, ไม่priceสามารถพิจารณาอินพุตของผู้ใช้ได้เช่นกัน? ทำไมคุณพิจารณาassert user.is_admin()เป็นการตรวจสอบข้อมูล แต่ไม่assert price?
alpha_989

1
@ LaryxDecidua Nope คุณสามารถอ่านได้บนเว็บไซต์ของฉัน เพียงกดปุ่ม Escape หรือคลิกที่สัญลักษณ์ "x" หากคุณไม่สนใจจดหมายข่าว หวังว่าสิ่งนี้จะช่วยให้ :-)
dbader

51

คนอื่น ๆ ได้มอบลิงก์ไปยังเอกสารให้คุณแล้ว

คุณสามารถลองสิ่งต่อไปนี้ในเชลล์แบบโต้ตอบ:

>>> assert 5 > 2
>>> assert 2 > 5
Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
builtins.AssertionError:

คำสั่งแรกไม่ทำอะไรเลยในขณะที่คำสั่งที่สองยกข้อยกเว้น นี่คือคำใบ้แรก: การยืนยันมีประโยชน์ในการตรวจสอบเงื่อนไขที่ควรเป็นจริงในตำแหน่งที่กำหนดของโค้ดของคุณ (โดยปกติคือจุดเริ่มต้น (เงื่อนไขเบื้องต้น) และจุดสิ้นสุดของฟังก์ชัน (postconditions)

Asserts นั้นผูกติดอยู่กับการเขียนโปรแกรมโดยสัญญาซึ่งเป็นวิธีปฏิบัติทางวิศวกรรมที่มีประโยชน์

http://en.wikipedia.org/wiki/Design_by_contract


นั่นหมายความว่าเราสามารถตรวจสอบรหัสในสถานการณ์เช่นยืนยัน (2> 5) และเพิ่มข้อผิดพลาดอย่างอื่นต่อไปได้หรือไม่

20
สูญเสียการล้อยืนยันไม่ได้เป็นฟังก์ชั่น
Pillmuncher

2
การสูญเสียคำอุปมาสำคัญกว่าที่คิด ดูด้านล่าง
Evgeni Sergeev

6
ยืนยันจริง ๆ แล้ววันที่กลับมา (นานก่อน "สัญญา") เพื่อทัวริงเมื่อเขาเขียนหนึ่งในเอกสารที่เก่าแก่ที่สุดเกี่ยวกับวิธีโปรแกรมเมอร์สามารถรับมือกับงานที่ค่อนข้างน่ากลัวของการสร้างโปรแกรมที่ถูกต้อง พบว่ากระดาษเหลือสำหรับการออกกำลังกายสำหรับผู้อ่านเนื่องจากโปรแกรมเมอร์ทุกคนสามารถได้รับประโยชน์จากการคุ้นเคยกับงานของเขา :-) turingarchive.org
Ron Burk

17

จากเอกสาร:

Assert statements are a convenient way to insert debugging assertions into a program

คุณสามารถอ่านเพิ่มเติมได้ที่นี่: http://docs.python.org/release/2.5.2/ref/assert.html


ฉันชอบความคิดเห็นนี้เพราะเพียงอธิบายสิ่งที่ชัดเจนมาก คำถามของฉันคือ "ถ้าฉันได้เขียนการทดสอบหน่วยที่เหมาะสมแล้วทำไมฉันต้องมีการยืนยัน" สิ่งนั้นไม่ได้ทำงานในการผลิตอยู่ดี
dtc

17

คำสั่งยืนยันมีสองรูปแบบ

รูปแบบที่เรียบง่ายassert <expression>เทียบเท่ากับ

if __debug__:
    if not <expression>: raise AssertionError

แบบฟอร์มเพิ่มเติมassert <expression1>, <expression2>, เทียบเท่ากับ

if __debug__:
    if not <expression1>: raise AssertionError, <expression2>

16

การยืนยันเป็นวิธีที่เป็นระบบในการตรวจสอบว่าสถานะภายในของโปรแกรมเป็นไปตามที่โปรแกรมเมอร์คาดไว้โดยมีเป้าหมายในการจับข้อบกพร่อง ดูตัวอย่างด้านล่าง

>>> 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!
>>> 

1
นอกจากนี้ยังสามารถใช้การยืนยันในโปรแกรมทดสอบหน่วย stackoverflow.com/questions/1383/what-is-unit-testing
panofish

7

นี่คือตัวอย่างง่ายๆบันทึกสิ่งนี้ในไฟล์ (สมมติว่า 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

6

ถ้าคำสั่งหลังจากยืนยันเป็นจริงแล้วโปรแกรมจะดำเนินการต่อ แต่ถ้าคำสั่งหลังจากยืนยันเป็นเท็จโปรแกรมจะแจ้งข้อผิดพลาด เรียบง่ายเหมือนที่

เช่น:

assert 1>0   #normal execution
assert 0>1   #Traceback (most recent call last):
             #File "<pyshell#11>", line 1, in <module>
             #assert 0>1
             #AssertionError

4

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ในบางโอกาสเมื่อโปรแกรมตรวจสอบเงื่อนไขและส่งคืนค่าที่ควรหยุดโปรแกรมทันทีแทนที่จะใช้วิธีอื่นเพื่อหลีกเลี่ยงข้อผิดพลาด:

1. วงเล็บ

ดังที่คุณอาจสังเกตเห็นว่า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.

2. วัตถุประสงค์ในการแก้ไขปัญหา

หากคุณสงสัยว่าเมื่อใช้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

3. การประมวลผลข้อมูลหรือการตรวจสอบข้อมูล

ความสำคัญสูงสุดคือการไม่ใช้assertคำสั่งเพื่อดำเนินการประมวลผลข้อมูลหรือการตรวจสอบความถูกต้องของข้อมูลเนื่องจากคำสั่งนี้สามารถปิดการเริ่มต้น Python ด้วย-Oหรือ-OOตั้งค่าสถานะ - หมายถึงค่า 1, 2 และ 0 (เป็นค่าเริ่มต้น) ตามลำดับ - หรือPYTHONOPTIMIZEตัวแปรสภาพแวดล้อม .

ค่า 1:

การยืนยัน * ถูกปิดใช้งาน

* ไฟล์ bytecode สร้างขึ้นโดยใช้.pyoนามสกุลแทน.pyc;

* sys.flags.optimizeตั้งไว้ที่ 1 ( True);

* และ__debug__ตั้งค่าเป็นFalse;

ค่า 2:ปิดใช้งานอีกหนึ่งสิ่ง

* เอกสารถูกปิดใช้งาน

ดังนั้นการใช้assertคำสั่งเพื่อตรวจสอบประเภทของข้อมูลที่คาดว่าจะเป็นอันตรายอย่างยิ่งหมายถึงแม้กระทั่งปัญหาด้านความปลอดภัยบางอย่าง จากนั้นหากคุณต้องการตรวจสอบสิทธิ์บางอย่างฉันขอแนะนำให้คุณraise AuthErrorแทน ในฐานะที่เป็นเงื่อนไขที่มีประสิทธิภาพ, assertมักจะถูกใช้โดยโปรแกรมเมอร์ในไลบรารีหรือโมดูลที่ไม่มีผู้ใช้โต้ตอบโดยตรง


3

ดังสรุปโดยสรุปในC2 Wiki :

การยืนยันเป็นนิพจน์บูลีนที่จุดเฉพาะในโปรแกรมซึ่งจะเป็นจริงเว้นแต่ว่ามีข้อผิดพลาดในโปรแกรม

คุณสามารถใช้assertคำสั่งเพื่อบันทึกความเข้าใจของโค้ดที่จุดโปรแกรมเฉพาะ ตัวอย่างเช่นคุณสามารถจัดทำเอกสารสมมติฐานหรือการรับประกันเกี่ยวกับอินพุต (เงื่อนไขเบื้องต้น) สถานะโปรแกรม (ค่าคงที่) หรือเอาต์พุต (โพสต์เงื่อนไข)

หากการยืนยันของคุณล้มเหลวนี่คือการแจ้งเตือนสำหรับคุณ (หรือผู้สืบทอดของคุณ) ว่าความเข้าใจในโปรแกรมของคุณนั้นผิดเมื่อคุณเขียนมันและอาจมีข้อผิดพลาดเกิดขึ้น

สำหรับข้อมูลเพิ่มเติม John Regehr มีโพสต์บล็อกที่ยอดเยี่ยมเกี่ยวกับการใช้การยืนยันซึ่งใช้กับassertคำสั่งPython เช่นกัน


2

หากคุณต้องการทราบว่าฟังก์ชั่นที่สงวนไว้ทำอะไรในไพ ธ อนให้พิมพ์ help(enter_keyword)

ตรวจสอบให้แน่ใจว่าคุณกำลังป้อนคำหลักที่สงวนไว้ซึ่งคุณป้อนไว้เป็นสตริง


2

Python assertนั้นเป็นตัวช่วยในการดีบักซึ่งเงื่อนไขการทดสอบสำหรับการตรวจสอบตัวเองของโค้ดของคุณ Assert ทำให้การดีบักง่ายมากเมื่อรหัสของคุณเข้าสู่กรณีที่เป็นไปไม่ได้ ยืนยันการตรวจสอบกรณีที่เป็นไปไม่ได้

สมมติว่ามีฟังก์ชั่นในการคำนวณราคาของสินค้าหลังหักส่วนลด:

def calculate_discount(price, discount):
    discounted_price = price - [discount*price]
    assert 0 <= discounted_price <= price
    return discounted_price

ที่นี่ลดราคา _ ไม่น้อยกว่า 0 และสูงกว่าราคาจริง ดังนั้นในกรณีที่เงื่อนไขข้างต้นถูกละเมิด assert จะทำให้เกิดข้อผิดพลาดในการยืนยันซึ่งช่วยให้ผู้พัฒนาสามารถระบุได้ว่ามีสิ่งที่เป็นไปไม่ได้เกิดขึ้น

หวังว่าจะช่วย :)


2
assertมีประโยชน์ในบริบทการตรวจแก้จุดบกพร่อง แต่ไม่ควรเชื่อถือนอกบริบทการตรวจแก้จุดบกพร่อง
FluxIX

2

คำอธิบายสั้น ๆ ของฉันคือ:

  • 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จะเป็นประโยชน์
FluxIX

1

ใน 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

0

ตามที่เขียนไว้ในคำตอบอื่น ๆ คำ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ฟังก์ชั่น (เช่น [ headfunction 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อาจยุ่งยาก:

  • สำหรับ postconditions คุณต้องกำหนดค่าส่งคืนให้กับตัวแปรและอาจจะเก็บสถานะ iniial ของวัตถุถ้าคุณกำลังจัดการกับวิธีการ;
  • สำหรับค่าคงที่คุณต้องตรวจสอบสถานะก่อนและหลังการเรียกใช้เมธอด

คุณจะไม่มีอะไรซับซ้อนเหมือนไอเฟล แต่คุณสามารถปรับปรุงคุณภาพโดยรวมของโปรแกรมได้


เพื่อสรุปที่assertคำสั่งเป็นวิธีที่สะดวกในการตรวจสอบนี้ไม่ควรเกิดขึ้นกับสถานการณ์ การละเมิดข้อกำหนด (เช่นส่งรายการว่างไปhead) เป็นชั้นหนึ่งซึ่งไม่ควรเกิดขึ้นในสถานการณ์ ดังนั้นในขณะที่assertคำสั่งอาจถูกใช้เพื่อตรวจสอบสถานการณ์ที่ไม่คาดคิดใด ๆ มันเป็นวิธีที่มีสิทธิพิเศษเพื่อให้แน่ใจว่าข้อมูลจำเพาะเป็นจริง เมื่อคุณแทรกassertคำสั่งลงในรหัสเพื่อแสดงสเปคเราหวังว่าคุณจะได้ปรับปรุงคุณภาพของโปรแกรมเนื่องจากการขัดแย้งที่ไม่ถูกต้องค่าส่งคืนที่ไม่ถูกต้องสถานะที่ไม่ถูกต้องของคลาส ... จะถูกรายงาน


-2

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!    

-2
def getUser(self, id, Email):

    user_key = id and id or Email

    assert user_key

สามารถใช้เพื่อให้แน่ใจว่าพารามิเตอร์ถูกส่งผ่านในการเรียกใช้ฟังก์ชัน


1
สิ่งนี้จะได้ผล แต่จากสิ่งที่ฉันเข้าใจไม่ควรใช้การยืนยันในการตรวจสอบการป้อนข้อมูลของผู้ใช้เนื่องจากสามารถปิดได้ในเวลาทำงาน หากคุณต้องการบังคับใช้หรือตรวจสอบความถูกต้องของอินพุตของผู้ใช้ให้ใช้if not user_key: raise ValueError()ตรวจสอบ 2 ย่อหน้าล่าสุดที่นี่: wiki.python.org/moin/UsingAssertionsEffectively
alpha_989

assertไม่ควรนำมาใช้สำหรับการตรวจสอบการป้อนข้อมูลเนื่องจากการตรวจสอบจะถูกปล้นว่าเป็น__debug__ Falseการใช้การยืนยันเพื่อจุดประสงค์ที่ไม่ใช่การดีบักอาจทำให้คนจับผลลัพธ์ที่AssertionErrorได้ซึ่งทำให้การดีบักยากขึ้นแทนที่จะเป็นน้อย
FluxIX

-4
>>>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
>>> 

-4

โดยทั่วไปความหมายคีย์เวิร์ด 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

2
กรุณาจัดรูปแบบรหัสของคุณอย่างถูกต้อง นอกจากนี้วิธีนี้จะปรับปรุงคำตอบก่อนหน้าได้อย่างไร
c2huc2hu

คำอธิบายของฉันมีปัญหาหรือไม่?
ujjwal_bansal

คำอธิบายของคุณไม่ได้เพิ่มอะไรเลยกับคำตอบที่มีอยู่และไวยากรณ์ที่ไม่ดีทำให้อ่านยาก หากคุณกำลังมองหาคำถามที่จะตอบลองพิจารณาฟีดคำถามใหม่
c2huc2hu

คำตอบที่ให้ไว้จะตอบวิธีใช้assertแต่ไม่ตอบเมื่อใช้ (หรือไม่ใช้) assertและ
FluxIX
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.