python khẳng định có và không có dấu ngoặc đơn


104

Dưới đây là bốn cách gọi đơn giản của khẳng định:

>>> assert 1==2
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError

>>> assert 1==2, "hi"
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError: hi

>>> assert(1==2)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AssertionError

>>> assert(1==2, "hi")

Lưu ý rằng cái cuối cùng không phát sinh lỗi. Sự khác biệt giữa việc gọi khẳng định có hoặc không có dấu ngoặc đơn gây ra hành vi này là gì? Thực hành của tôi là sử dụng dấu ngoặc đơn, nhưng những điều trên gợi ý rằng tôi không nên.


Cảm ơn vì những câu trả lời hữu ích. Sự khác biệt giữa các từ khóa và các chức năng tích hợp có vẻ tinh tế. Dưới đây là danh sách các từ khóa, mà tôi đoán, Parens nên bỏ qua: docs.python.org/reference/lexical_analysis.html#keywords
gaefan

2
Một điểm khác biệt là bạn có thể xác định lại các hàm tích hợp nhưng không thể làm như vậy với các từ khóa (không phải là ý tưởng hay).
gaefan

Nó không phải là sự phân biệt giữa hàm và từ khóa, mà là lệnh gọi hàm so với câu lệnh . (ví dụ - print từng là một câu lệnh và hoạt động không có dấu ngoặc đơn).
Tomasz Gandor

Câu trả lời:


129

Cuối cùng assertsẽ cung cấp cho bạn một cảnh báo ( SyntaxWarning: assertion is always true, perhaps remove parentheses?) nếu bạn chạy nó thông qua một trình thông dịch đầy đủ, không thông qua IDLE. Bởi vì assertlà một từ khóa chứ không phải một hàm, bạn thực sự đang chuyển vào một bộ giá trị làm đối số đầu tiên và bỏ qua đối số thứ hai.

Nhớ lại rằng các bộ giá trị không trống sẽ đánh giá đến Truevà vì thông báo xác nhận là tùy chọn, về cơ bản bạn đã gọi assert Truekhi viết assert(1==2, "hi").


10
Lý do là không xảy ra vì assert (1==2)dấu ngoặc đơn xung quanh một biểu thức sẽ không tự động tạo một bộ giá trị; bạn sẽ nhận được hành vi tương tự như # 4 nếu bạn đã làm assert (1==2,). Điều tương tự sẽ xảy ra nếu bạn làm print ('foo', 'bar')thay vì print 'foo', 'bar'; bạn sẽ thấy các tuple outputted
Michael Mrozek

Cần nhấn mạnh thêm rằng các câu lệnh dạng này assert(test, message)có thể sai và chắc chắn là khó hiểu. Không có parens!
tcarobruce

19
Vì vậy, cách thích hợp để thụt lề một câu lệnh khẳng định dài, wrt PEP8 là gì? Có vẻ như không thể.
stantonk


30

Nếu bạn đặt dấu ngoặc đơn ở đó vì bạn muốn khẳng định nhiều dòng, thì một giải pháp thay thế là đặt dấu gạch chéo ngược ở cuối dòng như sau:

foo = 7
assert foo == 8, \
    "derp should be 8, it is " + str(foo)

Bản in:

AssertionError: "derp should be 8, it is 7

Tại sao con trăn này assertphải khác với mọi thứ khác:

Tôi nghĩ tư tưởng trăn trở là một chương trình nên tự sửa sai mà không cần phải lo lắng về lá cờ đặc biệt để bật xác nhận. Sự cám dỗ để tắt các xác nhận là quá lớn, và do đó nó đang bị phản đối.

Tôi chia sẻ sự khó chịu của bạn rằng python assertcó cú pháp duy nhất so với tất cả các cấu trúc lập trình python khác và cú pháp này đã một lần nữa thay đổi từ python2 thành python3 và một lần nữa được thay đổi từ python 3.4 thành 3.6. Đưa ra các tuyên bố khẳng định không tương thích ngược từ bất kỳ phiên bản nào sang bất kỳ phiên bản nào khác.

Đó là một cú chạm vào vai assertlà công dân hạng 3, nó sẽ bị xóa hoàn toàn trong python4 và chắc chắn một lần nữa trong Python 8.1.


2
Có tài liệu về những gì chúng ta nên sử dụng thay vì khẳng định không? Assert có vẻ giống như một tên hợp lý để xác thực và nó có hành vi mong muốn, ví dụ: hiển thị một thông báo đặc biệt khi có lỗi.
AnneTheAgile

18

assert 1==2, "hi"được phân tích cú pháp như assert 1==2, "hi"với "hi" làm tham số thứ hai cho từ khóa. Do đó, tại sao nó lại cho một lỗi.

assert(1==2)được phân tích cú pháp assert (1==2)giống với assert 1==2, bởi vì các parens xung quanh một mục đơn lẻ không tạo ra một bộ giá trị trừ khi có một dấu phẩy ở cuối ví dụ (1==2,).

assert(1==2, "hi")được phân tích cú pháp thành assert (1==2, "hi"), điều này không gây ra lỗi vì bộ (False, "hi")giá trị không trống không phải là giá trị sai và không có tham số thứ hai được cung cấp cho từ khóa.

Bạn không nên sử dụng dấu ngoặc đơn vì assertkhông phải là một hàm trong Python - nó là một từ khóa.


13

Bạn có thể phá vỡ câu lệnh khẳng định mà không cần \như sau:

foo = 7
assert foo == 8, (
    'derp should be 8, it is ' + str(foo))

Hoặc nếu bạn còn tin nhắn dài hơn:

foo = 7
assert foo == 8, (
    'Lorem Ipsum is simply dummy text of the printing and typesetting '
    'industry. Lorem Ipsum has been the industry\'s standard dummy text '
    'ever since the 1500s'
)

1
Ý tưởng thú vị. Tôi ghét dấu gạch chéo ngược cho sự tiếp tục và đây là một giải pháp thay thế cho việc gói khẳng định trong một hàm tiện ích (đó là giải pháp của tôi).
Tomasz Gandor

1

Sau đây là trích dẫn từ tài liệu python

Câu lệnh Assert là một cách thuận tiện để chèn các xác nhận gỡ lỗi vào chương trình:

assert_stmt ::= "assert" expression ["," expression]

Dạng đơn giản, biểu thức khẳng định, tương đương với if __debug__: if not expression: raise AssertionError

Dạng mở rộng, khẳng định biểu thức1, biểu thức2 , tương đương với if __debug__: if not expression1: raise AssertionError(expression2)

Vì vậy, khi bạn đang sử dụng dấu ngoặc đơn ở đây, bạn đang sử dụng biểu mẫu đơn giản và biểu thức được đánh giá là một bộ giá trị, luôn luôn Đúng khi được chuyển thành bool

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.