茄子在线看片免费人成视频,午夜福利精品a在线观看,国产高清自产拍在线观看,久久综合久久狠狠综合

    <s id="ddbnn"></s>
  • <sub id="ddbnn"><ol id="ddbnn"></ol></sub>

  • <legend id="ddbnn"></legend><s id="ddbnn"></s>

    python程序員開發(fā)中常犯的10個錯誤
    來源:易賢網(wǎng) 閱讀:1611 次 日期:2016-06-30 09:34:57
    溫馨提示:易賢網(wǎng)小編為您整理了“python程序員開發(fā)中常犯的10個錯誤”,方便廣大網(wǎng)友查閱!

    python是一門簡單易學的編程語言,語法簡潔而清晰,并且擁有豐富和強大的類庫。與其它大多數(shù)程序設計語言使用大括號不一樣 ,它使用縮進來定義語句塊。

    在平時的工作中,python開發(fā)者很容易犯一些小錯誤,這些錯誤都很容易避免,本文總結了python開發(fā)者最常犯的10個錯誤,一起來看下,不知你中槍了沒有。

    1.濫用表達式作為函數(shù)參數(shù)默認值

    python允許開發(fā)者指定一個默認值給函數(shù)參數(shù),雖然這是該語言的一個特征,但當參數(shù)可變時,很容易導致混亂,例如,下面這段函數(shù)定義:

    代碼如下:

    >>> def foo(bar=[]):        # bar is optional and defaults to [] if not specified

    ...    bar.append(baz)    # but this line could be problematic, as we'll see...

    ...    return bar

    在上面這段代碼里,一旦重復調用foo()函數(shù)(沒有指定一個bar參數(shù)),那么將一直返回'bar',因為沒有指定參數(shù),那么foo()每次被調用的時候,都會賦予[]。下面來看看,這樣做的結果:

    代碼如下:

    >>> foo()

    [baz]

    >>> foo()

    [baz, baz]

    >>> foo()

    [baz, baz, baz]

    解決方案:

    代碼如下:

    >>> def foo(bar=none):

    ...    if bar is none:  # or if not bar:

    ...        bar = []

    ...    bar.append(baz)

    ...    return bar

    ...

    >>> foo()

    [baz]

    >>> foo()

    [baz]

    >>> foo()

    [baz]

    2.錯誤地使用類變量

    先看下面這個例子:

    代碼如下:

    >>> class a(object):

    ...     x = 1

    ...

    >>> class b(a):

    ...     pass

    ...

    >>> class c(a):

    ...     pass

    ...

    >>> print a.x, b.x, c.x

    1 1 1

    這樣是有意義的:

    代碼如下:

    >>> b.x = 2

    >>> print a.x, b.x, c.x

    1 2 1

    再來一遍:

    代碼如下:

    >>> a.x = 3

    >>> print a.x, b.x, c.x

    3 2 3

    僅僅是改變了a.x,為什么c.x也跟著改變了。

    在python中,類變量都是作為字典進行內(nèi)部處理的,并且遵循方法解析順序(mro)。在上面這段代碼中,因為屬性x沒有在類c中發(fā)現(xiàn),它會查找它的基類(在上面例子中只有a,盡管python支持多繼承)。換句話說,就是c自己沒有x屬性,獨立于a,因此,引用 c.x其實就是引用a.x。

    3.為異常指定不正確的參數(shù)

    假設代碼中有如下代碼:

    代碼如下:

    >>> try:

    ...     l = [a, b]

    ...     int(l[2])

    ... except valueerror, indexerror:  # to catch both exceptions, right?

    ...     pass

    ...

    traceback (most recent call last):

      file <stdin>, line 3, in <module>

    indexerror: list index out of range

    問題在這里,except語句并不需要這種方式來指定異常列表。然而,在python 2.x中,except exception,e通常是用來綁定異常里的 第二參數(shù),好讓其進行更進一步的檢查。因此,在上面這段代碼里,indexerror異常并沒有被except語句捕獲,異常最后被綁定 到了一個名叫indexerror的參數(shù)上。

    在一個異常語句里捕獲多個異常的正確方法是指定第一個參數(shù)作為一個元組,該元組包含所有被捕獲的異常。與此同時,使用as關鍵字來保證最大的可移植性,python 2和python 3都支持該語法。

    代碼如下:

    >>> try:

    ...     l = [a, b]

    ...     int(l[2])

    ... except (valueerror, indexerror) as e: 

    ...     pass

    ...

    >>>

    4.誤解python規(guī)則范圍

    python的作用域解析是基于legb規(guī)則,分別是local、enclosing、global、built-in。實際上,這種解析方法也有一些玄機,看下面這個例子:

    代碼如下:

    >>> x = 10

    >>> def foo():

    ...     x += 1

    ...     print x

    ...

    >>> foo()

    traceback (most recent call last):

      file <stdin>, line 1, in <module>

      file <stdin>, line 2, in foo

    unboundlocalerror: local variable 'x' referenced before assignment

    許多人會感動驚訝,當他們在工作的函數(shù)體里添加一個參數(shù)語句,會在先前工作的代碼里報unboundlocalerror錯誤( 點擊這里查看更詳細描述)。

    在使用列表時,開發(fā)者是很容易犯這種錯誤的,看看下面這個例子:

    代碼如下:

    >>> lst = [1, 2, 3]

    >>> def foo1():

    ...     lst.append(5)   # this works ok...

    ...

    >>> foo1()

    >>> lst

    [1, 2, 3, 5]

    >>> lst = [1, 2, 3]

    >>> def foo2():

    ...     lst += [5]      # ... but this bombs!

    ...

    >>> foo2()

    traceback (most recent call last):

      file <stdin>, line 1, in <module>

      file <stdin>, line 2, in foo

    unboundlocalerror: local variable 'lst' referenced before assignment

    為什么foo2失敗而foo1運行正常?

    答案與前面那個例子是一樣的,但又有一些微妙之處。foo1沒有賦值給lst,而foo2賦值了。lst += [5]實際上就是lst = lst + [5],試圖給lst賦值(因此,假設python是在局部作用域里)。然而,我們正在尋找指定給lst的值是基于lst本身,其實尚未確定。

    5.修改遍歷列表

    下面這段代碼很明顯是錯誤的:

    代碼如下:

    >>> odd = lambda x : bool(x % 2)

    >>> numbers = [n for n in range(10)]

    >>> for i in range(len(numbers)):

    ...     if odd(numbers[i]):

    ...         del numbers[i]  # bad: deleting item from a list while iterating over it

    ...

    traceback (most recent call last):

         file <stdin>, line 2, in <module>

    indexerror: list index out of range

    在遍歷的時候,對列表進行刪除操作,這是很低級的錯誤。稍微有點經(jīng)驗的人都不會犯。

    對上面的代碼進行修改,正確地執(zhí)行:

    代碼如下:

    >>> odd = lambda x : bool(x % 2)

    >>> numbers = [n for n in range(10)]

    >>> numbers[:] = [n for n in numbers if not odd(n)]  # ahh, the beauty of it all

    >>> numbers

    [0, 2, 4, 6, 8]

    6.如何在閉包中綁定變量

    看下面這個例子:

    代碼如下:

    >>> def create_multipliers():

    ...     return [lambda x : i * x for i in range(5)]

    >>> for multiplier in create_multipliers():

    ...     print multiplier(2)

    ...

    你期望的結果是:

    代碼如下:

    0

    2

    4

    6

    8

    實際上:

    代碼如下:

    8

    8

    8

    8

    8

    是不是非常吃驚!出現(xiàn)這種情況主要是因為python的后期綁定行為,該變量在閉包中使用的同時,內(nèi)部函數(shù)又在調用它。

    解決方案:

    代碼如下:

    >>> def create_multipliers():

    ...     return [lambda x, i=i : i * x for i in range(5)]

    ...

    >>> for multiplier in create_multipliers():

    ...     print multiplier(2)

    ...

    0

    2

    4

    6

    8

    7.創(chuàng)建循環(huán)模塊依賴關系

    假設有兩個文件,a.py和b.py,然后各自導入,如下:

    在a.py中:

    代碼如下:

    import b

    def f():

        return b.x

    print f()

    在b.py中:

    代碼如下:

    import a

    x = 1

    def g():

        print a.f()

    首先,讓我們試著導入a.py:

    代碼如下:>>> import a

    1

    可以很好地工作,也許你會感到驚訝。畢竟,我們確實在這里做了一個循環(huán)導入,難道不應該有點問題嗎?

    僅僅存在一個循環(huán)導入并不是python本身問題,如果一個模塊被導入,python就不會試圖重新導入。根據(jù)這一點,每個模塊在試圖訪問函數(shù)或變量時,可能會在運行時遇到些問題。

    當我們試圖導入b.py會發(fā)生什么(先前沒有導入a.py):

    代碼如下:

    >>> import b

    traceback (most recent call last):

         file <stdin>, line 1, in <module>

         file b.py, line 1, in <module>

        import a

         file a.py, line 6, in <module>

     print f()

         file a.py, line 4, in f

     return b.x

    attributeerror: 'module' object has no attribute 'x'

    出錯了,這里的問題是,在導入b.py的過程中還要試圖導入a.py,這樣就要調用f(),并且試圖訪問b.x。但是b.x并未被定義。

    可以這樣解決,僅僅修改b.py導入到a.py中的g()函數(shù):

    代碼如下:

    x = 1

    def g():

        import a # this will be evaluated only when g() is called

        print a.f()

    無論何時導入,一切都可以正常運行:

    代碼如下:

    >>> import b

    >>> b.g()

    1 # printed a first time since module 'a' calls 'print f()' at the end

    1 # printed a second time, this one is our call to 'g'

    8.與python標準庫模塊名稱沖突

    python擁有非常豐富的模塊庫,并且支持“開箱即用”。因此,如果不刻意避免,很容易發(fā)生命名沖突事件。例如,在你的代碼中可能有一個email.py的模塊,由于名稱一致,它很有可能與python自帶的標準庫模塊發(fā)生沖突。

    9.未按規(guī)定處理python2.x和python3.x之間的區(qū)別

    看一下foo.py:

    代碼如下:

    import sys

    def bar(i):

        if i == 1:

            raise keyerror(1)

        if i == 2:

            raise valueerror(2)

    def bad():

        e = none

        try:

            bar(int(sys.argv[1]))

        except keyerror as e:

            print('key error')

        except valueerror as e:

            print('value error')

        print(e)

    bad()

    在python 2里面可以很好地運行:

    代碼如下:

    $ python foo.py 1

    key error

    1

    $ python foo.py 2

    value error

    2

    但是在python 3里:

    代碼如下:

    $ python3 foo.py 1

    key error

    traceback (most recent call last):

      file foo.py, line 19, in <module>

        bad()

      file foo.py, line 17, in bad

        print(e)

    unboundlocalerror: local variable 'e' referenced before assignment

    解決方案:

    代碼如下:

    import sys

    def bar(i):

        if i == 1:

            raise keyerror(1)

        if i == 2:

            raise valueerror(2)

    def good():

        exception = none

        try:

            bar(int(sys.argv[1]))

        except keyerror as e:

            exception = e

            print('key error')

        except valueerror as e:

            exception = e

            print('value error')

        print(exception)

    good()

    在py3k中運行結果:

    代碼如下:$ python3 foo.py 1

    key error

    1

    $ python3 foo.py 2

    value error

    2

    在 python招聘指南里有許多關于python 2與python 3在移植代碼時需要關注的注意事項與討論,大家可以前往看看。

    10.濫用__del__方法

    比如這里有一個叫mod.py的文件:

    代碼如下:

    import foo

    class bar(object):

            ...

        def __del__(self):

            foo.cleanup(self.myhandle)

    下面,你在another_mod.py文件里執(zhí)行如下操作:

    代碼如下:

    import mod

    mybar = mod.bar()

    你會獲得一個attributeerror異常。

    至于為什么會出現(xiàn)該異常,點擊這里查看詳情。當解釋器關閉時,該模塊的全局變量全部設置為none。因此,在上面這個例子里,當__del__被調用時,foo已經(jīng)全部被設置為none。

    一個很好的解決辦法是使用atexit.register()代替。順便說一句,當程序執(zhí)行完成后,您注冊的處理程序會在解釋器關閉之前停止 工作。

    修復上面問題的代碼:

    代碼如下:

    import foo

    import atexit

    def cleanup(handle):

        foo.cleanup(handle)

    class bar(object):

        def __init__(self):

            ...

            atexit.register(cleanup, self.myhandle)

    在程序的正常終止的前提下,這個實現(xiàn)提供了一個整潔可靠的方式調用任何需要清理的功能。

    總結:

    python是一款強大而靈活的編程語言,并且?guī)в性S多機制和模式來大大提高工作效率。正如任何一門語言或軟件工具一樣,人們對其能力都會存在一個限制性地理解或欣賞,有些是弊大于利,有些時候反而會帶來一些陷進。 體會一名語言的細微之處,理解一些常見的陷阱,有助于你在開發(fā)者的道路上走的更遠。

    更多信息請查看腳本欄目
    易賢網(wǎng)手機網(wǎng)站地址:python程序員開發(fā)中常犯的10個錯誤

    2026上岸·考公考編培訓報班

    • 報班類型
    • 姓名
    • 手機號
    • 驗證碼
    關于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點 | 投訴建議
    工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務許可證:(云)人服證字(2023)第0102001523號
    聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關注公眾號:hfpxwx
    咨詢QQ:1093837350(9:00—18:00)版權所有:易賢網(wǎng)