輕輕松松搞定python--2

序列

序列是一種有序的集合,就是諸如數組、鏈表或者對外呈現類似結構的數據結構,特點就是擁有一串的元素,并且這些元素的存放是有順序的。
python內置多種序列類型,對所有這些序列類型,有一些通用的操作方法可以調用(見后面'序列的一般操作'章節),同時各種序列類型各自還有一些特有方法。

字符串

字符串str是一種字符序列,每個元素是一個字符,python沒有單個字符類型,只有字符串類型,一個字符也是字符串。
python對字符串的支持非常強大,使用起來很方便。

字符串字面量

字符串字面量(literal)就是字符串常量的書寫方式,包括單引號、雙引號、三引號,raw字符多種方式

  • 單引號
    用單引號把一串字符包起來,就構成一個字符串,特殊字符需要用轉義,轉義方法和c語言基本類似。

    >>> string = 'life is short, you need python' 
    >>> print(string)         #print是內置打印函數,類似c語言的printf,注意print函數默認會自動添加換行
    life is short, you need python
    >>> 
    >>> string = 'life is short, \nyou need python\n'  
    >>> print(string)
    life is short, 
    you need python
    
    >>> 
    >>> len(string)    #內置函數len可以獲取字符串長度即字符個數,注意不像c語言的字符串,python字符串是不需要'\0'結尾的
    32
    
  • 雙引號
    雙引號和單引號的用法類似,但雙引號里可以包含單引號,單引號里可以包含雙引號而不需要轉義。

    >>> string = "life is short, 'you need python'"
    >>> print(string)
    life is short, 'you need python'
    >>> 
    >>> string = 'life is short, "you need python"' 
    >>> print(string)
    life is short, "you need python"
    >>>
    
  • 三引號
    三引號支持多行, 換行、tab等特殊字符可以直接輸入,所見即所得。三引號字符串也同樣可以使用轉義字符。

    >>> string = '''life is short, 
    ... \tyou need python'''       # 在python命令中換行時,會顯示‘...’, 表示可以繼續輸入
    >>> print(string) 
    life is short, 
            you need python
    >>> 
    
  • raw字符串
    raw字符串用于禁止轉義, 用小寫r和和大寫R作前綴,可以和前面的幾種引號組合

    >>> string = r'life is short, \nyou need python\n'
    >>> print(string)
    life is short, \nyou need python\n
    >>> 
    
格式化字符串

字符串的格式化不需要調用函數,直接使用 % 實現

>>> string = 'string = %s' % 'abc'
>>> print(string)
string = abc
>>> 
>>> string = '%s = %d' % ('abc', 123)       #多個參數要使用括號
>>> print(string)                    
abc = 123
字符串編碼

字符在內存中是用16位unicode表示的,因此字符可以不只是ascii字符,還可以包括中文、日文、德文等世界上幾乎所有的語言字符。可以用內置函數 ord 獲取單個字符的unicode值,用內置函數 chr 把單個unicode值轉成單個字符,還可以用16進制unicode值直接書寫字符串。

>>> ord('a')  
97
>>> chr(97)
'a'
>>> 
>>> ord('我')
25105
>>> chr(25105)
'我'
>>> 
>>> string = '\u6211\u662f\u8c01'
>>> print(string)
我是誰
>>> 

字符串在python內存中的編碼方式是unicode,每個字符固定2字節編碼,處理速度快但浪費存儲空間。一般各種文檔為了節省存儲空間,使用的編碼不是直接用unicode,而是用諸如ASCII(純英文)、國標GB2312(漢字)、UTF-8(通用)等其他編碼,這些編碼對不同字符采用不同長度的編碼,可節省存儲空間。
python解析器解析代碼時,默認是以UTF-8編碼來讀取的,因此若非有特殊原因,python代碼文件建議用UTF-8編碼保存。

字符串通過 encode 方法把unicode編碼轉成其他編碼方式,生成字節串,生成的字節串可以用于傳輸或寫到文件中。
注意:原始的字符串并沒有被改變,返回的字節串是新生成的

