Praktik terbaik untuk Python menegaskan

483
  1. Apakah ada masalah kinerja atau pemeliharaan kode dengan penggunaan assertsebagai bagian dari kode standar alih-alih menggunakannya hanya untuk keperluan debugging?

    Adalah

    assert x >= 0, 'x is less than zero'

    lebih baik atau lebih buruk daripada

    if x < 0:
        raise Exception, 'x is less than zero'
  2. Juga, apakah ada cara untuk menetapkan aturan bisnis seperti if x < 0 raise erroritu selalu diperiksa tanpa try/except/finallyjadi, jika kapan saja seluruh kode xkurang dari 0 kesalahan dinaikkan, seperti jika Anda menetapkan assert x < 0pada awal fungsi, di mana saja dalam fungsi di mana xmenjadi kurang dari 0 pengecualian dimunculkan?

meade
sumber
29
Parameter python -O dan -OO akan menghapus pernyataan Anda. Itu harus mengarahkan pemikiran Anda tentang apa manfaatnya.
Peter Lada
4
Tautan Thomasz Zielinski rusak, sekarang: mail.python.org/pipermail/python-list/2013-November/660568.html . Saya cukup yakin pipermail memiliki fungsi ID yang tidak stabil, saya menemukan tautan lain dari dalam pipermail yang sama menunjuk ke url yang sama dengan maksud yang sama.
quodlibetor
3
Dalam kasus mail.python.org/pipermail/python-list/2013-November/660568.html bergerak lagi, ini diarsipkan di archive.is/5GfiG . Judul posting adalah "Kapan harus menggunakan menegaskan" dan merupakan posting yang sangat baik (artikel benar-benar) tentang praktik terbaik untuk Python assert.
klak

Jawaban:

144

Untuk dapat secara otomatis melempar kesalahan ketika x menjadi kurang dari nol di seluruh fungsi. Anda dapat menggunakan deskriptor kelas . Berikut ini sebuah contoh:

class LessThanZeroException(Exception):
    pass

class variable(object):
    def __init__(self, value=0):
        self.__x = value

    def __set__(self, obj, value):
        if value < 0:
            raise LessThanZeroException('x is less than zero')

        self.__x  = value

    def __get__(self, obj, objType):
        return self.__x

class MyClass(object):
    x = variable()

>>> m = MyClass()
>>> m.x = 10
>>> m.x -= 20
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "my.py", line 7, in __set__
    raise LessThanZeroException('x is less than zero')
LessThanZeroException: x is less than zero
Nadia Alramli
sumber
10
Meskipun properti diimplementasikan sebagai deskriptor, saya tidak akan menyebut ini sebagai contoh menggunakannya. Ini lebih merupakan contoh sifat dalam dan dari diri mereka sendiri: docs.python.org/library/functions.html#property
Jason Baker
3
Properti harus digunakan dalam MyClass saat mengatur x. Solusi ini terlalu umum.
113
Jawaban yang cukup bagus, seperti itu, tetapi tidak ada hubungannya dengan pertanyaan ... Tidak bisakah kita menandai jawaban Deestan atau John Mee sebagai respons yang valid?
Vajk Hermecz
4
Tampaknya ini tidak menjawab judul pertanyaan. Juga, ini adalah alternatif yang buruk untuk fitur properti kelas Python.
Kiamat101
10
@ VajkHermecz: Sebenarnya, jika Anda membaca ulang pertanyaannya, ini adalah dua pertanyaan sekaligus. Orang yang hanya melihat judulnya hanya terbiasa dengan pertanyaan pertama, yang tidak dijawab oleh jawaban ini. Jawaban ini sebenarnya berisi jawaban untuk pertanyaan kedua.
ArtOfWarfare
742

Pernyataan harus digunakan untuk menguji kondisi yang seharusnya tidak pernah terjadi . Tujuannya adalah untuk crash awal dalam kasus program yang korup.

Pengecualian harus digunakan untuk kesalahan yang bisa terjadi, dan Anda hampir selalu harus membuat kelas Pengecualian Anda sendiri .


