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 提供了 find
、rfind
喧务、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é)尾位來進行匹配,它們是 startswith
和 endswith
劫拢。
# 在指定的區(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)
- 占位符:使用
% 和格式字符串
組成降宅,例如%s
骂远,%d
等。s 調(diào)用str()
腰根,r 會調(diào)用repr()
激才。所有對象都可以被這兩個轉(zhuǎn)換 - 占位符中還可以插入修飾字符,例如
%03d
表示打印 3 個位置额嘿,不夠的話瘸恼,前面補 0 -
format % value
格式字符串和被格式字符串之間使用 % 分割 -
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 非常靈活芬为,下面是基本使用方法說明:
-
args
是可變位置參數(shù),是一個元組 -
kwargs
是可變關鍵字參數(shù)蟀悦,是一個字典 -
花括號
表示占位符
-
{}
表示按照順序匹配位置參數(shù)
媚朦,{n}
表示取位置參數(shù)中索引為 n 的值
-
{xxx}
表示在關鍵字參數(shù)中搜索名稱一致的值,kwargs
必須放在可變位置參數(shù)的后面
-
{{}}
表示打印花括號
# 按照位置格式化熬芜,第一個元素給第一個括號,第二個元素給第二個括號
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 引入兩個新類型:
- bytes:不可變字節(jié)序列
- 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虛擬機是大端模式
??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)存使用率的問題
瓤鼻。切片的表達方式和基本特點有:
- 格式:
sequence[start:stop:[,step=1]]
返回[start, stop, step=1)
的前閉后開
子序列。 - 支持負索引贤重。注意方向問題
- 當 start 為 0 或 stop 為末尾時茬祷,可以省略。
[:]
表示復制原線性結(jié)構(gòu)數(shù)據(jù)并蝗,等效于 copy() 方法(注意當對象為 list 時祭犯,屬于淺 copy
) - 超過上界(右邊界),則取到末尾借卧;超過下界(左邊界)盹憎,則取到開頭筛峭。
- 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)幾個問題:
- lst[1:3] = 1 切片賦值會失敗,因為
切片賦值
賦的值必須是一個可迭代對象
- 切片賦值改變了原數(shù)據(jù)
- 字符串些己、元組這類不可變的元素豌鸡,無法使用切片賦值
??當我們使用切片時嘿般,它會產(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)功偿,在進行切片賦值時的時間復雜度也是一樣盆佣,所以建議不要使用這種方法。