和其餘編程語言相比,什麼纔是Python獨一無二的特點呢?不少程序員會說,縮進。的確,縮進是Python語言的標誌性特色,但這只是外在的、形式上的。從語言特性層面講,Python的特色是什麼呢?我嘗試着搜索了一下,最具表明性的答案分別是語法簡潔、簡單易學、代碼高效、功能強大等四項。仔細品味這四項,我仍是以爲,這是Python語言表現出來的使用效果或用戶感覺,仍然不是語言特性層面的特點。
換個說法,到底是Python的哪些語言特性使得人們廣泛認爲Python具備語法簡潔、簡單易學、代碼高效、功能強大的特色呢?我我的認爲,這要歸功於列表(list)、字典(dict)、元組(tuple)和集合(set)這「四大金剛」。儘管整型(int)、浮點型(float)和字符串(str)也很重要,但這三種對象相對於其餘編程語言來講,差別並不像「四大金剛」那樣明顯。能夠絕不誇張地說,列表、字典、元組和集合表明了Python語言的核心和基礎,同時也是Python的精髓所在。學會使用列表、字典、元組和集合,就意味着掌握了Python這門編程語言。
若是承認這個觀點,那麼,Python的精髓就從列表、字典、元組和集合等「四大金剛」,演變成由方括號、花括號和圓括號組成的「括號族」。
1. 方括號
方括號幾乎是全部編程語言的第一符號。這裏的第一,並非指使用頻率,而是指這個符號展示出的編程語言的內涵和創造力。事實上,就符號的使用頻率而言,方括號也可能排在首位——只是個人直覺,並無統計數據支持。
1.1 建立列表
對於初學者來講,建立列表最經常使用的方法就是用一對方括號。
>>> a = []
>>> a
[]
>>> b = [3.14, False, 'x', None]
>>> b
[3.14, False, 'x', None]
即使是老鳥,也會大量使用方括號建立列表,尤爲是使用推導式建立列表的狀況下。
>>> c = [i**2 for i in range(5)]
>>> c
[0, 1, 4, 9, 16]
但我一直以爲,方括號就像口語或俚語,太過隨便。我更喜歡使用嚴謹的list()來建立列表。使用list()建立列表,是list類的實例化的標準方法,能夠體會list類的構造函數如何適應不一樣類型的參數。
>>> a = list()
>>> a
[]
>>> b = list((3.14, False, 'x', None))
>>> b
[3.14, False, 'x', None]
>>> c = list({1,2,3})
>>> c
[1, 2, 3]
>>> d = list({'x':1,'y':2,'z':3})
>>> d
['x', 'y', 'z']
>>> e = list(range(5))
>>> e
[0, 1, 2, 3, 4]
>>> f = list('*'*i for i in range(5))
>>> f
['', '*', '**', '***', '****']
1.2 列表的索引
方括號能夠建立列表,但方括號並不等同於列表,由於方括號還用來索引。
>>> [3.14, False, 'x', None][2]
'x'
>>> [3.14, False, 'x', None][-2]
'x'
>>> [3.14, False, 'x', None][1:]
[False, 'x', None]
>>> [3.14, False, 'x', None][:-1]
[3.14, False, 'x']
>>> [3.14, False, 'x', None][::2]
[3.14, 'x']
>>> [3.14, False, 'x', None][::-1]
[None, 'x', False, 3.14]
列表的索引很是靈活,尤爲是引入了負數索引,用-1表示最後一個元素或逆序,實屬喜大普奔。上面的操做,屬於經常使用索引方式,若是能讀懂下面的代碼,說明你已經具有了足夠深的功力。
>>> a = [3.14, False, 'x', None]
>>> a[2:2] = [1,2,3]
>>> a
[3.14, False, 1, 2, 3, 'x', None]
1.3 列表的方法
對於列表對象的方法若是能信手拈來,那就是Python高手了。
>>> a = [3.14, False, 'x', None]
>>> a.index('x')
2
>>> a.append([1,2,3])
>>> a
[3.14, False, 'x', None, [1, 2, 3]]
>>> a[-1].insert(1, 'ok')
>>> a
[3.14, False, 'x', None, [1, 'ok', 2, 3]]
>>> a.remove(False)
>>> a
[3.14, 'x', None, [1, 'ok', 2, 3]]
>>> a.pop(1)
'x'
>>> a
[3.14, None, [1, 'ok', 2, 3]]
>>> a.pop()
[1, 'ok', 2, 3]
>>> a
[3.14, None]
2. 花括號
花括號表明字典對象,大多數初學者都這樣認爲。然而,這是錯誤的,至少是片面的。下面的代碼中,a和b都是用花括號創造出來的對象,卻一個是字典,一個是集合。
>>> a = {}
>>> a
{}
>>> b = {'x','y','z'}
>>> b
{'y', 'z', 'x'}
>>> type(a)
<class 'dict'>
>>> type(b)
<class 'set'>
原來,Python用花括號表示字典和集合兩種對象:花括號內是空的,或者是鍵值對的,表示字典;花括號內是無重複元素的,表示集合。爲了避免引發誤會,我習慣用dict()來生成字典,用set()來生成集合。
>>> dict()
{}
>>> dict({'x':1, 'y':2, 'z':3})
{'x': 1, 'y': 2, 'z': 3}
>>> dict((('x',1), ('y',2), ('z',3)))
{'x': 1, 'y': 2, 'z': 3}
>>> dict.fromkeys('xyz')
{'x': None, 'y': None, 'z': None}
>>> dict.fromkeys('abc', 0)
{'a': 0, 'b': 0, 'c': 0}
>>> set((3,4,5))
{3, 4, 5}
>>> set({'x':1, 'y':2, 'z':3})
{'y', 'z', 'x'}
>>> set([3,3,4,4,5,5])
{3, 4, 5}
編碼實踐中,雖然在某些狀況下集合是無可替代的,但集合的使用頻率是「四大金剛」中最低的,咱們這裏不展開討論,只說說字典的使用技巧。
2.1 判斷一個鍵是否存在於字典中
Py2時代,dict對象曾經有has_key()的方法,用來判斷是否包含某個鍵。py3捨棄了這個方法,判斷一個鍵是否存在於字典中,只能使用in這樣的方法了。
>>> a = dict({'x':1, 'y':2, 'z':3})
>>> 'x' in a
True
>>> 'v' in a
False
2.2 向字典中添加一個新鍵或更新鍵值
不少人喜歡用對字典的一個鍵賦值的方法,實現向字典中添加一個新鍵或更新鍵值。
>>> a = dict()
>>> a['name'] = 'xufive'
>>> a
{'name': 'xufive'}
我不推薦這樣的方式,使用update()才更有儀式感,還能夠一次添加或修改多個鍵。
>>> a = dict()
>>> a.update({'name':'xufive', 'gender':'男'})
>>> a
{'name': 'xufive', 'gender': '男'}
2.3 從字典中獲取一個鍵值
a['age']是最經常使用的方式,可是也還會遇到鍵不存在的異常。下面的方法值得推薦。
>>> a.get('age', 18)
18
2.4 獲取字典的所有鍵、所有值、所有鍵值對
dict類提供了keys()、values()和items()等三個方法分別返回字典的所有鍵、所有值和所有鍵值對。須要注意的是,返回結果並不是列表,而是迭代器。若是你須要列表形式的返回結果,請使用list()轉換。
>>> a = dict()
>>> a.update({'name':'xufive', 'gender':'男'})
>>> list(a.keys())
['name', 'gender']
>>> list(a.values())
['xufive', '男']
>>> list(a.items())
[('name', 'xufive'), ('gender', '男')]
2.5 遍歷字典
遍歷字典的時候,不少同窗或寫成遍歷字典的keys()。其實,不須要這麼麻煩,能夠像下面這樣直接遍歷。
>>> a = dict([('name', 'xufive'), ('gender', '男')])
>>> for key in a:
print(key, a[key])
name xufive
gender 男
3. 圓括號
圓括號表明元組對象,這麼說應該沒有問題吧?的確,聽起來沒有問題,但在元組的使用上,我相信每一個初學者都會跌進同一個深坑至少一次。
3.1 必入之淺坑
元組不用於列表的最顯著的特色,就是沒法更新元素的值。忘記或者忽略這一點,就會入坑。
>>> a = (3, 4)
>>> a[0] = 5
Traceback (most recent call last):
File "<pyshell#14>", line 1, in <module>
a[0] = 5
TypeError: 'tuple' object does not support item assignment
3.2 必入之深坑
使用了多年Python以後,我曾經寫出的最糟糕的bug,就是下面這一段代碼。
>>> import threading
>>> def do_something(name):
print('My name is %s.'%name)
>>> th = threading.Thread(target=do_something, args=('xufive'))
>>> th.start()
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Users\xufive\AppData\Local\Programs\Python\Python37\lib\threading.py", line 926, in _bootstrap_inner
Custom Domain by Bitly()
File "C:\Users\xufive\AppData\Local\Programs\Python\Python37\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
TypeError: do_something() takes 1 positional argument but 6 were given
我分明只提供了1個參數,卻提示說給出了6個參數,爲何呢?原來,元組初始化時,若是隻有單個參數,則必須在單個參數以後增長一個逗號(,),不然,初始化結果僅返回原參數。
a = (5)
>>> a
5
>>> type(a)
<class 'int'>
>>> b = ('xyz')
>>> b
'xyz'
>>> type(b)
<class 'str'>
>>> a, b = (5,), ('xyz',)
>>> a, b
((5,), ('xyz',))
>>> type(a), type(b)
(<class 'tuple'>, <class 'tuple'>)
3.3 單星號解包元組
格式化輸出字符串時,C語言風格是個人最愛。當有多個%須要匹配時,下面也許是最天然而然的寫法。
>>> args = (95,99,100)
>>> '%s:語文%d分,數學%d分,英語%d分'%('天元浪子', args[0], args[1], args[2])
'天元浪子:語文95分,數學99分,英語100分'
[點擊並拖拽以移動]
正確當然正確,但不夠精彩。滿分寫法應該是這樣的。
>>> args = (95,99,100)
>>> '%s:語文%d分,數學%d分,英語%d分'%('天元浪子', *args)
'天元浪子:語文95分,數學99分,英語100分'
3.4 爲何要使用元組?
既然元組的元素不可改變,那爲何還要使用元組呢?使用列表代替元組不是更方便嗎?誠然,在多數狀況下,可使用列表代替元組,但下面的例子卻能夠證實,列表沒法代替元組。
>>> s = {1,'x',(3,4,5)}
>>> s
{1, (3, 4, 5), 'x'}
>>> s = {1,'x',[3,4,5]}
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
s = {1,'x',[3,4,5]}
TypeError: unhashable type: 'list'
咱們能夠將元組加到集合中,但列表不行,由於列表是不可哈希(unhashable)的。理解這一點並不困難:列表元素能夠被動態改變,因此沒有一個固定不變的哈希值——這與集合要求的元素惟一性衝突;而元組的元素被禁止更新,其哈希值在整個生命週期都不會變化,所以能夠成爲集合的元素。
顯然,元組和列表有着徹底不一樣的存儲方式。由於不用考慮更新問題,元組的速度性能要遠優於列表。優先使用元組,應該成爲Python程序員遵循的一條基本原則。
程序員
本文的文字及圖片來源於網絡,僅供學習、交流使用,不具備任何商業用途,若有問題請及時聯繫咱們以做處理
想要獲取更多Python學習資料能夠加QQ:2955637827私聊或加Q羣630390733你們一塊兒來學習討論吧!shell