Misalnya, jika Anda menulis fungsi untuk dibaca dari file konfigurasi menjadi a dict, pemformatan yang tidak benar dalam file tersebut akan menimbulkan a ConfigurationSyntaxError, sementara Anda dapat melakukannya assertAnda tidak akan kembali None.


Dalam contoh Anda, jika x nilai ditetapkan melalui antarmuka pengguna atau dari sumber eksternal, pengecualian adalah yang terbaik.

Jika xhanya diatur oleh kode Anda sendiri dalam program yang sama, lanjutkan dengan pernyataan.

Deestan
sumber
126
Ini adalah cara yang tepat untuk menggunakan pernyataan . Mereka seharusnya tidak digunakan untuk mengontrol aliran program.
Thane Brimhall
41
1 untuk paragraf terakhir - meskipun Anda harus secara eksplisit menyebutkan bahwa assertberisi implisit if __debug__dan dapat dioptimalkan pergi - sebagai jawaban John Mee negara
Tobias Kienzler
3
Membaca ulang jawaban Anda, saya pikir Anda mungkin tidak bermaksud mengatakan bahwa kondisi yang seharusnya tidak pernah dimaksudkan sebagai aturan, tetapi tujuannya adalah untuk crash lebih awal dalam kasus keadaan program yang korup yang biasanya bertepatan dengan kondisi yang tidak Anda harapkan. untuk pernah terjadi .
Bentley4
10
menegaskan hanya harus digunakan untuk menangkap masalah tanpa pemulihan yang diketahui; kode hampir selalu bug (bukan input buruk). ketika pernyataan dipicu, itu harus berarti bahwa program dalam keadaan yang mungkin berbahaya untuk melanjutkan, karena mungkin mulai berbicara ke jaringan atau menulis ke disk. kode robust bergerak 'secara atomis' dari keadaan valid ke keadaan valid dalam menghadapi input yang buruk (atau berbahaya). tingkat teratas dari setiap utas harus memiliki penghalang kesalahan. hambatan kesalahan yang mengkonsumsi input dari dunia luar umumnya gagal hanya untuk satu iterasi dari penghalang (saat / coba), rollback / kesalahan masuk.
Rob
10
"Pernyataan harus digunakan untuk menguji kondisi yang seharusnya tidak pernah terjadi." Iya. Dan arti dari "seharusnya" yang kedua adalah: Jika ini terjadi, kode program salah.
Lutz Prechelt
362

Pernyataan "menegaskan" dihapus ketika kompilasi dioptimalkan . Jadi, ya, ada perbedaan kinerja dan fungsional.

Pembuat kode saat ini tidak memancarkan kode untuk pernyataan tegas ketika optimasi diminta pada waktu kompilasi. - Python 2 Documents Python 3 Documents

Jika Anda menggunakan assert untuk mengimplementasikan fungsionalitas aplikasi, kemudian mengoptimalkan penyebaran ke produksi, Anda akan terganggu oleh cacat "but-it-works-in-dev".

Lihat PYTHONOPTIMIZE dan -O -OO

John Mee
sumber
26
Wow! Catatan super penting itu! Saya telah berencana menggunakan pernyataan untuk memeriksa beberapa hal yang seharusnya tidak pernah gagal, yang kegagalannya akan menunjukkan bahwa seseorang sangat hati-hati memanipulasi data saya yang mereka kirimkan dalam upaya untuk mendapatkan akses ke data yang seharusnya tidak dapat mereka akses. Itu tidak akan berhasil, tetapi saya ingin segera menutup usaha mereka dengan tegas, sehingga dengan mengoptimalkan produksi akan mengalahkan tujuan. Saya kira saya akan hanya raisesebagai Exceptiongantinya. Oh - Saya baru saja menemukan nama yang tepat SuspiciousOperation Exceptiondengan subclass di Django! Sempurna!
ArtOfWarfare
Omong-omong @ArtOfWarfare jika Anda menjalankan banditkode Anda, itu akan memperingatkan Anda tentang hal ini.
Nagev
132

Empat tujuan dari assert

Asumsikan Anda bekerja pada 200.000 baris kode dengan empat rekan kerja Alice, Bernd, Carl, dan Daphne. Mereka memanggil kode Anda, Anda memanggil kode mereka.

