Python_4_內(nèi)置結(jié)構(gòu)-元組-字符串

1. 元組概念

??元組(類型為 tuple)和列表十分相似,但是元組和字符串一樣是不可變的。

1.1. 元組的特點

  • 元組可以存儲一系列的值,使用 小括號 來定義,是一個 有序 的元素的集合。
  • 元組內(nèi)的元素是 不可變
  • 當元組內(nèi)嵌套列表這種引用類型時,元組的不可變表示的是嵌套的列表其內(nèi)存地址不會變,當直接操作元組內(nèi)嵌套的列表時漫蛔,是可以進行修改的

1.2. 元組的定義

格式:

tuple()   # 工廠函數(shù),用于創(chuàng)建并返回一個空元組
tuple(iterable)   # 使用可迭代對象的元素旧蛾,來初始化一個元組

例子:

In : t=(1)    # 會認為 () 只是優(yōu)先級

In : type(t) 
Out: int

In : t=(1,)

In : type(t)
Out: tuple     # tuple 表示元組類型
 
# 引用其他元組
In : a=(1,2,3)

In : t=('123',a)

In : t
Out:('123',(1, 2, 3))
 
# 通過索引只引用某一個值
In : t=('123', a[1])

In : t
Out:('123', 2)

# tuple 接受一個可迭代對象轉(zhuǎn)換為元組
In : tuple(range(1,7,2))
Out:(1, 3, 5)

1.3. 元組的訪問

??元組和列表在內(nèi)存中的格式是相同的莽龟,都是線性順序結(jié)構(gòu),所以我們可以像列表一樣锨天,使用 索引訪問 元組的元素毯盈,其中元組支持 正索引負索引,同樣不支持索引超界病袄,會提示 IndexError奶镶。

In : b =(1,2,3)

In : b[1]       
Out: 2

In : b[-1]
Out: 3

??當元組內(nèi)嵌套的是列表這種引用類型時迟赃,你可以對列表內(nèi)的數(shù)據(jù)進行修改,因為列表是可變的厂镇。

In : lst = (1, 2, [1, 2])
In : a = lst * 3

In : a
Out:(1, 2, [1, 2], 1, 2, [1, 2], 1, 2, [1, 2])

In : a[2][0] = 100 # 可以對嵌套的列表進行賦值操作 

In : a
Out:(1, 2, [100, 2], 1, 2, [100, 2], 1, 2, [100, 2])

In : a[3] = 100      # 修改指向的地址是不被允許的     
---------------------------------------------------------------------------
TypeError  Traceback(most recent call last)
<ipython-input-47-2b62bbdeb061> in <module>
----> 1 a[3] = 100

TypeError: 'tuple' object does not support item assignment

1.4. 元組的查詢

??我們通過使用元組的 index 方法和 count 來獲取和統(tǒng)計元組中的元素纤壁。

# 返回元組內(nèi)匹配 value 的第一個元素的 index
T.index(value, [start, [stop]]) --> integer   

# 統(tǒng)計 value 在元組中出現(xiàn)的次數(shù),不存在時捺信,則返回 0
T.count(value) --> integer   

??注意:t.index 和 t.count 因為要遍歷列表所有元素酌媒,時間復雜度都是 O(n), 隨著列表的元素增加,而效率下降


In : a=('1','2','3')

In : a.count("4")     # 不存在迄靠,返回 0
Out: 0

In : a.count("1")
Out: 1
 
# a.index(value) 用來返回 value 在元組中的索引秒咨,如果 value 不在元組中,則會報錯掌挚。
# 如果有多個雨席,默認返回第一個(可以指定從哪個索引開始查找到某個索引結(jié)束,指定范圍區(qū)間)

In : a=('1','2','3')

In : a.index('1')
Out: 0

In : a.index('3')
Out: 2

In : a=('1','2','3')    

In : a.index('4')     # 不存在吠式,就會報錯     
---------------------------------------------------------------------------
ValueError Traceback(most recent call last)
<ipython-input-58-dca64b8e9162> in <module>
----> 1 a.index('4')

ValueError: tuple.index(x): x not in tuple

>>> t1
('a', 'b', 'a', 'b', 'a', 'b', 'a', 'b')
>>> t1.index('a',5,7)    # 在指定的區(qū)間內(nèi)查找
6

2. 命名元組

??命名元組是元組的子類陡厘,所以它也是無法進行修改的,它的特點是可以針元組的對字段進行命名特占。
??Tuple有一個兄弟糙置,叫namedtuple。雖然都是tuple是目,功能更為強大谤饭。對于 namedtuple,你不必再通過索引值進行訪問懊纳,你可以把它看做一個字典通過名字進行訪問揉抵,只不過其中的值是不能改變的。

# 格式:
collections.namedtuple(typename, field_names, *, verbose=False, rename=False, module=None)   
# 返回一個新的元組子類嗤疯,名為 typename 冤今。
這個新的子類用于創(chuàng)建類元組的對象,可以通過域名來獲取屬性值身弊,同樣也可以通過索引和迭代獲取值。

常用參數(shù)含義

  • typename: 一般和命名元組的名稱相同列敲。
  • field_names: 可以是空白字符或逗號分隔的字段的字符串阱佛,可以是字段的列表

??namedtuple 存放在 collections 包中,所以需要先進行導入

>>> from collections import namedtuple    
>>> Point = namedtuple('Point', ['x', 'y'])  # 創(chuàng)建一個名為 Point 的命名元組類戴而,其中含有兩個字段
>>> p = Point(11, 22)     # 創(chuàng)建一個實例凑术,11 會傳遞給 x,22 會傳遞給 y所意。
>>> p[0] + p[1] # 可以通過索引訪問
33
>>> p.x + p.y     # 也可以通過字段名訪問
33
>>> p.x = 33# 無法修改淮逊,將報錯 
---------------------------------------------------------------------------
AttributeError    Traceback(most recent call last)
<ipython-input-63-dac7085722b7> in <module>
----> 1 p.x = 33

