圍繞一門語言,學習它的文化精髓,能讓你成為一名更優秀的程式設計師。如果你還沒讀過Python之禪(Zen of Python) ,那麼開啟Python的命令提示符輸入import this,列表中的每一項你都可以在這裡找到相對應的例子。
(Credit: itswater )
吸引我注意力的一條是:
優雅勝於醜陋 (Beautiful is better than ugly)
看下面例子:
一個帶有數字引數的list函式其功能是返回引數中的奇數可以分開寫:
1 2 3 4 5 6 |
#----------------------------------------------------------------------- halve_evens_only = lambda nums: map(lambda i: i/2,\ filter(lambda i: not i%2, nums)) #----------------------------------------------------------------------- def halve_evens_only(nums): return [i/2 for i in nums if not i % 2] |
記住Python中那些非常簡單的事
兩個變數的交換:
1 |
a, b = b, a |
引數在切片操作中的步驟,如:
1 2 3 |
a = [1,2,3,4,5] >>> a[::2] # 以步長為2的增量迭代整個list物件 [1,3,5] |
1 |
一個特殊的例子 `x[::-1]`用來反轉x的實用語法。 |
1 |
1 2 |
>>> a[::-1] [5,4,3,2,1] |
不要用可變物件作為預設引數值(Don’t use mutable as defaults)
1 2 3 4 |
def function(x, l=[]): # 不要這麼幹 def function(x, l=None): # 更好的一種方式 if l is None: l = [] |
使用iteritems而不是items
iteriterms 使用的是 generators,所以當迭代很大的序列是此方法更好
1 |
1 2 3 4 5 |
d = {1: "1", 2: "2", 3: "3"} for key, val in d.items() # 呼叫items()後會構建一個完整的list物件 for key, val in d.iteritems() # 只有在迭代時每請求一次才生成一個值 |
此情景和range與xrange的關係相似。
使用isinstance 而不是type
不要這樣做:
1 |
1 2 3 |
if type(s) == type(""): ... if type(seq) == list or \ type(seq) == tuple: ... |
應該是這樣:
1 |
1 2 |
if isinstance(s, basestring): ... if isinstance(seq, (list, tuple)): ... |
至於為什麼這樣做,看這裡:http://stackoverflow.com/a/1549854/504262
需要注意的是這裡使用basestring而不是str是因為你可能會用一個unicode物件去檢查是否為string,例如:
1 |
1 2 3 4 5 |
>>> a=u'aaaa' >>> print isinstance(a, basestring) True >>> print isinstance(a, str) False |
因為在Python中3.0以下的版本存在兩種字串型別str和unicode
1 |
object |
1 |
| |
1 |
basestring |
1 |
/ \ |
1 |
str unicode |
學習各種集合(learn the various collections)
python有各種各樣的容器資料型別,在特定情況下選擇python內建的容器如:list和dict。通常更多像如下方式使用:
1 2 3 4 5 6 |
freqs = {} for c in "abracadabra": try: freqs[c] += 1 except: freqs[c] = 1 |
一種更好的方案如下:
1 2 3 |
freqs = {} for c in "abracadabra": freqs[c] = freqs.get(c, 0) + 1 |
一種更好的選擇 collection型別defautdict:
1 2 3 4 |
from collections import defaultdict freqs = defaultdict(int) for c in "abracadabra": freqs[c] += 1 |
其它集合
1 2 3 4 5 |
namedtuple() # 用指定的域建立元組子類的工廠函式 deque # 類似list的容器,快速追加以及刪除在序列的兩端 Counter # 統計雜湊表的dict子類 OrderedDict # 記錄實體新增順序的dict子類 defaultdict # 呼叫工廠方法為key提供預設值的dict子類 |
當建立類時Python的魔術方法:
1 2 3 4 5 6 |
__eq__(self, other) # 定義相等操作的行為, ==. __ne__(self, other) # 定義不相等操作的行為, !=. __lt__(self, other) #定義小於操作的行為, <. __gt__(self, other) #定義不大於操作的行為, >. __le__(self, other) #定義小於等於操作的行為, <=. __ge__(self, other) #定義大於等於操作的行為, >=. |
條件賦值
1 |
x = 3 if (y == 1) else 2 |
表示式請起來恰恰像:如果y等於1就把3賦值給x,否則把2賦值給x,當然同樣可以使用鏈式條件賦值如果你還有更復雜的條件的話。
1 |
x = 3 if (y == 1) else 2 if (y == -1) else 1 |
然而到了某個特定的點,它就有點兒過分了。
記住,你可以在任何表示式中使用if-else例如:
1 |
(func1 if y == 1 else func2)(arg1, arg2) |
func1將被呼叫如果y等於1的話,反之func2被呼叫。兩種情況下,arg1和arg2兩個引數都將附帶在相應的函式中。
類似地,下面這個表示式同樣是正確的
1 |
x = (class1 if y == 1 else class2)(arg1, arg2) |
class1和class2是兩個類
在有必要的時侯使用Ellipsis
建立類時,你可以使用__getitem__,讓你的類像字典一個工作,拿下面這個類舉例來說:
1 2 3 4 5 6 7 8 |
class MyClass(object): def __init__(self, a, b, c, d): self.a, self.b, self.c, self.d = a, b, c, d def __getitem__(self, item): return getattr(self, item) x = MyClass(10, 12, 22, 14) |
因為有了__getitem__,你就能夠通過物件x的x[‘a’]獲取a的值,這應該是公認的事實。
這個物件通常用於繼承Python的切片(slicing) (http://docs.python.org/library/stdtypes.html#bltin-ellipsis-object),如果新增如下語句:
1 2 3 4 5 |
def __getitem__(self, item): if item is Ellipsis: return [self.a, self.b, self.c, self.d] else: return getattr(self, item) |
我們就可以使用x[…]獲取的包含所有項的序列
1 2 3 |
>>> x = MyClass(11, 34, 23, 12) >>> x[...] [11, 34, 23, 12] |
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!