Kemudian assertmemiliki empat peran :

  1. Beri tahu Alice, Bernd, Carl, dan Daphne apa yang diharapkan kode Anda.
    Asumsikan Anda memiliki metode yang memproses daftar tupel dan logika program bisa pecah jika tupel itu tidak berubah:

    def mymethod(listOfTuples):
        assert(all(type(tp)==tuple for tp in listOfTuples))

    Ini lebih dapat dipercaya daripada informasi yang setara dalam dokumentasi dan jauh lebih mudah untuk dipelihara.

  2. Beri tahu komputer apa yang diharapkan kode Anda.
    assertmemberlakukan perilaku yang tepat dari penelepon kode Anda. Jika kode Anda menyebut kode Alices dan Bernd menyebut kode Anda, maka tanpa itu assert, jika program mogok dalam kode Alices, Bernd mungkin menganggap itu salah Alice, Alice menyelidiki dan mungkin menganggap itu salah Anda, Anda menyelidiki dan memberi tahu Bernd bahwa itu sebenarnya nya. Banyak pekerjaan hilang.
    Dengan penegasan, siapa pun yang mendapat telepon salah, mereka akan dengan cepat dapat melihat bahwa itu adalah kesalahan mereka, bukan milik Anda. Alice, Bernd, dan kalian semua mendapat manfaat. Menghemat banyak waktu.

  3. Beri tahu pembaca kode Anda (termasuk diri Anda sendiri) apa yang telah dicapai kode Anda di beberapa titik.
    Anggaplah Anda memiliki daftar entri dan masing-masingnya dapat bersih (yang baik) atau dapat berupa smorsh, trale, gullup, atau berkelap-kelip (yang semuanya tidak dapat diterima). Jika itu smorsh, itu harus tidak dipilah; jika itu basi, itu harus baludo; jika itu gullup, itu harus ditelusuri (dan kemudian mungkin berjalan juga); jika berbinar-binar itu harus berbinar lagi kecuali pada hari Kamis. Anda mendapat ide: Ini hal yang rumit. Tetapi hasil akhirnya adalah (atau seharusnya) bahwa semua entri bersih. Right Thing (TM) yang harus dilakukan adalah merangkum efek dari loop pembersihan Anda sebagai

    assert(all(entry.isClean() for entry in mylist))

    Pernyataan ini menghemat sakit kepala bagi semua orang yang mencoba memahami apa sebenarnya yang dicapai lingkaran luar biasa itu. Dan yang paling sering dari orang-orang ini kemungkinan adalah diri Anda sendiri.

  4. Beri tahu komputer apa yang telah dicapai kode Anda di beberapa titik.
    Jika Anda pernah lupa untuk mempercepat entri yang membutuhkannya setelah berlari, itu assertakan menghemat hari Anda dan menghindari bahwa kode Anda rusak Daphne jauh nanti.

Dalam pikiran saya, assertdua tujuan dokumentasi (1 dan 3) dan perlindungan (2 dan 4) sama-sama berharga.
Memberitahu orang-orang bahkan mungkin lebih berharga daripada memberi informasi kepada komputer karena hal itu dapat mencegah kesalahan yang assertingin ditangkap (dalam kasus 1) dan banyak kesalahan selanjutnya dalam kasus apa pun.

Lutz Prechelt
sumber
34
5. menegaskan isinstance () membantu PyCharm (python IDE) untuk mengetahui jenis variabel, itu digunakan untuk autocomplete.
Cjkjvfnby
1
Menegaskan asumsi kode dokumen diri untuk apa yang benar pada waktu eksekusi saat ini. Ini adalah komentar asumsi, yang diperiksa.
pyj
9
Mengenai 2 dan 4: Anda harus sangat berhati-hati agar pernyataan Anda tidak terlalu ketat. Jika tidak, tegaskan sendiri mungkin satu-satunya hal yang membuat program Anda digunakan dalam pengaturan yang lebih umum. Terutama jenis menegaskan bertentangan dengan bebek-mengetik python.
zwirbeltier
9
@Cjkjvfnby Berhati-hatilah dengan terlalu sering menggunakan isinstance () seperti yang dijelaskan dalam entri blog ini: " isinstance () dianggap berbahaya ". Anda sekarang dapat menggunakan docstring untuk menentukan tipe dalam Pycharm.
binarysubstrate
2
Menggunakan pernyataan dalam satu cara untuk memastikan kontrak. Info lebih lanjut tentang Desain oleh Kontrak en.wikipedia.org/wiki/Design_by_contract
Leszek Zarna
22