AttributeError: can't set attribute

??Namedtuple 比普通 tuple 具有更好的可讀性催首,可以使代碼更易于維護。同時與字典相比泄鹏,又更加的輕量和高效郎任。但是有一點需要注意,就是 namedtuple 中的屬性都是不可變的备籽。任何嘗試改變其屬性值的操作都是非法的舶治。

In : from collections import namedtuple

In : Animal = namedtuple('animal', 'name age type')   
# 創(chuàng)建一個名為 Animal 的命名元組類,其中含有 name车猬、age霉猛、type 三個字段

In : Tom = Animal(name='Tom', age=33, type='cat')   
# 創(chuàng)建一個實例并根據(jù)字段的關鍵字賦值。

In : Tom
Out: animal(name='Tom', age=33, type='cat')

In : print(Tom)
animal(name='Tom', age=33, type='cat')

In : type(Tom)
Out: __main__.animal

In : Tom.type# 可以通過字段名訪問
Out: 'cat'

In : Tom.age = 3    # 和 tuple 一樣珠闰,無法修改值惜浅,將報錯 
---------------------------------------------------------------------------
AttributeError     Traceback (most recent call last)
<ipython-input-9-63d4b4478930> in <module>
----> 1 Tom.age = 3

AttributeError: can't set attribute

3. 字符串

??字符串是 Python 中比較重要的數(shù)據(jù)類型,是以單引號 ' 或雙引號 " 括起來的任意文本伏嗜,比如 'abc'坛悉,"xyz" 等等。請注意阅仔,''"" 本身只是一種表示方式吹散,不是字符串的一部分,因此八酒,字符串 'abc' 只有 a空民,b,c 這 3 個字符羞迷。如果 ' 本身也是一個字符界轩,那就可以用雙引號 "" 括起來,比如 "I'm OK" 包含的字符是 I衔瓮,'浊猾,m,空格热鞍,O葫慎,K 這 6 個字符。有三種方法定義字符串:單引號薇宠,雙引號偷办,三引號,需要注意的是字符串是不可變對象澄港,并且從 Python3 起椒涯,字符串就是Unicode 類型。
??定義方式:

str1='this is string'
str2="this is string"

# 也可以是三個雙引號回梧,三個引號可以多行注釋但是不能單雙混合废岂,三重引號除了能定義字符串以外祖搓,還可以表示注釋。
str3='''this is string'''   

# 在 print 打印字符串的時候 \n 會被當作換行符進行打印
str4='hello\n world'    

# 前面使用了 r 對字符串進行整體轉(zhuǎn)義湖苞,所見即所得
str5=r'hello\n world'   

# 當然使用 \ 也可以對特殊符號進行脫義
str6='hellow\\nworld'   

# R 和 r 相同
str7=R'hello\nworld'    

3.1. 字符串的基本操作

??Python 的字符串是一個有序序列拯欧,所以他可以和列表一樣使用下標來訪問元素,但是由于它是不可變類型袒啼,所以無法對字符串中的某個字符進行修改哈扮,下面介紹下字符串的基本操作。

??單個字符并沒有特殊的類型蚓再,Python 中沒有字符的概念滑肉,嚴格來講,說字符是不準確的摘仅,字符串是由一個個長度為一的字符串組成的靶庙,雖然聽起來很別扭,但真的就是這樣!

3.1.1. 字符串的訪問

??字符串和列表是相似娃属,都是順序的線性結(jié)構(gòu)六荒,所以它可以被索引,也可以被遍歷矾端。字符串的索引類似數(shù)組的下標:

In : a = '1234567'

In : a[0] # 下標從 0 開始掏击,0 表示第一個數(shù)
Out: '1'

In : a[3] # 表示第四個數(shù)
Out: '4'

In : a[1] = 100   # 字符串無法修改  
---------------------------------------------------------------------------
TypeError  Traceback(most recent call last)
<ipython-input-3-8554a2b011c3> in <module>
----> 1 a[1] = 100

TypeError: 'str' object does not support item assignment

In : for i in a:       # 可以被 for 循環(huán)進行迭代
   ...:     print(i) 
   ...:     
1
2
3
4
5
6
7

In : list(a)# 可以被當作一個可迭代對象傳給 list,轉(zhuǎn)換為一個列表
Out: ['1', '2', '3', '4', '5', '6', '7']

3.1.2. 字符串的拼接

??當我們需要把多個字符串連接在一起秩铆,那么就需要對字符串進行拼接砚亭,python 提供了 join 方法,+ 號殴玛,以及 * 號捅膘,使我們方便的完成需求。

# 使用 join 對可迭代對象進行拼接滚粟,返回拼接后的字符串寻仗。
str.join(iterable) --> str   
  • join:str 可以為任意字符,包括空凡壤∈鹩龋可迭代對象中的元素必須是字符串類型
  • +:把兩個字符串直接進行連接,返回一個新的字符串
  • *:把字符串重復復制 N 次亚侠,返回一個新的字符串
In : str1 
Out: ['h', 'e', 'l', 'l', 'o']

In : ''.join(str1)
Out: 'hello'

In : str2 = ''.join(str1)  

In : str2 
Out: 'hello'

In : '-'.join(str1)      # 使用 - 進行拼接   
Out: 'h-e-l-l-o'

In : str2 * 2     
Out: 'hellohello'

In : str2 + str2  
Out: 'hellohello'

In : lst = [['1','2'], '1', '3']

In : ''.join(lst)  # lst 的第 0 個元素是列表曹体,不是字符串,無法拼接盖奈,會報錯
---------------------------------------------------------------------------
TypeError  Traceback(most recent call last)
<ipython-input-19-58ac5d2512ec> in <module>
----> 1 ''.join(lst)

TypeError: sequence item 0: expected str instance, list found