>>> 'who am i'.encode(encoding="utf-8")
b'who am i'
>>> 
>>> 'who am i'.encode(encoding="ascii")
b'who am i'
>>> 
>>> 'who am i, 我是誰'.encode(encoding="utf-8")
b'who am i, \xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81'
>>> 
>>> 'who am i, 我是誰'.encode(encoding="gb2312")
b'who am i, \xce\xd2\xca\xc7\xcb\xad'
>>> 

編碼后的字節串可以通過 decode 方法解出字符串,還可以通過內置函數 str 解出字符串
注意:原始的字節串并沒有被改變,返回的字符串是新生成的

>>> b'who am i'.decode(encoding="utf-8")
'who am i'
>>> 
>>> b'who am i'.decode(encoding="ascii")
'who am i'
>>> b'who am i, \xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81'.decode(encoding="utf-8")
'who am i, 我是誰'
>>> 
>>> b'who am i, \xce\xd2\xca\xc7\xcb\xad'.decode(encoding="gb2312")            
'who am i, 我是誰'
>>> 
>>> str(b'who am i, \xe6\x88\x91\xe6\x98\xaf\xe8\xb0\x81', encoding="utf-8")
'who am i, 我是誰'
>>> 
字符串方法

字符串內置很多方法(字符串其實是對象,python里一切皆對象),以下羅列出常用的方法并簡要說明,需要用到時可以再查閱python文檔。

  • 統計

    方法 說明
    str.count(sub[, start[, end]]) 統計子字符串
  • 編碼

    方法 說明
    str.encode(encoding="utf-8", errors="strict") 編碼,轉成字節串bytes
  • 查找和替換

    方法 說明
    str.startswith(prefix[, start[, end]]) 檢查字符串前綴
    str.endswith(suffix[, start[, end]]) 檢查字符串后綴
    str.find(sub[, start[, end]]) 正序(即左查找)查找字符串,返回第一個找到的位置,沒找到則返回-1
    str.rfind(sub[, start[, end]]) 右查找
    str.index(sub[, start[, end]]) 和find的唯一區別是,沒找到拋出ValueError異常
    str.rindex(sub[, start[, end]]) 和rfind的唯一區別是,沒找到拋出ValueError異常
    str.replace(old, new[, count]) 替換字符串
    str.expandtabs(tabsize=8) 把tabs轉成空格,注意并不是每個tab都轉成tabsize個空格,而是跟列對齊有關
  • 格式化

    方法 說明
    str.format(*args, **kwargs) 格式化
    str.format_map(mapping) 格式化,參數是個字典
  • 檢查字符串

    方法 說明
    str.isalnum() 是否由字母和數字組成
    str.isalpha() 是否只由字母組成
    str.isdecimal() 是否是10進制數
    str.isdigit() 是否只包含‘0’~‘9’
    str.isidentifier() 是否是有效的Python標識符
    str.islower() 是否全是小寫
    str.isnumeric() 是否是數字,可以不只包括數字字符‘0’~‘9’, 甚至可以包括漢字‘一’、‘二’、‘三’等
    str.isprintable() 是否全是可打印字符
    str.isspace() 是否全是空白字符
    str.istitle() 是否是標題,標題的每個單詞的首字母大寫
    str.isupper() 是否全是大寫
  • 對齊處理

    方法 說明
    str.center(width[, fillchar]) 居中處理
    str.ljust(width[, fillchar]) 左對齊, 并使用空格填充至長度width
    str.rjust(width[, fillchar]) 右對齊, 并使用空格填充至長度width
    str.zfill(width) 右對齊, 并使用‘0’填充至長度width
  • 大小寫處理

    方法 說明
    str.capitalize() 把首字母變成大寫,其余變成小寫
    str.casefold() 變成小寫,不僅僅針對英文字母,也包括其他字母,如德文
    str.lower() 轉為全小寫
    str.upper() 轉為全大寫
    str.swapcase() 翻轉大小寫
    str.title() 標題化,每個單詞首字母大寫
  • 去頭去尾處理

    方法 說明
    str.lstrip([chars]) 去頭
    str.rstrip([chars]) 去尾
    str.strip([chars]) 去頭去尾
  • 映射處理

    方法 說明
    static str.maketrans(x[, y[, z]]) 創建字符映射表, 是個靜態方法
    str.translate(table) 根據映射表,轉換字符串
  • 連接和分割處理

    方法 說明
    str.join(iterable) 用字符串作為分隔符,把序列中的元素連接起來
    str.partition(sep) 正序分離字符串,sep為第一個
    str.rpartition(sep) 反序分離字符串,sep為最后一個
    str.split(sep=None, maxsplit=-1) 正序分割字符串,可以指定最多分割次數,從左到右查找sep
    str.rsplit(sep=None, maxsplit=-1) 反序分割字符串,可以指定最多分割次數
    str.splitlines([keepends]) 按行分割