Selain jawaban lain, menegaskan diri mereka melemparkan pengecualian, tetapi hanya AssertionErrors. Dari sudut pandang utilitarian, pernyataan tidak cocok ketika Anda membutuhkan kendali butir halus atas pengecualian yang Anda tangkap.

outis
sumber
3
Baik. Tampaknya konyol untuk menangkap pengecualian kesalahan pernyataan dalam penelepon.
Raffi Khatchadourian
Poin yang sangat bagus. Nuansa yang dapat dengan mudah diabaikan ketika hanya melihat pertanyaan asli dari tingkat makro. Bahkan jika bukan karena masalah dengan pernyataan yang dibatalkan saat mengoptimalkan, kehilangan detail spesifik tentang jenis kesalahan apa yang terjadi akan membuat debugging jauh lebih menantang. Ceria, outis!
cfwschmidt
Jawaban Anda dapat dibaca seolah-olah Anda ingin menangkapnya AssertionErrors, ketika Anda setuju dengan itu yang berbutir kasar. Pada kenyataannya, Anda seharusnya tidak menangkap mereka.
Tomasz Gandor
19

Satu-satunya hal yang benar-benar salah dengan pendekatan ini adalah sulit untuk membuat pengecualian yang sangat deskriptif menggunakan pernyataan tegas. Jika Anda mencari sintaks yang lebih sederhana, ingat Anda juga dapat melakukan sesuatu seperti ini:

class XLessThanZeroException(Exception):
    pass

def CheckX(x):
    if x < 0:
        raise XLessThanZeroException()

def foo(x):
    CheckX(x)
    #do stuff here

Masalah lain adalah bahwa menggunakan menegaskan untuk memeriksa kondisi normal adalah bahwa itu membuatnya sulit untuk menonaktifkan menegaskan debugging menggunakan flag -O.

Jason Baker
sumber
24
Anda dapat menambahkan pesan kesalahan ke pernyataan. Ini adalah parameter kedua. Itu akan membuatnya deskriptif.
Raffi Khatchadourian
10

Kata bahasa Inggris menegaskan di sini digunakan dalam arti bersumpah , menegaskan , mengakui . Itu tidak berarti "centang" atau "harus" . Ini berarti bahwa Anda sebagai pembuat kode membuat pernyataan tersumpah di sini:

# I solemnly swear that here I will tell the truth, the whole truth, 
# and nothing but the truth, under pains and penalties of perjury, so help me FSM
assert answer == 42

Jika kodenya benar, kecuali gangguan acara tunggal , kegagalan perangkat keras dan semacamnya, tidak ada pernyataan yang akan gagal . Itulah sebabnya perilaku program kepada pengguna akhir tidak boleh terpengaruh. Terutama, sebuah pernyataan tidak dapat gagal bahkan di bawah kondisi program yang luar biasa . Itu tidak pernah terjadi. Jika itu terjadi, programmer harus di-zapping untuk itu.

Antti Haapala
sumber
8

Seperti yang telah dikatakan sebelumnya, pernyataan harus digunakan ketika kode Anda TIDAK HARUS mencapai titik, yang berarti ada bug di sana. Mungkin alasan paling berguna yang bisa saya lihat untuk menggunakan pernyataan adalah invarian / pra / postkondisi. Ini adalah sesuatu yang harus benar pada awal atau akhir setiap iterasi dari suatu loop atau fungsi.

Misalnya, fungsi rekursif (2 fungsi terpisah sehingga 1 menangani input buruk dan yang lainnya menangani kode buruk, menyebabkan sulit dibedakan dengan rekursi). Ini akan memperjelas jika saya lupa menulis pernyataan if, apa yang salah.

def SumToN(n):
    if n <= 0:
        raise ValueError, "N must be greater than or equal to 0"
    else:
        return RecursiveSum(n)

