最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python程序員開發(fā)中常犯的10個(gè)錯(cuò)誤

 更新時(shí)間:2014年07月07日 10:25:36   投稿:junjie  
這篇文章主要介紹了Python程序員開發(fā)中常犯的10個(gè)錯(cuò)誤,不知道你有沒有中槍呢,需要的朋友可以參考下

Python是一門簡(jiǎn)單易學(xué)的編程語言,語法簡(jiǎn)潔而清晰,并且擁有豐富和強(qiáng)大的類庫。與其它大多數(shù)程序設(shè)計(jì)語言使用大括號(hào)不一樣 ,它使用縮進(jìn)來定義語句塊。

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

1.濫用表達(dá)式作為函數(shù)參數(shù)默認(rèn)值

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

復(fù)制代碼 代碼如下:

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

  在上面這段代碼里,一旦重復(fù)調(diào)用foo()函數(shù)(沒有指定一個(gè)bar參數(shù)),那么將一直返回'bar',因?yàn)闆]有指定參數(shù),那么foo()每次被調(diào)用的時(shí)候,都會(huì)賦予[]。下面來看看,這樣做的結(jié)果:
復(fù)制代碼 代碼如下:

>>> foo()
["baz"]
>>> foo()
["baz", "baz"]
>>> foo()
["baz", "baz", "baz"]

解決方案:

復(fù)制代碼 代碼如下:

>>> 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.錯(cuò)誤地使用類變量

先看下面這個(gè)例子:

復(fù)制代碼 代碼如下:

>>> class A(object):
...     x = 1
...
>>> class B(A):
...     pass
...
>>> class C(A):
...     pass
...
>>> print A.x, B.x, C.x
1 1 1

這樣是有意義的:

復(fù)制代碼 代碼如下:

>>> B.x = 2
>>> print A.x, B.x, C.x
1 2 1

再來一遍:
復(fù)制代碼 代碼如下:

>>> A.x = 3
>>> print A.x, B.x, C.x
3 2 3

  僅僅是改變了A.x,為什么C.x也跟著改變了。

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

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

  假設(shè)代碼中有如下代碼:

復(fù)制代碼 代碼如下:

>>> 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ù),好讓其進(jìn)行更進(jìn)一步的檢查。因此,在上面這段代碼里,IndexError異常并沒有被except語句捕獲,異常最后被綁定 到了一個(gè)名叫IndexError的參數(shù)上。

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

復(fù)制代碼 代碼如下:

>>> try:
...     l = ["a", "b"]
...     int(l[2])
... except (ValueError, IndexError) as e: 
...     pass
...
>>>

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

  Python的作用域解析是基于LEGB規(guī)則,分別是Local、Enclosing、Global、Built-in。實(shí)際上,這種解析方法也有一些玄機(jī),看下面這個(gè)例子:

復(fù)制代碼 代碼如下:

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

許多人會(huì)感動(dòng)驚訝,當(dāng)他們?cè)诠ぷ鞯暮瘮?shù)體里添加一個(gè)參數(shù)語句,會(huì)在先前工作的代碼里報(bào)UnboundLocalError錯(cuò)誤( 點(diǎn)擊這里查看更詳細(xì)描述)。

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

復(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運(yùn)行正常?

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

5.修改遍歷列表

  下面這段代碼很明顯是錯(cuò)誤的:

復(fù)制代碼 代碼如下:

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

在遍歷的時(shí)候,對(duì)列表進(jìn)行刪除操作,這是很低級(jí)的錯(cuò)誤。稍微有點(diǎn)經(jīng)驗(yàn)的人都不會(huì)犯。

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

復(fù)制代碼 代碼如下:

>>> 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.如何在閉包中綁定變量

  看下面這個(gè)例子:

復(fù)制代碼 代碼如下:

>>> def create_multipliers():
...     return [lambda x : i * x for i in range(5)]
>>> for multiplier in create_multipliers():
...     print multiplier(2)
...

  你期望的結(jié)果是:
復(fù)制代碼 代碼如下:

0
2
4
6
8

  實(shí)際上:
復(fù)制代碼 代碼如下:

8
8
8
8
8

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

  解決方案:

復(fù)制代碼 代碼如下:

>>> 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)模塊依賴關(guān)系

  假設(shè)有兩個(gè)文件,a.py和b.py,然后各自導(dǎo)入,如下:

  在a.py中:

復(fù)制代碼 代碼如下:

import b

def f():
    return b.x
 
print f()


  在b.py中:
復(fù)制代碼 代碼如下:

import a

x = 1

def g():
    print a.f()


首先,讓我們?cè)囍鴮?dǎo)入a.py:

復(fù)制代碼 代碼如下:
>>> import a
1

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

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

  當(dāng)我們?cè)噲D導(dǎo)入b.py會(huì)發(fā)生什么(先前沒有導(dǎo)入a.py):

復(fù)制代碼 代碼如下:

>>> 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'

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

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

復(fù)制代碼 代碼如下:

x = 1
def g():
    import a # This will be evaluated only when g() is called
    print a.f()

無論何時(shí)導(dǎo)入,一切都可以正常運(yùn)行:

復(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標(biāo)準(zhǔn)庫模塊名稱沖突

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

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

  看一下foo.py:

復(fù)制代碼 代碼如下:

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里面可以很好地運(yùn)行:

復(fù)制代碼 代碼如下:

$ python foo.py 1
key error
1
$ python foo.py 2
value error
2

  但是在Python 3里:
復(fù)制代碼 代碼如下:

$ 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

解決方案:

復(fù)制代碼 代碼如下:

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中運(yùn)行結(jié)果:

復(fù)制代碼 代碼如下:
$ python3 foo.py 1
key error
1
$ python3 foo.py 2
value error
2

  在 Python招聘指南里有許多關(guān)于Python 2與Python 3在移植代碼時(shí)需要關(guān)注的注意事項(xiàng)與討論,大家可以前往看看。

10.濫用__del__方法

  比如這里有一個(gè)叫mod.py的文件:

復(fù)制代碼 代碼如下:

import foo
class Bar(object):
        ...
    def __del__(self):
        foo.cleanup(self.myhandle)

  下面,你在another_mod.py文件里執(zhí)行如下操作:
復(fù)制代碼 代碼如下:

import mod
mybar = mod.Bar()

 你會(huì)獲得一個(gè)AttributeError異常。

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

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

  修復(fù)上面問題的代碼:

復(fù)制代碼 代碼如下:

import foo
import atexit

def cleanup(handle):
    foo.cleanup(handle)


class Bar(object):
    def __init__(self):
        ...
        atexit.register(cleanup, self.myhandle)

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

總結(jié)

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

相關(guān)文章

  • Python開發(fā)加薪利器之Docker的使用實(shí)踐

    Python開發(fā)加薪利器之Docker的使用實(shí)踐

    docker利用容器技術(shù),獨(dú)立運(yùn)行一個(gè)或者一組應(yīng)用,docker是基于go語言開發(fā),docker鏡像好比是一個(gè)模版,可以通過這個(gè)模版來創(chuàng)建容器服務(wù),今天通過本文給大家分享Docker的使用實(shí)踐,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • Python?Pygame實(shí)戰(zhàn)之打磚塊游戲的實(shí)現(xiàn)

    Python?Pygame實(shí)戰(zhàn)之打磚塊游戲的實(shí)現(xiàn)

    這篇文章主要介紹了如何利用Python實(shí)現(xiàn)經(jīng)典的游戲—打磚塊。玩家操作一根螢?zāi)簧纤降摹鞍糇印?,讓一顆不斷彈來彈去的“球”在撞擊作為過關(guān)目標(biāo)消去的“磚塊”的途中不會(huì)落到螢?zāi)坏紫?。感興趣的小伙伴可以了解一下
    2022-03-03
  • Ubuntu配置Python環(huán)境的超詳細(xì)教程

    Ubuntu配置Python環(huán)境的超詳細(xì)教程

    這篇文章主要給大家介紹了關(guān)于Ubuntu配置Python環(huán)境的超詳細(xì)教程,文中通過代碼示例將配置的過程介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2023-08-08
  • python進(jìn)程池Pool中apply方法與apply_async方法的區(qū)別

    python進(jìn)程池Pool中apply方法與apply_async方法的區(qū)別

    這篇文章主要介紹了python進(jìn)程池Pool中apply方法與apply_async方法的區(qū)別及說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Sklearn調(diào)優(yōu)之網(wǎng)格搜索與隨機(jī)搜索原理詳細(xì)分析

    Sklearn調(diào)優(yōu)之網(wǎng)格搜索與隨機(jī)搜索原理詳細(xì)分析

    這篇文章主要介紹了Sklearn調(diào)優(yōu)之網(wǎng)格搜索與隨機(jī)搜索原理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • Pycharm自動(dòng)添加文件頭注釋和函數(shù)注釋參數(shù)的方法

    Pycharm自動(dòng)添加文件頭注釋和函數(shù)注釋參數(shù)的方法

    這篇文章主要介紹了Pycharm自動(dòng)添加文件頭注釋和函數(shù)注釋參數(shù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Python爬蟲庫requests-html進(jìn)行HTTP請(qǐng)求HTML解析等高級(jí)功能應(yīng)用

    Python爬蟲庫requests-html進(jìn)行HTTP請(qǐng)求HTML解析等高級(jí)功能應(yīng)用

    這篇文章主要為大家介紹了Python爬蟲庫requests-html進(jìn)行HTTP請(qǐng)求HTML解析JavaScript渲染以及更高級(jí)的功能應(yīng)用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • numpy.where() 用法詳解

    numpy.where() 用法詳解

    這篇文章主要介紹了numpy.where() 用法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Python文件操作指南解鎖三個(gè)txt文件合并技術(shù)

    Python文件操作指南解鎖三個(gè)txt文件合并技術(shù)

    本文將深入介紹如何利用Python編寫腳本,將三個(gè)文本文件中指定的列數(shù)據(jù)合并成一個(gè)新文件,通過豐富的示例代碼和詳細(xì)解釋,幫助掌握這一實(shí)用而靈活的數(shù)據(jù)處理技巧
    2024-01-01
  • python繪制y關(guān)于x的線性回歸線性方程圖像實(shí)例

    python繪制y關(guān)于x的線性回歸線性方程圖像實(shí)例

    這篇文章主要為大家介紹了python繪制y關(guān)于x的線性回歸線性方程圖像實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10

最新評(píng)論

阳高县| 绵阳市| 绵竹市| 忻城县| 临海市| 阿图什市| 福鼎市| 德江县| 重庆市| 汝州市| 阳江市| 盖州市| 铁岭市| 平邑县| 北海市| 宜章县| 九江县| 荆州市| 抚州市| 凉城县| 漾濞| 昌宁县| 丰原市| 河西区| 乐山市| 醴陵市| 绍兴县| 白银市| 荔波县| 东宁县| 旬邑县| 宁波市| 馆陶县| 江达县| 肥城市| 墨玉县| 屏南县| 封开县| 石嘴山市| 开江县| 华池县|