3.2. 字符串分割

??字符串中有關于字符分割功能的主要有兩類混坞,split 系和 partition 系狐援,他們分別適用于不用的場景钢坦。但用的比較多的是 split究孕。

  • split 系:將字符串按照分割符分隔成若干字符串,并返回列表
  • partition 系:將字符串按照分割符分割成 2 段爹凹,返回這 2 段和分隔符組成的三元組
# 從左至右對字符串 str 進行切割厨诸,分割符為 sep,默認為盡可能多的空字符禾酱,
# maxsplit 表示分割幾次微酬,默認為 -1,全部進行分割颤陶,返回一個切割后的列表颗管。
str.split(sep=None, maxsplit=-1) --> list of strings   

# 從左至右對字符串 str 進行切割,必須指定一個分割符 sep滓走,返回一個三元組垦江,
# 其中中間的元素為分割符,第一個和最后一個元素為按照分隔符分開后的前后兩個元素搅方。
# 當分隔符無法對字符串進行分割時比吭,返回的是 字符串,空姨涡,空衩藤,組成的三元組。
str.partition(sep) --> (head, sep, tail)   

# 例子:
In : s = "hello world I am Colin"

In : s.split() # 默認使用空格進行分割      
Out: ['hello', 'world', 'I', 'am', 'Colin']

In : s.split('o')      # 使用字母 o 進行分割
Out: ['hell', ' w', 'rld I am C', 'lin']   

In : s.split('o',1)    # 使用字母 o 進行分割涛漂,并且只分割 1 次    
Out: ['hell', ' world I am Colin']

In : s.split(sep='o',maxsplit=1)       # 也可以用關鍵字進行傳參
Out: ['hell', ' world I am Colin']

In : s.partition(' ')  # 使用 ' ' 進行分割赏表,返回三元組
Out:('hello', ' ', 'world I am Colin')

In : s.partition('o')  # 用字母 o 進行分割,返回一個三元組
Out:('hell', 'o', ' world I am Colin')

# --------------------------------------------------------------
In : s = "helloworldIamColin" # 當分割符不存在時

In : s.split()     # 一定會返回一個列表怖喻,如果沒有被切分底哗,那么會返回一個元素的列表
Out: ['helloworldIamColin']

# 一定會返回一個三元組,如果沒有被切分锚沸,那么會從字符串的最右邊切開跋选,
# 形成一個三元組,和一個空字符組成的列表
In : s.partition(' ') 
Out:('helloworldIamColin', '', '')

In : s.partition('12')
Out:('helloworldIamColin', '', '')

??當然 split 類還包含了其他兩個方法:

# 功能與 split 相同哗蜈,只不過從右往左切分
str.rsplit(sep=None, maxsplit=-1) --> list of strings   

# 按照行來切分前标,keepends 表示是否保留換行符,True 表示保留距潘,F(xiàn)alse 表示不保留炼列,默認為 False
str.splitlines([keepends]) --> list of strings    

# 例子:
In : s = 'I am struper Man' 

In : s.rsplit('a')     # 不指定分割次數(shù),一般和 split 是一樣的效果
Out: ['I ', 'm struper M', 'n']

In : s.rsplit(sep='a',maxsplit=1)     #  當指分割 1 次時音比,會從右邊開始切分       
Out: ['I am struper M', 'n']

In : s = 'hello\nworld\rI\nam\r\nColin'     

In : print(s)
hello
Iorld
am
Colin

In : s.splitlines() # 默認不保留分隔符
Out: ['hello', 'world', 'I', 'am', 'Colin']

In : s.splitlines(True)     # True 表示保留分隔符
Out: ['hello\n', 'world\r', 'I\n', 'am\r\n', 'Colin']

??partition 和 split 相似俭尖,也有個rpartition函數(shù),也是從右開始截取,需要注意的是稽犁,當分隔符無法對字符切分時焰望,返回的是已亥,字符串熊赖,組成的三元組。

3.3. 字符串大小寫

  • upper:將字符串轉(zhuǎn)換為大寫字母
  • lower:將字符串轉(zhuǎn)換為
  • swapcase: 大小寫對調(diào)
  • capitalize:轉(zhuǎn)換成首字母大寫的單詞格式
  • title: 轉(zhuǎn)換成每個單詞首字母大寫的標題模式
In : s = 'hElLo wORld i aM Colin'

In : s.upper()    
Out: 'HELLO WORLD I AM Colin'

In : s.lower()    
Out: 'hello world i am Colin'

In : s.swapcase() 
Out: 'HeLlO WorLD I Am Colin'

In : s.capitalize()       
Out: 'Hello world i am colin'

In : s.title()    
Out: 'Hello World I Am Colin'    

3.4. 字符串排版

  • center(width [,fillchar]):居中顯示虑椎,參數(shù) width 表示整體寬度震鹉,fillchar 表示填充字符,默認填充字符為空格
  • ljust(width [, fillchar]):左對齊捆姜,width 表示整體寬度传趾,fillchar 表示填充字符,默認填充字符為空格
  • rjust(width [, fillchar]):右對齊泥技,width 表示整體寬度墨缘,fillchar 表示填充字符,默認填充字符為空格
  • zfill(width):居右顯示零抬,參數(shù) width 表示整體寬度镊讼,左邊用 0 進行填充
In : a   
Out: 'abc'

In : a.ljust(20,'-')      
Out: 'abc-----------------'

In : a.rjust(20,'-')      
Out: '-----------------abc'

In : a.center(30,'-')     
Out: '-------------abc--------------' 

In : a.zfill(20)
Out: '00000000000000000abc'

3.5. 字符串修改

??前面說字符串是不可變的,為什么這里又說字符串的修改平夜?請繼續(xù)往下看

# 對字符串 str 進行查找蝶棋,將指定的 old 字符串轉(zhuǎn)換為 new 字符串,count 表示替換的次數(shù)忽妒,默認表示重復替換所有
str.replace(old, new [, count]) --> str   

