例舉 Python 的一些坑?
首先得聲明一下,本人可不是在黑Python,事實上目前正在用Python做項目,而且在接觸Python這些時間之後,已經不大使用C++和Delphi了,因為Python在很多方面已經滿足我的工作要求。
但在使用的過程中,也碰到過一些坑,我想凡用過一段時間的人也該深有體會。Python的坑也許還有更多,很想聽到各位的見解。
我覺得Python真正能算坑的其實不多,更多是因為對於內部機制了解不深。不過以下這個可以算真正的「坑」:
&>&> t = ([],[])
&>&> t[0] += [1] # guess what will happen?
&>&> print t # how about it now?
下面這個blog對於這個有詳細解釋,可以參考:
Stupid Python Ideas: Augmented Assignments (a += b)
我認為違背大多數人常規判斷的都屬於坑:比如(如無特別說明,同時針對Python2.7xPython3.x):1.
In [1]: f0, f1, f2 = [lambda x: x*i for i in range(3)]
In [2]: print f0(1), f1(1), f2(1) # ???
In [1]: var = 100
In [2]: def f1():
...: locals()[var] = 200
...: print var
...:
In [3]: def f2():
...: exec "locals()[var] = 300"
...: print var
...:
In [4]: f1(), f2() #???
In [1]: class Any(object):
...: def var(self): pass
...:
In [2]: obj = Any()
In [3]: obj.var == obj.var # True or False
In [4]: obj.var is obj.var # True or False
In [5]: id(obj.var) == id(obj.var) # True or False
In [6]: x, y = obj.var, obj.var
In [7]: x == y # True or False
In [8]: x is y # True or False
In [9]: id(x) == id(y) # True or False
In [1]: class Base(object):
...: def __init__(self):
...: self._value = 10
...: def __repr__(self):
...: return Value(%s) % self._value
...: @property
...: def value(self):
...: return self._value
...: @value.setter
...: def value(self, v):
...: self._value = v
...:
In [2]: class Derived(Base):
...: @property
...: def value(self):
...: return super(Derived, self).value * 2
...: @value.setter
...: def value(self, v):
...: super(Derived, self).value = v / 2
...:
In [3]: b, d = Base(), Derived()
In [4]: b.value, d.value
In [5]: b.value = 100
In [6]: d.value = 100
In [7]: b.value, d.value
In [1]: def createClsByName(name):
...: def createA():
...: class A:
...: xs, ys = ABC, 123
...: values = [x+y for x, y in zip(xs, ys)]
...: return A()
...: def createB():
...: class B:
...: xs, ys = ABC, 123
...: values = [xs[i]+ys[i] for i in range(len(xs))]
...: return B()
...: return createA() if name==A else createB()
...:
In [2]: createClsByName(A).values
Out[2]: #???
In [3]: createClsByName(B).values
Out[3]: #???
定義函數時的可選參數,實際上是個全局變數,如果寫一個引用類型的值(比如 dict / list / set)就坑爹了,比如:
def f(a, b=[]):
b.append(a)
print len(b)
f(1)
每次列印的結果都不一樣。
=================================================================
list 中兩個字元串如果不加逗號分割的話,不會報錯,而是合併為同一個字元串:l = [
foo # 這裡沒寫逗號
bar
]
如果不小心的話很容易中招。
=================================================================
datetime 的 isoformat 方法沒有時區信息,比如:from datetime import datetime
print datetime.now().isoformat()
結果是 2015-05-13T18:05:53.820435。這個時間是本地時間,最後也沒有時區信息,發送給其他服務去處理的時候,如果忽略時區信息,當成 UTC 時間來處理就中招了。
看起來有但其實並沒有的閉包。。。3的閉包勉強還能用,2連 nonlocal 都沒有。。。
Python中,多重繼承,parent1父類可以調用children子類的方法,也就是說可以調用子類多重繼承中另一個parent2父類的方法(繼承給了子類),而且這個方法parent1沒有定義,parent1也沒有父類(父類是object)。這樣寫有點像java的介面,因為parent1 new完以後,調用方法是會報錯,但是子類多重繼承後,因為子類從parent2繼承了該方法,所以不會出錯。於是會出現什麼問題呢,你看開源代碼的時候,有時候找不到該方法在哪裡定義,往上找繼承鏈找也找不到,這時可能需要往下找和往兩邊找(看子類或其他父類有沒有這個方法,坑。) 學過c++,Python,JavaScript,java。要說哪門簡單,我會選擇java,動態語言花樣太多
我遇到的if __name__ == __main__:判斷一直錯誤是什麼鬼→_→,剛開始代碼不執行,我還以為是我的包和模塊寫的有問題,調試的時候__name__也是__main__啊,可是一直跳過。直到我把這句話剪切又粘貼了一遍,它奇蹟般的又好了。。。神奇。
說兩個自己碰到過的吧第一個是cPickle在Ubuntu下load大文件時的問題,會爆Memory Error,但是改用pickle之後就可以順利load,讓我從此不敢再用cPickle(伺服器用的是Ubuntu傷不起)第二個是urllib里的quote這個函數。這個函數在python2.x和python3.x中不僅所在的包不一樣,而且如果同時安裝python2.x和python3.x,那麼python解釋器就會報錯,把爬蟲從2.x轉到3.x的時候比較坑
縮進……強迫是空格,多好,非得要個Tab最好調成縮進可見。複製粘貼,經常就是縮進錯
3都這麼多年,那就裝3吧,媽蛋,PIL尚不支持,找別的吧
上面也有人提到了,碰到坑的時候往往是對於Python運行的內部機制不太了解
這裡推薦個網站 Visualize Python code execution
它以可視化的形式幫助讀者加深對Python運行機制的了解
下面是運行效果截圖:
先贊一下題主沒有 spam tags。Python 十坑:10 Most Common Python Programming Problems
說一個我自己遇到的問題,也許並不算Python有坑,只是我腦子有坑。
因為不是專門學編程的,所以養成了一些不好的習慣,比如不想要的代碼就直接注釋掉,就像下面這個例子
a = 5
wf = wave.open(r"C:UsersNotepad++xboxubuntu.wav", rb)
print(a)
用 』引起來的部分是注釋,這樣可以把一大塊代碼一次注釋掉,但是這裡會出錯:
SyntaxError: (unicode error) unicodeescape codec cant decode bytes in position 20-21: truncated UXXXXXXXX escape
原因是這裡的U被認為是unicode編碼的轉義字元(涉及到編碼我就不想看了。。。),就是說如果在注釋中包含有U的話,就會被坑,其實不只是U,包含N, x, u都是不行的(可以參考python 3.3.3 字面量,正則,反斜杠和原始字元串)。用#注釋不會出現這個問題。
就我自己分析, 本質上還是字元串的一種,因為它本身具備的特質,被借用來當做注釋,和真正的注釋還是有所區別的。另外,把代碼修改一下:a = 5
r
wf = wave.open(r"C:UsersNotepad++xboxubuntu.wav", rb)
print(a)
這樣不會報錯。
-1
Python3
子類不寫構造函數會自動調用父類的構造函數,寫了就不自動調用了
多線程,2傻逼一樣的utf8支持。 還有pip上若干的坑比庫。
粘貼代碼,縮進不對,無法運行!!!!
語法上還好,就是複製了別人的(或者自己以前寫的)一段代碼,粘貼在現在的代碼上,縮進不對,不能運行。關鍵是人家ide也不知道你是什麼縮進的、不知道你的if語句是內循環里還是外循環里,也無法幫你縮進,只能手動調縮進。1.樓上說的函數默認參數問題
2.多線程 GIL 3.gc頓卡,不gc環引用內存泄露 4.python 程序相對較占內存,一個空字典就100多個位元組。py3做了改進5.寫cpython的話,引用計數和多線程下的GIL容易坑印象中碰到的就這些
Python的元組本來不就是以逗號區分的嗎?有沒有括弧反而是無所謂的事情,我不知道題主為什麼認為這是Python的坑
CPython的Global Interpreter Lock (GIL)
推薦閱讀:
※對ldap實現增刪改查--附demo
※Python 是慢,但我無所謂
※python封裝阿里雲API
※用100行Python爬蟲代碼抓取公開的足球數據玩(一)
TAG:Python |