乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      python 異常處理和斷言...

       天上飛雞 2022-04-05

      資料來(lái)源: https://book./details/321/

      介紹

      在編程過(guò)程中為了增加友好性,在程序出現(xiàn)bug時(shí)一般不會(huì)將錯(cuò)誤信息顯示給用戶讓用戶蒙逼,而是顯示一個(gè)更友好的提示信息。

      語(yǔ)法

      try:
          """your code"""
      except Exception:
          """上面的程序執(zhí)行出錯(cuò)后就指行這里的代碼"""
      

      需求:將用戶輸入的兩個(gè)數(shù)字相加

      while True:
          num1 = input('num1:')
          num2 = input('num2:')
          try:
              num1 = int(num1)
              num2 = int(num2)
              result = num1 + num2
          except Exception as e:
              print('出現(xiàn)異常,信息如下:')
              print(e)
      

      輸入的不是數(shù)字的話,執(zhí)行出錯(cuò)的異常就會(huì)把捕捉到
      在這里插入圖片描述

      像上面這個(gè)Exception異常,幾乎能捕捉到所有的錯(cuò)誤,這不一定是好事,因?yàn)槌绦虺鲥e(cuò)的原因有很多種,我可能希望出不同的錯(cuò)誤就執(zhí)行不同的異常處理邏輯。 全執(zhí)行同一邏輯的話會(huì)增加程序調(diào)試難度,因?yàn)槟悴恢朗鞘裁丛驅(qū)е碌腻e(cuò)誤

      異常類型

      內(nèi)置異常類的繼承關(guān)系

      BaseException ------------------------------------- 所有異常的基類
       +-- SystemExit ----------------------------------- 解釋器請(qǐng)求退出
       +-- KeyboardInterrupt  --------------------------- 用戶中斷執(zhí)行(通常是輸入^C)
       +-- GeneratorExit -------------------------------- 生成器(generator)發(fā)生異常來(lái)通知退出
       +-- Exception  ----------------------------------- 常規(guī)錯(cuò)誤的基類
            +-- StopIteration --------------------------- 迭代器沒(méi)有更多的值
            +-- StopAsyncIteration
            +-- ArithmeticError  ------------------------ 所有數(shù)值計(jì)算錯(cuò)誤的基類
            |    +-- FloatingPointError ----------------- 浮點(diǎn)計(jì)算錯(cuò)誤
            |    +-- OverflowError ---------------------- 數(shù)值運(yùn)算超出最大限制
            |    +-- ZeroDivisionError ------------------ 除(或取模)零 (所有數(shù)據(jù)類型)
            +-- AssertionError -------------------------- 斷言語(yǔ)句失敗
            +-- AttributeError -------------------------- 對(duì)象沒(méi)有這個(gè)屬性
            +-- BufferError
            +-- EOFError -------------------------------- 沒(méi)有內(nèi)建輸入,到達(dá)EOF 標(biāo)記
            +-- ImportError ----------------------------- 導(dǎo)入模塊/對(duì)象失敗
            |    +-- ModuleNotFoundError
            +-- LookupError ----------------------------- 無(wú)效數(shù)據(jù)查詢的基類
            |    +-- IndexError ------------------------- 序列中沒(méi)有此索引(index)
            |    +-- KeyError --------------------------- 映射中沒(méi)有這個(gè)鍵
            +-- MemoryError ----------------------------- 內(nèi)存溢出錯(cuò)誤(對(duì)于Python 解釋器不是致命的)
            +-- NameError ------------------------------- 未聲明/初始化對(duì)象 (沒(méi)有屬性)
            |    +-- UnboundLocalError ------------------ 訪問(wèn)未初始化的本地變量
            +-- OSError --------------------------------- 操作系統(tǒng)錯(cuò)誤
            |    +-- BlockingIOError
            |    +-- ChildProcessError
            |    +-- ConnectionError
            |    |    +-- BrokenPipeError
            |    |    +-- ConnectionAbortedError
            |    |    +-- ConnectionRefusedError
            |    |    +-- ConnectionResetError
            |    +-- FileExistsError
            |    +-- FileNotFoundError
            |    +-- InterruptedError
            |    +-- IsADirectoryError
            |    +-- NotADirectoryError
            |    +-- PermissionError
            |    +-- ProcessLookupError
            |    +-- TimeoutError
            +-- ReferenceError -------------------------- 弱引用(Weak reference)試圖訪問(wèn)已經(jīng)垃圾回收了的對(duì)象
            +-- RuntimeError ---------------------------- 一般的運(yùn)行時(shí)錯(cuò)誤
            |    +-- NotImplementedError ---------------- 尚未實(shí)現(xiàn)的方法
            |    +-- RecursionError
            +-- SyntaxError ----------------------------- Python 語(yǔ)法錯(cuò)誤
            |    +-- IndentationError ------------------- 縮進(jìn)錯(cuò)誤
            |         +-- TabError ---------------------- Tab 和空格混用
            +-- SystemError ----------------------------- 一般的解釋器系統(tǒng)錯(cuò)誤
            +-- TypeError ------------------------------- 對(duì)類型無(wú)效的操作
            +-- ValueError ------------------------------ 傳入無(wú)效的參數(shù)
            |    +-- UnicodeError ----------------------- Unicode 相關(guān)的錯(cuò)誤
            |         +-- UnicodeDecodeError ------------ Unicode 解碼時(shí)的錯(cuò)誤
            |         +-- UnicodeEncodeError ------------ Unicode 編碼時(shí)錯(cuò)誤
            |         +-- UnicodeTranslateError --------- Unicode 轉(zhuǎn)換時(shí)錯(cuò)誤
            +-- Warning --------------------------------- 警告的基類
                 +-- DeprecationWarning ----------------- 關(guān)于被棄用的特征的警告
                 +-- PendingDeprecationWarning ---------- 關(guān)于特性將會(huì)被廢棄的警告
                 +-- RuntimeWarning --------------------- 可疑的運(yùn)行時(shí)行為(runtime behavior)的警告
                 +-- SyntaxWarning ---------------------- 可疑的語(yǔ)法的警告
                 +-- UserWarning ------------------------ 用戶代碼生成的警告
                 +-- FutureWarning ---------------------- 關(guān)于構(gòu)造將來(lái)語(yǔ)義會(huì)有改變的警告
                 +-- ImportWarning
                 +-- UnicodeWarning
                 +-- BytesWarning
                 +-- ResourceWarning
      

      常見(jiàn)異常類型

      • AttributeError 試圖訪問(wèn)一個(gè)對(duì)象沒(méi)有的屬性,比如foo.x,但是foo沒(méi)有屬性x
      class A:
          pass
      
      try:
          a = A()
          print(a.name)  # name不存在
      except AttributeError as e:
          print(e) # 'A' object has no attribute 'name'
      
      • IOError 輸入/輸出異常;基本上是無(wú)法打開(kāi)文件
      try:
          f = open("不存在的文件.txt", mode="r", encoding="utf-8")
      except IOError as e:
          print(e)  # [Errno 2] No such file or directory: '不存在的文件.txt'
      
      • ImportError 無(wú)法引入模塊或包;基本上是路徑問(wèn)題或名稱錯(cuò)誤
      import importlib
      try:
          metaclass = importlib.import_module("import_lib.metaclasss")
      except ImportError as e:
          print(e)  # No module named 'import_lib.metaclasss'
      
      • IndexError 下標(biāo)索引超出序列邊界,比如當(dāng)x只有三個(gè)元素,卻試圖訪問(wèn)x[5]
      try:
          a = [1, 2, 3]
          print(a[9])
      except IndexError as e:
          print(e)
      
      • KeyError 試圖訪問(wèn)字典里不存在的鍵
      try:
          a = {"name": "張小小"}
          print(a["age"])
      except KeyError as e:
          print(e)	# age
      
      • KeyboardInterrupt Ctrl+C被按下
      """
      命令行程序運(yùn)行期間,如果用戶想終止程序,一般都會(huì)采用Ctrl-C快捷鍵,
      這個(gè)快捷鍵會(huì)引發(fā)python程序拋出KeyboardInterrupt異常。
      我們可以捕獲這個(gè)異常,在用戶按下Ctrl-C的時(shí)候,進(jìn)行一些清理工作。
      注意,攜程except Exception將無(wú)法捕獲KeyboardInterrupt異常。
      """
      try:
          # many code here
      except KeyboardInterrupt as e:
          # do something
      
      • NameError 使用一個(gè)還未被賦予對(duì)象的變量
      try:
          print(aa) # aa未定義
      except NameError as e:
          print(e) # name 'aa' is not defined
      
      • TypeError 傳入對(duì)象類型與要求的不符合
      try:
          print(float(['3']))
      except TypeError as e:
          print(e) # float() argument must be a string or a number, not 'list'
      
      • ValueError 傳入一個(gè)調(diào)用者不期望的值,即使值的類型是正確的
      """
      float函數(shù)可以接受字符串,即float('5'),只是float('string')中的值'string'是不合適的(不可轉(zhuǎn)換的)字符串
      另一方面
      因此,如果您嘗試float(['5']),就會(huì)得到一個(gè)TypeError,因?yàn)榱斜碛肋h(yuǎn)不能轉(zhuǎn)換為浮點(diǎn)。
      """
      try:
          print(float('ooo'))
      except ValueError as e:
          print(e) # could not convert string to float: 'ooo'
      
      import math
      try:
          print(math.sqrt(-10))
      except ValueError as e:
          print(e) # math domain error
      
      • UnboundLocalError 試圖訪問(wèn)一個(gè)還未被設(shè)置的局部變量,基本上是由于另有一個(gè)同名的全局變量,導(dǎo)致你以為正在訪問(wèn)它
      • IndentationError 語(yǔ)法錯(cuò)誤(的子類);代碼沒(méi)有正確對(duì)齊
      • SyntaxError Python代碼非法,代碼不能編譯(個(gè)人認(rèn)為這是語(yǔ)法錯(cuò)誤,寫錯(cuò)了)

      捕獲多個(gè)異常

      寫程序時(shí)需要考慮到try代碼塊中可能出現(xiàn)的任意異常,可以這樣寫:

      s1 = 'hello'
      try:
          int(s1)
      except IndexError as e:
          print(e)
      except KeyError as e:
          print(e)
      except ValueError as e:
          print(e)
      

      如果上面3個(gè)異常依然沒(méi)有匹配到對(duì)應(yīng)的錯(cuò)誤 怎么辦? 可以在程序最后加上Exception這個(gè)萬(wàn)能異常。

      一個(gè)except還可以同時(shí)包含多個(gè)異常,即相當(dāng)于我們對(duì)某幾個(gè)不同的異常,采用同樣的處理
      except后面跟著的多個(gè)異常類型,要把它們寫成tuple的形式。

      import os
      
      
      def test_exception2(num):
          try:
              a = 1/num
              if num == 1: os.remove('NotExistedFile')
          except (ZeroDivisionError, FileNotFoundError) as e:
              print('3---', repr(e))
      
      
      test_exception2(0)
      ZeroDivisionError('division by zero')
      test_exception2(1)
      FileNotFoundError(2, 'No such file or directory')
      

      其它異常結(jié)構(gòu)

      try:
          # 主代碼塊
          pass
      except KeyError,e:
          # 異常時(shí),執(zhí)行該塊
          pass
      else:
          # 主代碼塊執(zhí)行完,若未觸發(fā)任何異常,執(zhí)行該塊
          pass
      finally:
          # 無(wú)論監(jiān)測(cè)的代碼是否發(fā)生異常,都執(zhí)行該處代碼
          pass
      

      主動(dòng)觸發(fā)異常raise

      try:
          raise Exception('錯(cuò)誤了。。。')
      except Exception as e:
          print(e)
      

      raise是更好的return

      該資料來(lái)源:https://www./archives/1175

      編寫軟件,大部分代碼都是在處理各種異常和錯(cuò)誤。我們常常會(huì)遇到這樣的場(chǎng)景,代碼流程需要一層層的判斷底層的返回是否成功,
      這樣的代碼寫起來(lái)其實(shí)很費(fèi)勁,為了一個(gè)可能出現(xiàn)的錯(cuò)誤,要在每一個(gè)獲取返回值的地方寫if判斷。
      其實(shí),這個(gè)時(shí)候,使用raise來(lái)拋出一個(gè)異常,比用return返回標(biāo)志位(True或False),更加簡(jiǎn)單,代碼的可讀性和可維護(hù)性也更好,代碼的層次感也越強(qiáng)。

      return語(yǔ)句只能返回到上一層調(diào)用的地方,如果調(diào)用層次比較多,底層的問(wèn)題,要層層傳遞上來(lái)就太費(fèi)勁了,
      這樣代碼寫起來(lái)看起來(lái)都很別扭。return主要還是用來(lái)返回?cái)?shù)據(jù)的,而raise是更好的“返回異?!钡姆绞?。

      在一個(gè)處于層層調(diào)用關(guān)系的流程中,不管哪個(gè)地方raise拋出一個(gè)異常,我們只需要在流程需要的地方try…except…捕獲異常,
      就可以了。raise拋出異常后,代碼返回到最近的try…except…的地方(這是個(gè)與return很不一樣的細(xì)節(jié)),這樣中間流程的代碼,
      寫起來(lái)就會(huì)很輕松愜意優(yōu)雅。而且,如果中間雖捕獲了異常,但是不對(duì)異常進(jìn)行處理,也可以直接獨(dú)立的依據(jù)raise,再次將異常拋出,交給更上層來(lái)處理。

      舉個(gè)例子:

      def level_1():
          raise ValueError("this is a value error")
      
      
      def level_2():
          level_1()
          print("in level 2")
      
      
      def level_3():
          level_2()
          print("in level 3")
      
      
      def top():
          level_3()
          print("in top")
      
      
      try:
          top()
      except:
          print("catch exception from level 1")
      
      # 輸出:catch exception from level 1
      

      以上示例代碼,在最底層的函數(shù)raise一個(gè)ValueError異常,top函數(shù)與直接raise異常的函數(shù),中間還經(jīng)過(guò)了兩層調(diào)用。
      不過(guò),運(yùn)行程序發(fā)現(xiàn),最底層raise之后,在最頂層直接捕獲異常,而且,很重要的細(xì)節(jié)是,代碼中所有的打印都沒(méi)有執(zhí)行,
      代碼相當(dāng)于從最底層直接return到了最頂層try…except…的地方。

      這種代碼的寫法,比一層層return再判斷,要簡(jiǎn)單很多。這種層層調(diào)用在軟件中很常見(jiàn),稍微封裝一下底層接口代碼,
      層次關(guān)系就出現(xiàn)了。如果再學(xué)會(huì)了自定義Python的異常類,配合這種寫法,您的代碼一定會(huì)更加漂亮性感!

      單獨(dú)一句raise的作用

      代碼中常常能看到單獨(dú)使用一句raise,后面不帶任何參數(shù),這樣寫的作用是,將向下文當(dāng)前的異常拋出(raise語(yǔ)句不帶參數(shù)的默認(rèn)動(dòng)作)。

      def do_raise():
          raise ValueError('test value error')
      
      
      def middle():
          try:
              do_raise()
          except:
              print('something wrong')
              raise
      
      
      def top():
          try:
              middle()
          except ValueError as e:
              print(repr(e))
      
      
      top()
      

      在middle函數(shù)中,單獨(dú)使用raise語(yǔ)句,它將會(huì)被do_raise拋出的異常,直接在此拋出。middle函數(shù)不對(duì)此異常進(jìn)行處理,而是交給上層代碼去處理。這段代碼的運(yùn)行效果如下:

      something wrong
      ValueError('test value error')
      

      raise在層層調(diào)用的代碼流程中,簡(jiǎn)化了異常處理的代碼編寫,并形成了自己獨(dú)有的異常處理層次關(guān)系,使得代碼在處理異常時(shí)非常靈活高效。

      自定義異常

      class MyException(BaseException): # BaseException是所有異常的基類
          def __init__(self,msg):
              self.message = msg
          def __str__(self):
              return self.message
      try:
          raise MyException("我的錯(cuò)誤")
      except MyException as e:
          print(e)
      

      斷言

      • assert語(yǔ)法用于判斷代碼是否符合執(zhí)行預(yù)期
      • 一般來(lái)說(shuō)在做單元測(cè)試的時(shí)候用的比較多,在生產(chǎn)環(huán)境代碼運(yùn)行的情況下,不建議使用斷言,會(huì)讓程序abort掉。
      assert  type(1) is int
      assert  1+1 == 2
      assert  1+1 == 3 # 會(huì)報(bào)AssertionError
      

      應(yīng)用場(chǎng)景舉例,別人調(diào)你的接口,你的接口要求他調(diào)用時(shí)必須傳遞指定的關(guān)鍵參數(shù),等他傳遞進(jìn)來(lái)時(shí),你就可以用用assert語(yǔ)句他傳的參數(shù)是否符合你的預(yù)期

      def my_interface(name,age,score):
          assert type(name) is str
          assert type(age) is int
          assert type(score) is float
      my_interface("alex",22,89.2)
      

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多