# 從字符串 str 兩端去除指定的字符集 chars 中的所有字符玩裙,
# chars 默認是所有空白字符(\n,\r\n,\r,\t 等等都包含)
str.strip([chars]) --> str

str.lstrip([chars]) --> str    # 從左開始

str.rstrip([chars]) --> str    # 從右開始

注意:replace 的替換是 生成一個新的字符串, 而 不是就地修改原字符串,這也是字符串修改的原理

In : s = ' \n\t Hello World \n\r' 

In : s.strip()     # ' 不指定 chars段直,默認是任意多個空白字符
Out: 'Hello World'

In : s.strip(' \n\tHd')   # 如果指定了 chars吃溅,那么就挨個使用 char 進行匹配去除
Out: 'ello World \n\r'

In : s.strip(' \n\rHd')    
Out: '\t Hello Worl'

In : s.replace('World', 'Colin')
Out: ' \n\t Hello Colin \n\r' 

In : s.replace('o', 'O') # 默認從頭到尾進行替換
Out: ' \n\t HellO WOrld \n\r'

In : s.replace('o', 'O', 1) # 指定替換 1 次      
Out: ' \n\t HellO World \n\r'  

3.6. 字符串查找

??我們有很多的時候要判斷關鍵字是否存在一個字符串中,那么我們就需要在字符串中 遍歷 查找鸯檬,是否有匹配的字符串决侈。python 提供了 findrfind喧务、index赖歌、count 等函數(shù)用于完成需求。

 # 在指定的區(qū)間[start, end)功茴,從左至右庐冯,查找子串 sub 。找到返回索引坎穿,沒找到返回 -1
str.find(sub [, start [, end]]) --> int 

# 在指定的區(qū)間[start, end)展父,從右至左返劲,查找子串 sub 。找到返回索引栖茉,沒找到返回 -1
str.rfind(sub [, start [, end]]) --> int  

# 在指定的區(qū)間[start, end)旭等,從左至右,查找子串 sub 衡载。找到返回索引,沒找到拋出異常 ValueError
str.index(sub [, start [, end]]) --> int  

# 在指定的區(qū)間[start, end)隙袁,從右至左痰娱,查找子串 sub 。找到返回索引菩收,沒找到拋出異常 ValueError
str.rindex(sub[, start[, end]]) --> int  

# 在指定的區(qū)間[start, end)梨睁,從左至右,統(tǒng)計子串 sub 出現(xiàn)的次數(shù)娜饵,默認為整個字符串坡贺。沒有找到返回 0
str.count(sub [, start [, end]]) --> int  

??find 、index 和 count 方法由于是遍歷查找箱舞,所以時間復雜度都是 O(n), 會隨著字符串序列的數(shù)據(jù)規(guī)模的增大遍坟,而效率下降。


In : s = 'abc abc abc'    

In : s.find('a')  
Out: 0

In : s.find('a',1,-1)   # 指定區(qū)間晴股,注意這里 -1 表示最后 1 位愿伴,但是不包含 -1,類似于 [1,-1)
Out: 4

In : s.find('a',-1,-15)   # end 超出范圍电湘,沒找到返回 -1
Out: -1

In : s.rfind('a') 
Out: 8

In : s.rfind('a', 2, -1)    
Out: 8  
  
In : s.rfind('c', 2, -1)    
Out: 6  
  
In : s.rfind('c', 2, -100)    
Out: -1  # end 超出范圍隔节,沒找到返回 -1,start寂呛,end 表示起始和終止怎诫,最好不要使用負數(shù)表示區(qū)間

In : s.index('a') 
Out: 0

In : s.rindex('a', 2)     # 從索引 2 至最右邊,從右往左查找  
Out: 4

In : s.index('e') # 沒找到贷痪,直接報異常
---------------------------------------------------------------------------
ValueError Traceback(most recent call last)
<ipython-input-25-90b1c28da6f0> in <module>
----> 1 s.index('e')

ValueError: substring not found

In : s.count('a')
Out: 3

3.7. 字符串判斷

??Python 的字符串對象提供了兩個函數(shù)幻妓,用于對字符串的起始位和結(jié)尾位來進行匹配,它們是 startswithendswith劫拢。

# 在指定的區(qū)間[start, end)涌哲,字符串是否是 prefix 開頭,默認為 0尚镰,即整個字符串 str, 返回 bool 類型阀圾。
str.startswith(prefix [, start [, end]]) --> bool       

# 在指定的區(qū)間[start, end),字符串是否是 suffix 結(jié)尾狗唉,默認為 0初烘,即整個字符串 str, 返回 bool 類型。
str.endswith(suffix [, start [, end]]) --> bool 

??例子:

In : s    
Out: 'abc abc abc'

In : s.startswith('bc',1,-1)    # 從 s 的 [1,-1) 開始判斷 'bc' 是否是開頭
Out: True

In : s.endswith('bc',2,-1)      # 從 s 的 [2,-1) 開始匹配 'bc' 是否是結(jié)尾
Out: False     # 這里 -1 不包含,所以返回 False

In : s.endswith('bc',3,7) 
Out: True

In : s.startswith('abc')  
Out: True

In : s.endswith('bc')     
Out: True 

??除了判斷開始和結(jié)尾肾筐,Python 的字符串還提供了部分函數(shù)哆料,用來判斷字符串內(nèi)的元素類型,比如判斷字符串是否是純數(shù)字組成吗铐?是否是純字母組成等东亦,這些函數(shù)的返回值統(tǒng)一都為bool型,可以作為if 語句的條件表達式唬渗。