def RecursiveSum(n):
    #precondition: n >= 0
    assert(n >= 0)
    if n == 0:
        return 0
    return RecursiveSum(n - 1) + n
    #postcondition: returned sum of 1 to n

Invarian loop ini sering dapat diwakili dengan pernyataan.

matts1
sumber
2
Ini paling baik dilakukan dengan dekorator (@prondondition dan @postcondition)
Caridorc
@Caridorc apa manfaat nyata dari itu?
Chiel ten Brinke
@ChieltenBrinke mendokumentasikan sendiri kode, alih-alih #precondition: n >= 0 dan menegaskan, dia bisa menulis@precondition(lambda n: n >= 0)
Caridorc
@Caridorc Apakah itu dekorator bawaan? Dan bagaimana cara menghasilkan dokumentasi dari itu?
Chiel ten Brinke
@ChieltenBrinke bukan bawaan tetapi mudah diimplementasikan stackoverflow.com/questions/12151182/… . Untuk dokumentasi cukup tambal __doc__atribut dengan memberikan string tambahan
Caridorc
4

Apakah ada masalah kinerja?

  • Harap ingat untuk "membuatnya bekerja terlebih dahulu sebelum Anda membuatnya bekerja cepat" .
    Sangat sedikit persen dari setiap program biasanya relevan dengan kecepatannya. Anda selalu dapat mengusir atau menyederhanakan assertjika terbukti menjadi masalah kinerja - dan kebanyakan dari mereka tidak akan pernah melakukannya.

  • Bersikap pragmatis :
    Asumsikan Anda memiliki metode yang memproses daftar tupel yang tidak kosong dan logika program akan pecah jika tupel tersebut tidak dapat diubah. Anda harus menulis:

    def mymethod(listOfTuples):
        assert(all(type(tp)==tuple for tp in listOfTuples))

    Ini mungkin baik jika daftar Anda cenderung panjang sepuluh entri, tetapi bisa menjadi masalah jika mereka memiliki sejuta entri. Tetapi alih-alih membuang cek yang berharga ini, Anda cukup menurunkannya

    def mymethod(listOfTuples):
        assert(type(listOfTuples[0])==tuple)  # in fact _all_ must be tuples!

    yang murah tetapi kemungkinan akan menangkap sebagian besar kesalahan program yang sebenarnya .

Lutz Prechelt
sumber
2
Seharusnya assert(len(listOfTuples)==0 or type(listOfTyples[0])==tuple).
Osa
Tidak, seharusnya tidak. Itu akan menjadi tes yang jauh lebih lemah, karena tidak lagi memeriksa properti 'non-kosong', yang dinyatakan cek kedua. (Yang pertama tidak, meskipun seharusnya.)
Lutz Prechelt
1
Penegasan kedua tidak secara eksplisit memeriksa properti tidak kosong; ini lebih merupakan efek samping. Jika itu untuk menimbulkan pengecualian karena daftar kosong, orang yang bekerja dengan kode (orang lain atau penulis, setahun setelah menulisnya) akan menatapnya, mencoba mencari tahu apakah pernyataan itu benar-benar dimaksudkan untuk menangkap situasi daftar kosong, atau jika itu kesalahan dalam pernyataan itu sendiri. Selain itu, saya tidak melihat bagaimana tidak memeriksa case kosong "jauh lebih lemah", sedangkan hanya memeriksa elemen pertama adalah "97% benar".
Osa
3

Baiklah, ini adalah pertanyaan terbuka, dan saya memiliki dua aspek yang ingin saya sentuh: kapan menambahkan pernyataan dan bagaimana menulis pesan kesalahan.

Tujuan

Untuk menjelaskannya kepada pemula - pernyataan adalah pernyataan yang dapat menimbulkan kesalahan, tetapi Anda tidak akan menangkapnya. Dan mereka biasanya tidak harus dibangkitkan, tetapi dalam kehidupan nyata terkadang mereka memang dibesarkan. Dan ini adalah situasi serius, di mana kode tidak dapat dipulihkan dari, apa yang kita sebut 'kesalahan fatal'.