二進制字節串

二進制字節串有兩種類型,bytes和bytearray,bytes是不可變的,一旦初始化就不可修改,對其修改都是生成新字節串,bytearray的元素可以修改,并且長度也是可變的。

  • bytes字面量
    bytes常量用 b 前綴加上ascii字符串或小于256的16進制或8進制數表示

    >>> a = b'\x10\x11\x12'  #每個元素用2位16進制數表示
    >>> 
    >>> a = b'\20\21\022\347' #每個元素用2或3位8進制數表示, 個人建議不要用8進制,比如b'\378', 最后的8不是8進制數的一部分,暈吧?
    >>> 
    >>> a = b'abc'  #每個元素用1個asciii字符表示
    >>> 
    >>> a = b'\x10\x11\x12abc' #混合使用16進制數和ascii字符
    >>>
    >>> len(a) #獲取字節串長度
    6
    
  • 字節串創建

    >>> a = bytes()
    >>> a
    b''         #不是None
    >>> 
    >>> a = bytearray()
    >>> a
    bytearray(b'')      #不是None
    >>> 
    >>> a = bytes(10)
    >>> a
    b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'     #元素默認為0
    >>> 
    >>> a = bytearray(10)
    >>> a
    bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')  ##元素默認為0
    >>> 
    >>> a = bytes(range(10))
    >>> a
    b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t'
    >>> 
    

    實際上,bytes或bytearray可以通過bytes(obj)或bytearray(obj)創建,只要obj支持buffer protocol。至于什么是buffer protocol可以查閱python規范

  • 字節串方法
    str的方法幾乎都有對應的bytes和bytearray方法,這里只列出幾個特殊的。

    >>> bytes.fromhex('2Ef0F1f2') #
    b'.\xf0\xf1\xf2'
    >>> 
    >>> b'.\xf0\xf1\xf2'.hex()
    '2ef0f1f2'
    >>> 
    

列表和元組