str.isalpha()      # 是否是字母
str.isalnum()      # 是否是字母和數(shù)字組成
str.isdigit()      # 是否全是十進制數(shù)字典阵,int
str.isdecimal()    # 判斷是否是數(shù)字類型,包含 float镊逝,但不包含負數(shù)
str.islower()      # 判斷字符串是否全是小寫字母
str.isupper()      # 判斷字符串是否全是大寫字母
str.isspace()      # 是否是空白字符
str.isnumberic()   # 判斷是否是正整數(shù)
str.isidentifier() # 是否是一個合規(guī)的變量標識符

3.8. 字符串格式化

??字符串格式化是我們需要重點掌握的東西壮啊,在早期的 Python 中使用的是 C 語言風格的字符串替換,使用起來比較難看撑蒜,不符合 python 的風格(純屬筆者猜測)歹啼。后來 Python 推薦使用內(nèi)置的 format 函數(shù)來對字符串進行格式化。
??字符串格式化是一種拼接字符串輸出樣式的手段座菠,更靈活方便狸眼,之前我們使用 join+ 來對字符串進行拼接泌射。

  • join:只能使用分隔符边篮,且要求被拼接的是可迭代對象且元素必須是字符串類型
  • +:使用起來比較方便许帐,但是非字符串需要先轉(zhuǎn)換為字符串類型才可以進行拼接沥潭。

3.8.1. C 語言格式化

??在 Python 2.5 版本以前刃永,只能使用 printf-style formatting 風格的 print 輸出励稳,這種風格來自于 C 語言的 printf 函數(shù)抢韭,它有如下格式要求松嘶。(建議使用 format)

  1. 占位符:使用 % 和格式字符串組成降宅,例如 %s骂远,%d 等。s 調(diào)用 str() 腰根,r 會調(diào)用 repr()激才。所有對象都可以被這兩個轉(zhuǎn)換
  2. 占位符中還可以插入修飾字符,例如 %03d 表示打印 3 個位置额嘿,不夠的話瘸恼,前面補 0
  3. format % value 格式字符串和被格式字符串之間使用 % 分割
  4. values 只能是一個對象,或是一個與格式字符串占位符數(shù)量相等的元組册养,或一個字典
In : 'I am %03d' % 20  # 表示 3 為數(shù)字东帅,不夠的話高位補 0
Out: 'I am 020'

In : 'I like %s' % 'Python'      # 字符串格式化
Out: 'I like Python'

In : 'I am %s' % 20      # 20 會被 str 作用后,傳遞給字符串 
Out: 'I am 20'

# 3.2f 表示最長 3 為球拦,小數(shù)點后精度為 2 位靠闭,當數(shù)字大時整體長度會被撐開帐我,
# x 表示 16 進制,02X 表示兩位顯示愧膀,高位補 0
In : '%3.2f%%,0x%x,0X%02X' % (89.7654,10,15)     
Out: '89.77%,0xa,0X0F'

In : "I am %-5d" % 20     
Out: 'I am 20   '

In : "I am %5d" % 20      
Out: 'I am    20'

3.8.2. format 格式化

??Python 中推崇使用 format() 函數(shù)來對字符串進行格式化拦键。

# 函數(shù)的一般格式,{} 表示占位符檩淋,使用 format 中的參數(shù)進行傳遞
'{}{XXX}'.format(*args, **kwargs)  --> str   

??format 非常靈活芬为,下面是基本使用方法說明:

  1. args 是可變位置參數(shù),是一個元組
  2. kwargs 是可變關鍵字參數(shù)蟀悦,是一個字典
  3. 花括號 表示 占位符
  4. {} 表示按照順序匹配 位置參數(shù)媚朦,{n} 表示取位置參數(shù)中 索引為 n 的值
  5. {xxx} 表示在關鍵字參數(shù)中搜索名稱一致的值,kwargs 必須放在 可變位置參數(shù)的后面
  6. {{}} 表示打印花括號
# 按照位置格式化熬芜,第一個元素給第一個括號,第二個元素給第二個括號      
In : '{}:{}'.format('10.0.0.13','8888')       
Out: '10.0.0.13:8888'    # 

# 命名格式化福稳,host 表示只獲取關鍵字為 host 的值來填充涎拉,
# 其他沒有指定關鍵字的占位符,則按照位置參數(shù)進行傳遞的圆,并格式化顯示     
In : '{host}:{}:{}'.format('10.0.0.13','8888',host='Colin')   
Out: 'Colin:10.0.0.13:8888'

# 訪問元素的方式進行字符串格式化(不常用)
In : '{0[0]}:{0[1]}'.format(['10.0.0.13','8888'])   
Out: '10.0.0.13:8888'

# 由于 p 對象含有 x 和 y 屬性鼓拧,所以可以在字符串格式化時直接引用
In : from collections import namedtuple     
In : Point = namedtuple('_Point',['x','y']) 
In : p = Point(4,5)       
In : print('{' + '{0.x},{0.y}'.format(p) + '}')   
Out: '{4,5}'

3.8.3. 對齊

??字符串還提供了多種的對齊方式,便于我們對輸出內(nèi)容做一個簡單的優(yōu)化越妈。

  • <:左對齊(默認)
  • >:右對齊
  • ^: 居中對齊

??對齊方式需要在占位符內(nèi)使用 :號 進行分割

#   打印字符串季俩,這個字符串占 5 位,默認靠左對齊梅掠,其他位使用空格填充
In : '{:5}'.format('c')     
Out: 'c    '

# > 表示右對齊
In : '{:>5}'.format('c')       
Out: '    c'

# 字符串站 5 位酌住,左對齊,其他位使用 0 填充(可以簡寫為 '{:<05}')
In : '{:0<5}'.format('c')     
Out: 'c0000'

In : '{:0>5}'.format('c')
Out: '0000c'

# > 表示右對齊阎抒,其他位用 * 填充
In : '{:*>5}'.format('c')     
Out: '****c'

# 居中對齊酪我,其它位使用 0 進行填充 
In : '{:0^5}'.format('c')     
Out: '00c00'

# 居中對齊,其它位使用 * 進行填充
In : '{:*^5}'.format('c')
Out: '**c**'

