Python中實現參數類型檢查的簡單方法

來源:互聯網
上載者:User
Python是一門弱類型語言,很多從C/C++轉過來的朋友起初不是很適應。比如,在聲明一個函數時,不能指定參數的類型。用C做類比,那就是所有參數都是void*類型!void類型強制轉換在C++中被廣泛地認為是個壞習慣,不到萬不得已是不會使用的。

Python自然沒有類型強制轉換一說了,因為它是動態語言。首先,所有對象都從Object繼承而來,其次,它有強大的內省,如果調用某個不存在的方法會有異常拋出。大多數情況,我們都不需要做參數類型栓查,除了一些特殊情況。例如,某個函數接受一個str類型,結果在實際調用時傳入的是unicode,測試過程中又沒有代碼覆蓋到,這樣問題就比較嚴重了。解決方案也很簡單,藉助Python的內省,很容易就能判斷出參數的類型。但是每個地方都寫檢查代碼會很累贅,何況它帶來的實際價值並不高。一個好的解決方案是使用裝飾器。

''' >>> NONE, MEDIUM, STRONG = 0, 1, 2 >>> >>> @accepts(int, int, int) ... def average(x, y, z): ...   return (x + y + z) / 2 ... >>> average(5.5, 10, 15.0) TypeWarning: 'average' method accepts (int, int, int), but was given (float, int, float) 15.25'''def accepts(*types, **kw):  """ Function decorator. Checks that inputs given to decorated function  are of the expected type.  Parameters:  types -- The expected types of the inputs to the decorated function.       Must specify type for each parameter.  kw  -- Optional specification of 'debug' level (this is the only valid       keyword argument, no other should be given).       debug = ( 0 | 1 | 2 )  """  if not kw:    # default level: MEDIUM    debug = 1  else:    debug = kw['debug']  try:    def decorator(f):      def newf(*args):        if debug == 0:          return f(*args)        assert len(args) == len(types)        argtypes = tuple(map(type, args))        if argtypes != types:          msg = info(f.__name__, types, argtypes, 0)          if debug == 1:            print >> sys.stderr, 'TypeWarning: ', msg          elif debug == 2:            raise TypeError, msg        return f(*args)      newf.__name__ = f.__name__      return newf    return decorator  except KeyError, key:    raise KeyError, key + "is not a valid keyword argument"  except TypeError, msg:    raise TypeError, msgdef info(fname, expected, actual, flag):  """ Convenience function returns nicely formatted error/warning msg. """  format = lambda types: ', '.join([str(t).split("'")[1] for t in types])  expected, actual = format(expected), format(actual)  msg = "'%s' method " % fname \     + ("accepts", "returns")[flag] + " (%s), but " % expected\     + ("was given", "result is")[flag] + " (%s)" % actual  return msg

本質上講,這也是一種運行時檢查,但效果已經不錯了。
更多有趣的裝飾器的使用,可以參考這篇文章http://wiki.python.org/moin/PythonDecoratorLibrary

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.