列表和元組的每個元素可以是不同的數據類型,元組是不可變的,一旦初始化就不可更改,列表是可變的。

  • 創建
    列表用中括號或內置函數list創建,元組用圓括號或內置函數tuple創建。

    >>> a = []  # 空列表
    >>> a
    []
    >>> b = ()  # 空元組
    >>> b
    ()
    >>> 
    >>> a = (1,2,'aaa', None)  # 初始化值
    >>> a
    (1, 2, 'aaa', None)
    >>> 
    >>> b = [1,2,'aaa', None] # 初始化值
    >>> b
    [1, 2, 'aaa', None]
    >>> 
    >>> a = [1, 2, [3, 4], (5, 6)] # 元素甚至可以是列表或元組
    >>> a
    [1, 2, [3, 4], (5, 6)]
    
  • 列表推導
    即List Comprehensions,是指創建列表時,列表的每一個元素通過一個表達式來推導,表達式一般是個for循環, 可以帶if表達式,還可以是多重循環。
    使用列表推導可以精簡代碼,減少代碼行,但不建議寫太復雜的推導表達式,可讀性太差。
    注意元組沒有類似推導,如果寫成'元組推導',實際生成的不是元組,而是另一種東西,叫生成器(generator),后面會講。

    [x*x for x in range(1, 11)]                # 列表為:[1x1, 2x2, 3x3, ..., 10x10]
    
    [x*x for x in range(1, 11) if x % 2 == 0]  # 列表為:[2x2, 4x4, ..., 10x10], 只有偶數部分
    
    a = (1, 2, 3)
    b = (4, 5, 6)
    [x*y for x in a for y in b]                # 列表為:[4, 5, 6, 8, 10, 12, 12, 15, 18]
    
    (x*x for x in range(1, 11))                # 生成的不是元組,是生成器
    
  • 列表排序
    列表內建排序 sort(, key=None, reverse=None)* 方法,使用 '<' 比較元素,排序是在原列表上直接操作的,如果某個元素比較失敗,則整個排序失敗,并且已經被修改的元素不會還原。
    參數 key:一個函數,用來預處理每個比較 key, 比如 key=str.lower
    參數 reverse:是否反序,True則反序。
    元組沒有排序方法,因為元組是不可變的。

range

range用來生成一個數序列, 一般用在 for 循環中,range是不可變的,一旦生成后就不可更改,range的每個元素是在訪問到時才生成的,因此就算是一個很大整數的range也不會占用太多內存。這點和元組不同,也是為什么有元組了為何還需要range類型的原因。

>>> range(10)
range(0, 10)
>>> a = range(10)
>>> a
range(0, 10)
>>> 
>>> list(range(10))      
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> 
>>> list(range(0, 10, 2))
[0, 2, 4, 6, 8]

序列的一般操作

字符串、字節串、元組、列表等序列類型有一些通用的操作。

  • 通用操作

    操作 說明
    x in s 檢查序列中是否有元素等于x,有為True,否則為False
    x not in s 以上面剛好相反
    s + t 連接兩個序列, 注意:如果是不可變序列,則返回新的序列,不是修改原序列
    s[i] 第i個元素, i可以為負數,-1表示最后一個,-2為倒數第二個,以此類推
    s[i:j] 子序列切片:第i到第j-1元素, i,j可以為負數,-1表示最后一個,-2為倒數第二個,以此類推
    len(s) 序列長度
    s * n or n * s 相當于序列重復n次
    s[i] 第i個元素
    s[i:j] 子序列切片:第i到第j-1元素
    s[i:j:k] 子序列切片:第i到第j-1元素,間隔為k
    min(s) 元素最小值
    max(s) 元素最大值
    s.index(x[, i[, j]]) 從[i:j]中第一個值等于x的元素的索引
    s.count(x) 值等于x的元素個數
  • 可變序列特有的操作
    可變序列是指序列的元素在是可以修改的,列表是可變序列,字符串、字節串、元組、range是不可變序列

    操作 說明
    s[i] = x 第i個元素改寫為x
    s[i:j] = t 用t[0:j-i]替換s[i:j],t不一定是序列,只要是可迭代對象就行
    del s[i:j] 刪除第i到第j-1元素,也可以寫成 s[i:j] = []
    s[i:j:k] = t 跟s[i:j] = t類似,指定間隔
    del s[i:j:k] 跟del s[i:j]類似,指定間隔
    s.append(x) 把x加入到序列的尾部
    s.clear() 清空序列s 也可以寫成 del s[:]
    s.copy() 淺拷貝 也可以寫成 s[:]
    s.extend(t) or s += t 把序列t加入到序列s的尾部
    s *= n 相當于序列s重復n次,直接修改原序列s
    s.insert(i, x) 把x插入到i位置 也可以寫成 s[i:i] = [x]
    s.pop([i]) 彈出i元素,即返回i元素,并從序列中刪除i元素
    s.remove(x) 刪除序列中等于x的元素,如果有多個,則只刪除第一個
    s.reverse() 第一個元素和最后一個對調,第二個和倒數第二個對調,以此類推
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容