??當填充符為數(shù)字的時候且叁,可以與寬度寫在一起都哭,比如 '{:0<5}'.format('3') 可以寫成 '{:<05}'.format('3'),而 '{:0^5}'.format('3') 可以寫成 '{:^05}'.format('3')

3.8.4. 浮點數(shù)與進制

??雖然用的不多逞带,還是這里還是舉例說明一下進制和浮點數(shù)的使用方法(注意寬度可以被撐破)

  • d: 表示十進制
  • x: 表示十六進制
  • o: 表示八進制
  • b: 表示二進制
  • F: 表示浮點型
  • #: 表示添加進制前綴
  • *[1,2,3]: 表示把列表中的元素解構(gòu)出來:*[1,2,3] --> 1,2,3
# 輸出時轉(zhuǎn)換進制
In : "int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42)
Out: 'int: 42; hex: 2a; oct: 52; bin: 101010'

# 加上進制前綴
In : "int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42)
Out: 'int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010'

In : octets = [10,0,0,13]      

In : '{:02X}{:02X}{:02X}{:02X}'.format(*octets) 
Out: '0A00000D'

In : '{:02X}-{:02X}-{:02X}-{:02X}'.format(*octets)      
Out: '0A-00-00-0D'  
 
# ----------------------------------------------------------
In : "{}".format(3**0.4)# 默認按照字符串打印 
Out: '1.5518455739153598' 
 
In : "{:f}".format(1.5518455739153598)      # f 表示填充位為小數(shù)欺矫,小數(shù)是有精度的
Out: '1.551846' 
 
In : "{:02f}".format(1.5518455739153598)    # 表示小數(shù)的長度為 2,但是如果小數(shù)的位數(shù)超過 2展氓,會直接撐開   
Out: '1.551846' 
 
In : "{:10f}".format(1.5518455739153598)    # 表示小數(shù)的長度為 10穆趴,默認是右對齊 
Out: '  1.551846' 
 
In : "{:<10f}".format(1.5518455739153598)   # 左對齊 
Out: '1.551846  ' 
 
In : "{:.2f}".format(1.5518455739153598)    # .2f 表示小數(shù)點后取兩位的浮點型 
Out: '1.55' 
 
In : "{:3.2f}".format(123456.123456)   # 總長 3 位,小數(shù)點后保留 2 位遇汞,若整數(shù)位長度超出毡代,則撐開 
Out: '123456.12' 
 
In : "{:2.2%}".format(1.5518455739153598)   # 使用百分比顯示
Out: '155.18%'

4. bytes阅羹、bytearray

??Python3 引入兩個新類型:

  1. bytes:不可變字節(jié)序列
  2. bytearray:字節(jié)數(shù)組,可變

字符串與 bytes

  • 字符串是字符組成的有序序列教寂,字符可以使用編碼來理解
  • bytes 是字節(jié)組成的有序的不可變序列
  • bytearray 是字節(jié)組成的有序的可變序列

編碼與解碼

  • 字符串按照不同的字符集編碼 encode 返回字節(jié)序列 bytes
    • str.encode(encoding='utf-8', errors='strict') --> bytes
  • 字節(jié)序列按照不同的字符集解碼decode返回字符串
    • bytes.decode(encoding="utf-8", errors="strict") --> str
    • bytearray.decode(encoding="utf-8", errors="strict") --> str
In : '李'.encode()
Out: b'\xe6\x9d\x8e'

In : b'\xe6\x9d\x8e'.decode()
Out: '李'

In : b"\x41\x61".decode()
Out: 'Aa'

# bytearray 和 bytes 不一樣的地方在于捏鱼,bytearray 是可變的。
In : str1 = '人生苦短酪耕,Python當歌'

In : b1 = bytearray(str1.encode())

In : b1
Out: bytearray(b'\xe4\xba\xba\xe7\x94\x9f\xe8\x8b\xa6\xe7\x9f\xad\xef\xbc\x8cPython\xe5\xbd\x93\xe6\xad\x8c')

In : type(b1)
Out: bytearray

In : b1.decode()
Out: '人生苦短导梆,Python當歌'

In : b1[:6] = bytearray('生命'.encode())

In : b1
Out: bytearray(b'\xe7\x94\x9f\xe5\x91\xbd\xe8\x8b\xa6\xe7\x9f\xad\xef\xbc\x8cPython\xe5\xbd\x93\xe6\xad\x8c')

In : b1.decode()
Out: '生命苦短,Python當歌'

4.1. ASCII

??ASCII(American Standard Code for Information Interchange迂烁,美國信息交換標準代碼)是基于拉丁字母的一套單字節(jié)編碼系統(tǒng)看尼,編碼范圍從 0 到 127

?? 熟記常用字符的 ASCII 碼_

Char Decimal(十進制) Hex(十六進制)
\t 水平制表符 9 09
\n 換行符 10 0A
\v 垂直制表符 11 0B
\f 換頁符 12 0C
\r 回車符 13 0D
(space) 空格 32 20
0~9 48~57 30~39
A-Z 65~90 41~5A
a-z 97~122 61~7A

4.2. bytes 定義

  • bytes() 空 bytes
  • bytes(int) 指定字節(jié)的 bytes,被 0 填充
  • bytes(iterable_of_ints) --> bytes ( 由[0,255] 的 int 組成的可迭代對象 )
  • bytes(string, encoding[, errors]) --> bytes ( 等價于 string.encode() )
  • bytes(bytes_or_buffer) --> immutable copy of bytes_or_buffer (從一個字節(jié)序列或者 buffer 復制出一個新的不可變的 bytes 對象)
  • 使用 b 前綴定義
    • 只允許基本 ASCII 使用字符形式 b'abc9'
    • 使用 16 進制表示 b"\x41\x61"
In : bytes()
Out: b''

