python menegaskan dengan dan tanpa tanda kurung

104

Berikut adalah empat pemanggilan sederhana dari assert:

>>> 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")

Perhatikan bahwa yang terakhir tidak menimbulkan kesalahan. Apa perbedaan antara panggilan assert dengan atau tanpa tanda kurung yang menyebabkan perilaku ini? Praktik saya adalah menggunakan tanda kurung, tetapi penjelasan di atas menyarankan agar saya tidak melakukannya.

gaefan
sumber
Terima kasih atas jawaban yang membantu. Perbedaan antara kata kunci dan fungsi bawaan tampaknya tidak kentara. Berikut adalah daftar kata kunci, yang menurut saya, parens harus ditinggalkan: docs.python.org/reference/lexical_analysis.html#keywords
gaefan
2
Satu perbedaan adalah Anda dapat mendefinisikan ulang fungsi bawaan tetapi tidak dapat melakukannya dengan kata kunci (bukan berarti yang pertama adalah ide yang bagus).
gaefan
Ini bukan perbedaan fungsi vs kata kunci, tetapi pemanggilan fungsi vs pernyataan . (misalnya - print digunakan sebagai pernyataan, dan bekerja tanpa tanda kurung).
Tomasz Gandor

Jawaban:

129

Yang terakhir assertakan memberi Anda peringatan ( SyntaxWarning: assertion is always true, perhaps remove parentheses?) jika Anda menjalankannya melalui interpreter lengkap, bukan melalui IDLE. Karena assertmerupakan kata kunci dan bukan fungsi, Anda sebenarnya mengirimkan tupel sebagai argumen pertama dan meninggalkan argumen kedua.

Ingatlah bahwa tupel yang tidak kosong mengevaluasi ke True, dan karena pesan pernyataan bersifat opsional, pada dasarnya Anda telah menelepon assert Truesaat menulis assert(1==2, "hi").

Mark Rushakoff
sumber
10
Alasan tidak terjadi assert (1==2)adalah tanda kurung di sekitar ekspresi tunggal tidak akan membuat tupel secara otomatis; Anda akan mendapatkan perilaku yang sama seperti # 4 jika Anda melakukannya assert (1==2,). Hal yang sama akan terjadi jika Anda melakukannya, print ('foo', 'bar')bukan print 'foo', 'bar'; Anda akan melihat tupel dikeluarkan
Michael Mrozek
Perlu ditekankan lebih lanjut bahwa pernyataan dalam bentuk assert(test, message)mungkin salah, dan tentu saja membingungkan. Tidak ada orang tua!
tcarobruce
19
Jadi, apa cara yang tepat untuk mengindentasi pernyataan pernyataan panjang, wrt PEP8? Sepertinya tidak mungkin.
stantonk
30

Jika Anda meletakkan tanda kurung di sana karena Anda menginginkan pernyataan multi-baris, maka alternatifnya adalah meletakkan garis miring terbalik di akhir baris seperti ini:

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

Cetakan:

AssertionError: "derp should be 8, it is 7

Mengapa python assertini harus berbeda dari yang lainnya:

Saya pikir ideologi pythonic adalah bahwa program harus mengoreksi diri sendiri tanpa harus khawatir tentang bendera khusus untuk mengaktifkan pernyataan. Godaan untuk menonaktifkan asserts terlalu besar, dan karenanya sudah tidak digunakan lagi.

Saya berbagi kekesalan Anda bahwa python assertmemiliki sintaks unik relatif terhadap semua konstruksi pemrograman python lainnya, dan sintaks ini sekali lagi telah berubah dari python2 menjadi python3 dan sekali lagi berubah dari python 3.4 menjadi 3.6. Membuat pernyataan assert tidak kompatibel ke belakang dari versi mana pun ke versi lain.

Ini adalah ketukan di pundak yang assertmerupakan warga kelas 3, itu akan dihapus sepenuhnya di python4, dan tentunya lagi di Python 8.1.

Eric Leschinski
sumber
2
Apakah ada dokumen tentang apa yang harus kita gunakan daripada menegaskan? Tegaskan sepertinya nama yang logis untuk memvalidasi, dan memiliki perilaku yang diinginkan, mis. Menampilkan pesan khusus saat terjadi kesalahan.
AnneTheAgile
18

assert 1==2, "hi"diuraikan assert 1==2, "hi"dengan "hi" sebagai parameter kedua untuk kata kunci. Karenanya mengapa itu benar memberikan kesalahan.

assert(1==2)diuraikan seperti assert (1==2)yang identik dengan assert 1==2, karena parens di sekitar item tunggal tidak membuat tupel kecuali ada tanda koma, mis (1==2,).

assert(1==2, "hi")diuraikan sebagai assert (1==2, "hi"), yang tidak memberikan kesalahan karena tupel (False, "hi")yang tidak kosong bukanlah nilai yang salah, dan tidak ada parameter kedua yang diberikan ke kata kunci.

Anda tidak boleh menggunakan tanda kurung karena assertbukan fungsi dalam Python - ini adalah kata kunci.

Amber
sumber
13

Anda dapat merusak pernyataan assert tanpa \seperti ini:

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

Atau jika Anda memiliki pesan yang lebih panjang:

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'
)
karantan
sumber
1
Ide yang menarik. Saya benci garis miring terbalik untuk kelanjutan, dan ini adalah alternatif untuk membungkus pernyataan dalam fungsi utilitas (yang merupakan solusi saya).
Tomasz Gandor
1

Berikut ini dikutip dari doc python

Pernyataan assert adalah cara mudah untuk memasukkan pernyataan debugging ke dalam program:

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

Bentuk sederhana, ekspresi assert, setara dengan if __debug__: if not expression: raise AssertionError

Bentuk yang diperluas, menegaskan ekspresi1, ekspresi2 , setara dengan if __debug__: if not expression1: raise AssertionError(expression2)

Jadi, saat Anda menggunakan tanda kurung di sini, Anda menggunakan formulir sederhana, dan ekspresi dievaluasi sebagai tupel, yang selalu True saat dicor ke bool

VicX
sumber