Selanjutnya, ini untuk 'tujuan debugging', yang, meskipun benar, terdengar sangat meremehkan. Saya suka formulasi 'menyatakan invarian, yang tidak boleh dilanggar' lebih baik, meskipun bekerja secara berbeda pada pemula yang berbeda ... Beberapa 'hanya mengerti', dan yang lain tidak menemukan gunanya, atau mengganti pengecualian normal, atau bahkan mengendalikan aliran dengannya.

Gaya

Dalam Python, assertadalah pernyataan, bukan fungsi! (ingat assert(False, 'is true')tidak akan naik. Tapi, memiliki itu keluar dari jalan:

Kapan, dan bagaimana, menulis 'pesan kesalahan' opsional?

Ini berlaku untuk kerangka pengujian unit, yang sering memiliki banyak metode khusus untuk melakukan asersi ( assertTrue(condition), assertFalse(condition), assertEqual(actual, expected)dll.). Mereka sering juga menyediakan cara untuk mengomentari pernyataan tersebut.

Dalam kode dibuang Anda bisa melakukannya tanpa pesan kesalahan.

Dalam beberapa kasus, tidak ada yang ditambahkan ke pernyataan:

def dump (sesuatu): nyatakan isinstance (sesuatu, Dumpable) # ...

Namun terlepas dari itu, pesan berguna untuk komunikasi dengan programmer lain (yang kadang-kadang pengguna interaktif kode Anda, misalnya dalam Ipython / Jupyter dll.).

Beri mereka informasi, bukan hanya membocorkan detail implementasi internal.

dari pada:

assert meaningless_identifier <= MAGIC_NUMBER_XXX, 'meaningless_identifier is greater than MAGIC_NUMBER_XXX!!!'

menulis:

assert meaningless_identifier > MAGIC_NUMBER_XXX, 'reactor temperature above critical threshold'

atau bahkan mungkin:

assert meaningless_identifier > MAGIC_NUMBER_XXX, f'reactor temperature({meaningless_identifier }) above critical threshold ({MAGIC_NUMBER_XXX})'

Saya tahu, saya tahu - ini bukan kasus untuk pernyataan statis, tetapi saya ingin menunjukkan nilai informasi dari pesan tersebut.

Pesan negatif atau positif?

Ini mungkin kontroversial, tetapi saya sakit membaca hal-hal seperti:

assert a == b, 'a is not equal to b'
  • ini adalah dua hal yang saling bertentangan yang ditulis di sebelah satu sama lain. Jadi setiap kali saya memiliki pengaruh pada basis kode, saya mendorong untuk menentukan apa yang kita inginkan, dengan menggunakan kata kerja tambahan seperti 'harus' dan 'harus', dan tidak mengatakan apa yang tidak kita inginkan.

    menyatakan a == b, 'a harus sama dengan b'

Kemudian, mendapatkan AssertionError: a must be equal to bjuga dapat dibaca, dan pernyataan itu terlihat logis dalam kode. Juga, Anda bisa mendapatkan sesuatu darinya tanpa membaca traceback (yang kadang-kadang bahkan tidak tersedia).

Tomasz Gandor
sumber
1

Baik penggunaan assertmaupun peningkatan pengecualian adalah tentang komunikasi.

  • Penegasan adalah pernyataan tentang kebenaran kode yang ditujukan pada pengembang : Penegasan dalam kode memberi informasi kepada pembaca tentang kode yang harus dipenuhi agar kode tersebut benar. Pernyataan yang gagal saat dijalankan menginformasikan pengembang bahwa ada cacat dalam kode yang perlu diperbaiki.

  • Pengecualian adalah indikasi tentang situasi non-tipikal yang dapat terjadi pada saat run-time tetapi tidak dapat diselesaikan dengan kode yang ada, yang ditujukan pada kode panggilan yang akan ditangani di sana. Munculnya pengecualian tidak menunjukkan bahwa ada bug dalam kode.

Praktek terbaik

Oleh karena itu, jika Anda menganggap terjadinya situasi tertentu pada saat run-time sebagai bug yang ingin Anda beri tahu pengembang tentang ("Hai pengembang, kondisi ini menunjukkan bahwa ada bug di suatu tempat, perbaiki kodenya.") Lalu pergi untuk pernyataan. Jika pernyataan memeriksa argumen input dari kode Anda, Anda biasanya harus menambahkan ke dokumentasi bahwa kode Anda memiliki "perilaku tidak terdefinisi" ketika argumen input melanggar kondisi itu.

Jika alih-alih kejadian dari situasi yang sama itu bukan indikasi bug di mata Anda, tetapi sebaliknya (mungkin jarang tetapi) situasi yang mungkin Anda pikir harus ditangani oleh kode klien, ajukan pengecualian. Situasi ketika pengecualian yang diajukan harus menjadi bagian dari dokumentasi kode masing-masing.

Apakah ada masalah kinerja [...] dengan menggunakan assert

Evaluasi pernyataan membutuhkan waktu. Mereka dapat dihilangkan pada waktu kompilasi. Ini memiliki beberapa konsekuensi, namun lihat di bawah.

Apakah ada masalah pemeliharaan kode [...] dengan penggunaan assert

Biasanya pernyataan meningkatkan rawatan kode, karena mereka meningkatkan keterbacaan dengan membuat asumsi eksplisit dan selama waktu berjalan secara teratur memverifikasi asumsi ini. Ini juga akan membantu menangkap regresi. Namun ada satu masalah yang perlu diingat: Ekspresi yang digunakan dalam asersi tidak boleh memiliki efek samping. Seperti disebutkan di atas, pernyataan dapat dihilangkan pada waktu kompilasi - yang berarti bahwa juga efek samping potensial akan hilang. Ini dapat - tanpa sengaja - mengubah perilaku kode.

Dirk Herrmann
sumber
1

Assert adalah untuk memeriksa -
1. kondisi yang valid,
2. pernyataan yang valid,
3. true logic;
kode sumber. Alih-alih gagal seluruh proyek itu memberikan alarm bahwa ada sesuatu yang tidak sesuai dalam file sumber Anda.

Dalam contoh 1, karena variabel 'str' bukan nol. Jadi tidak ada pernyataan atau pengecualian yang diajukan.

Contoh 1:

#!/usr/bin/python

str = 'hello Python!'
strNull = 'string is Null'

if __debug__:
    if not str: raise AssertionError(strNull)
print str

if __debug__:
    print 'FileName '.ljust(30,'.'),(__name__)
    print 'FilePath '.ljust(30,'.'),(__file__)


------------------------------------------------------

Output:
hello Python!
FileName ..................... hello
FilePath ..................... C:/Python\hello.py

Dalam contoh 2, var 'str' adalah nol. Jadi kami menyelamatkan pengguna dari melanjutkan program yang salah dengan pernyataan tegas .

Contoh 2:

#!/usr/bin/python

str = ''
strNull = 'NULL String'

if __debug__:
    if not str: raise AssertionError(strNull)
print str

if __debug__:
    print 'FileName '.ljust(30,'.'),(__name__)
    print 'FilePath '.ljust(30,'.'),(__file__)


------------------------------------------------------

Output:
AssertionError: NULL String

Saat kita tidak ingin men-debug dan menyadari masalah pernyataan dalam kode sumber. Nonaktifkan bendera optimisasi

python -O assertStatement.py
tidak ada yang akan dicetak

akD
sumber
0

Dalam IDE seperti PTVS, PyCharm, assert isinstance()pernyataan Wing dapat digunakan untuk mengaktifkan penyelesaian kode untuk beberapa objek yang tidak jelas.

denfromufa
sumber
Ini tampaknya mendahului penggunaan anotasi jenis atau typing.cast.
Acumenus
-1

Untuk apa nilainya, jika Anda berurusan dengan kode yang mengandalkan assertberfungsi dengan benar, maka menambahkan kode berikut akan memastikan bahwa pernyataan diaktifkan:

try:
    assert False
    raise Exception('Python assertions are not working. This tool relies on Python assertions to do its job. Possible causes are running with the "-O" flag or running a precompiled (".pyo" or ".pyc") module.')
except AssertionError:
    pass
Emilio M Bumachar
sumber
2
Ini tidak menjawab pertanyaan OP yaitu tentang praktik terbaik.
codeforester