In : bytes(5)
Out: b'\x00\x00\x00\x00\x00'

In : bytes(range(3))
Out: b'\x00\x01\x02'

4.3. bytes 操作

  • 和 str 類型類似盟步,都是不可變類型藏斩,所以方法很多都一樣。只不過 bytes 的方法却盘,輸入是 bytes 狰域,輸出是 bytes
In : b'abcdef'.replace(b'f',b'k')
Out: b'abcdek'

In : b'abc'.find(b'b')
Out: 1
  • 類方法 bytes.fromhex(string):string 必須是 2 個字符的 16 進制的形式,'6162 6a 6b'黄橘,空格將被忽略
In : bytes.fromhex('6162 09 6a 6b00')
Out: b'ab\tjk\x00'
  • hex():返回16進制表示的字符串
In : 'abc'.encode().hex()
Out: '616263'
  • 索引:b'abcdef'[2] 返回該字節(jié)對應的數(shù)兆览,int類型
In : b'abcdef'[2]
Out: 99

4.4. bytearray 定義

  • bytearray() 空 bytearray
  • bytearray(int) 指定字節(jié)的 bytearray,被 0 填充
  • bytearray(iterable_of_ints) --> bytearray ([0,255]的 int 組成的可迭代對象)
  • bytearray(string, encoding[, errors]) --> bytearray (近似 string.encode()塞关,不過返回可變對象)
  • bytearray(bytes_or_buffer) 從一個字節(jié)序列或者 buffer 復制出一個新的可變的 bytearray 對象
  • 注意抬探,b 前綴定義的類型是 bytes 類型
In : bytearray()
Out: bytearray(b'')

In : bytearray(6)
Out: bytearray(b'\x00\x00\x00\x00\x00\x00')

In : bytearray(range(3))
Out: bytearray(b'\x00\x01\x02')

4.5. bytearray 操作

  • 和 bytes 類型的方法相同
In : bytearray(b'abcdef').replace(b'f',b'k')
Out: bytearray(b'abcdek')

In : bytearray(b'abc').find(b'b')
Out: 1
  • 類方法 bytearray.fromhex(string):string 必須是 2 個字符的 16 進制的形式,'6162 6a 6b'帆赢,空格將被忽略
In : bytearray.fromhex('6162 09 6a 6b00')
Out: bytearray(b'ab\tjk\x00')
  • hex():返回 16 進制表示的字符串
In : bytearray('abc'.encode()).hex()
Out: '616263'
  • 索引:bytearray(b'abcdef')[2] 返回該字節(jié)對應的數(shù)小压,int類型
  • append(int) 尾部追加一個元素
  • insert(index, int) 在指定索引位置插入元素
  • extend(iterable_of_ints) 將一個可迭代的整數(shù)集合追加到當前 bytearray
  • pop(index=-1) 從指定索引上移除元素,默認從尾部移除
  • remove(value) 找到第一個 value 移除椰于,找不到拋 ValueError 異常
  • 注意:上述方法若需要使用 int 類型场航,值在 [0, 255]
  • clear() 清空 bytearray
  • reverse() 翻轉(zhuǎn) bytearray,就地修改
In : bytearray(b'abcdef')[2]
Out: 99

In : b = bytearray()

In : b.append(97)

In : b.append(99)

In : b.insert(1,98)

In : b.extend([65,66,67])

In : print(b)
bytearray(b'abcABC')

In : b.remove(66)

In : print(b)
bytearray(b'abcAC')

In : b.pop()
Out: 67

In : print(b)
bytearray(b'abcA')

In : b.reverse()

In : print(b)
bytearray(b'Acba')

In : b.clear()

In : print(b)
bytearray(b'')

4.6. 字節(jié)序

  • 大端模式廉羔,big-endian溉痢;小端模式,little-endian
  • Intel X86 CPU使用小端模式
  • 網(wǎng)絡傳輸更多使用大端模式
  • Windows憋他、Linux使用小端模式
  • Mac OS使用大端模式
  • Java虛擬機是大端模式
LSB_MSB.png

??C2 認為是尾巴孩饼。尾巴放在低地址端,就是小端模式 LSB:Least Significant Bit竹挡,最低有效位镀娶;尾巴放在大地址端,就是大端模式 MSB:Most Significant Bit揪罕,最高有效位梯码。

4.7. int 和 bytes

  • int.from_bytes(bytes, byteorder)
    • 將一個字節(jié)數(shù)組表示成整數(shù)
  • int.to_bytes(length, byteorder)
    • byteorder 字節(jié)序
    • 將一個整數(shù)表達成一個指定長度的字節(jié)數(shù)組
In : i = int.from_bytes(b'abc', 'big')

In : print(i, hex(i))
6382179 0x616263

In : print(i.to_bytes(3, 'big'))
b'abc'

In : b1 = bytearray()

In : b1.append(97)

In : b1
Out: bytearray(b'a')

In : b1.extend(range(98, 100))

In : b1
Out: bytearray(b'abc')

5. 切片

??列表宝泵、元組、字符串轩娶、bytes儿奶、bytearray 都屬于線性結(jié)構(gòu),線性結(jié)構(gòu)其他的特點還有:

  • 可迭代 (for ... in)
  • len() 可以獲取長度
  • 可以通過下標進行訪問(有序)
  • 都可以被切片

??那什么是切片鳄抒?我們說通過索引區(qū)間訪問線性結(jié)構(gòu)一段數(shù)據(jù)的方法就叫做切片闯捎,需要注意的是 切片操作會引起內(nèi)存復制,當對一個過于龐大的線性結(jié)構(gòu)進行切片的時候许溅,請慎重考慮內(nèi)存使用率的問題瓤鼻。切片的表達方式和基本特點有:

  1. 格式:sequence[start:stop:[,step=1]] 返回 [start, stop, step=1)前閉后開 子序列。
  2. 支持負索引贤重。注意方向問題
  3. 當 start 為 0 或 stop 為末尾時茬祷,可以省略。[:] 表示復制原線性結(jié)構(gòu)數(shù)據(jù)并蝗,等效于 copy() 方法(注意當對象為 list 時祭犯,屬于 淺 copy
  4. 超過上界(右邊界),則取到末尾借卧;超過下界(左邊界)盹憎,則取到開頭筛峭。
  5. start 一定要在 stop 的左邊
In : a = 'hello world , My name is Colin'
In : a[2:-1]   
Out: 'llo world , My name is Coli'

In : a[2:]       
Out: 'llo world , My name is Colin'

In : a[-100:]    
Out: 'hello world , My name is Colin'

In : a[10:-100]      # stop 位置在 start 左邊铐刘,所以沒辦法取出,如果實在想要倒著取影晓,那么需要使用負步長
Out: '' 

In : a[10:-100:-1]   # 負步長就可以形成開閉區(qū)間镰吵,注意是從起始位開始按照 step 取的(所以會倒序排列返回) 
Out: 'dlrow olleh'

In : list('My Name is ColinLee')[4:20:2]         # 列表類型,步長為 2
Out: ['a', 'e', 'i', ' ', 'o', 'i', 'L', 'e']

In : tuple('My Name is ColinLee')[4:20:2]        # 元組類型挂签,步長為 2
Out: ('a', 'e', 'i', ' ', 'o', 'i', 'L', 'e')

注意:

  • 切片并不會對原數(shù)據(jù)進行修改疤祭,會返回新的數(shù)據(jù)
  • 如果不是用變量接受,那么就會被標記為待回收
  • 由于是新生成的數(shù)據(jù)饵婆,所以 內(nèi)存地址 和原數(shù)據(jù)內(nèi)存地址 一定不相同勺馆。

5.1. 切片賦值

??既然可以進行切片,那么就會引申出來侨核,是否可以進行切片賦值草穆,什么是切片賦值?它該如何表示搓译?下面以列表例進行說明悲柱。

  • 切片操作寫在等號的左邊
  • 被插入的可迭代對象在等號右邊
In : lst = list(range(10))
In : lst 
Out: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In : lst[1:3]   
Out: [1, 2]

In : lst[1:3] = 1       # 只能針對可迭代對象賦值
---------------------------------------------------------------------------
TypeError  Traceback(most recent call last)
<ipython-input-82-7fef59136c7e> in <module>
----> 1 lst[1:3] = 1

TypeError: can only assign an iterable


In : lst[1:3] = [100,200]

In : lst 
Out: [0, 100, 200, 3, 4, 5, 6, 7, 8, 9]  

In : a
Out: [0, 4]

In : b = list()

In : b[:] = a

In : b
Out: [0, 4]

In : c = a

In : print(id(a), id(b), id(c))
1935299790344 1935291542600 1935299790344

仔細看上面示例代碼會發(fā)現(xiàn)幾個問題:

  1. lst[1:3] = 1 切片賦值會失敗,因為 切片賦值 賦的值必須是 一個可迭代對象
  2. 切片賦值改變了原數(shù)據(jù)
  3. 字符串些己、元組這類不可變的元素豌鸡,無法使用切片賦值

??當我們使用切片時嘿般,它會產(chǎn)生新的內(nèi)存地址來存放生成的新列表,但是如果把切片操作放在賦值操作的左邊時涯冠,那么就相當于引用了原列表的 [start:stop] 的索引炉奴,這種操作是不會生成新的內(nèi)存空間的,換句話來講就是直接對原列表進行了 list.insert 操作.

In : lst 
Out: [0, 100, 200, 3, 4, 5, 6, 7, 8, 9]

In : lst[1:3] = []          # 這種操作相當于在 [1:3) 的位置上進行了 list.remove

In : lst 
Out: [0, 3, 4, 5, 6, 7, 8, 9]

In : lst[1:3] = [100,200]   # 這種操作相當于在 [1:3) 的位置上進行了 list.insert

In : lst 
Out: [0, 100, 200, 5, 6, 7, 8, 9]

??我們知道 list 在進行 insert 和 remove 時的時間復雜度都是 O(n)功偿,在進行切片賦值時的時間復雜度也是一樣盆佣,所以建議不要使用這種方法。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末械荷,一起剝皮案震驚了整個濱河市共耍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吨瞎,老刑警劉巖痹兜,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異颤诀,居然都是意外死亡字旭,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門崖叫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來遗淳,“玉大人,你說我怎么就攤上這事心傀∏担” “怎么了?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵脂男,是天一觀的道長养叛。 經(jīng)常有香客問我,道長宰翅,這世上最難降的妖魔是什么弃甥? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮汁讼,結(jié)果婚禮上淆攻,老公的妹妹穿的比我還像新娘。我一直安慰自己嘿架,他們只是感情好瓶珊,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著眶明,像睡著了一般艰毒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上搜囱,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天丑瞧,我揣著相機與錄音柑土,去河邊找鬼。 笑死绊汹,一個胖子當著我的面吹牛稽屏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播西乖,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼狐榔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了获雕?” 一聲冷哼從身側(cè)響起薄腻,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎届案,沒想到半個月后庵楷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡楣颠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年尽纽,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片童漩。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡弄贿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出矫膨,到底是詐尸還是另有隱情差凹,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布豆拨,位于F島的核電站直奋,受9級特大地震影響能庆,放射性物質(zhì)發(fā)生泄漏施禾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一搁胆、第九天 我趴在偏房一處隱蔽的房頂上張望弥搞。 院中可真熱鬧,春花似錦渠旁、人聲如沸攀例。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽粤铭。三九已至,卻和暖如春杂靶,著一層夾襖步出監(jiān)牢的瞬間梆惯,已是汗流浹背酱鸭。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留垛吗,地道東北人凹髓。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像怯屉,于是被迫代替她去往敵國和親蔚舀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容