重慶分公司,新征程啟航
為企業提供網站建設、域名注冊、服務器等服務
為企業提供網站建設、域名注冊、服務器等服務
迭代器是 23 種設計模式中最常用的一種(之一),在 Python 中隨處可見它的身影,我們經常用到它,但是卻不一定意識到它的存在。在關于迭代器的系列文章中(鏈接見文末),我至少提到了 23 種生成迭代器的方法。有些方法是專門用于生成迭代器的,還有一些方法則是為了解決別的問題而“暗中”使用到迭代器。
成都創新互聯公司2013年至今,是專業互聯網技術服務公司,擁有項目成都做網站、成都網站建設網站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元騰沖做網站,已為上家服務,為騰沖各地企業和個人服務,聯系電話:18980820575
在系統學習迭代器之前,我一直以為 range() 方法也是用于生成迭代器的,現在卻突然發現,它生成的只是可迭代對象,而并不是迭代器! (PS:Python2 中 range() 生成的是列表,本文基于Python3,生成的是可迭代對象)
于是,我有了這樣的疑問:為什么 range() 不生成迭代器呢?在查找答案的過程中,我發現自己對 range 類型的認識存在一些誤區。因此,本文將和大家全面地認識一下 range ,期待與你共同學習進步。
1、range() 是什么?
它的語法:range(start, stop [,step]) ;start 指的是計數起始值,默認是 0;stop 指的是計數結束值,但不包括 stop ;step 是步長,默認為 1,不可以為 0 。range() 方法生成一段左閉右開的整數范圍。
對于 range() 函數,有幾個注意點:(1)它表示的是左閉右開區間;(2)它接收的參數必須是整數,可以是負數,但不能是浮點數等其它類型;(3)它是不可變的序列類型,可以進行判斷元素、查找元素、切片等操作,但不能修改元素;(4)它是可迭代對象,卻不是迭代器。
2、 為什么range()不生產迭代器?
可以獲得迭代器的內置方法很多,例如 zip() 、enumerate()、map()、filter() 和 reversed() 等等,但是像 range() 這樣僅僅得到的是可迭代對象的方法就絕無僅有了(若有反例,歡迎告知)。這就是我存在知識誤區的地方。
在 for-循環 遍歷時,可迭代對象與迭代器的性能是一樣的,即它們都是惰性求值的,在空間復雜度與時間復雜度上并無差異。我曾概括過兩者的差別是“一同兩不同”:相同的是都可惰性迭代,不同的是可迭代對象不支持自遍歷(即next()方法),而迭代器本身不支持切片(即 getitem () 方法)。
雖然有這些差別,但很難得出結論說它們哪個更優。現在微妙之處就在于,為什么給 5 種內置方法都設計了迭代器,偏偏給 range() 方法設計的就是可迭代對象呢?把它們都統一起來,不是更好么?
事實上,Pyhton 為了規范性就干過不少這種事,例如,Python2 中有 range() 和 xrange() 兩種方法,而 Python3 就干掉了其中一種,還用了“李代桃僵”法。為什么不更規范點,令 range() 生成的是迭代器呢?
關于這個問題,我沒找到官方解釋,以下純屬個人觀點 。
zip() 等方法都需要接收確定的可迭代對象的參數,是對它們的一種再加工的過程,因此也希望馬上產出確定的結果來,所以 Python 開發者就設計了這個結果是迭代器。這樣還有一個好處,即當作為參數的可迭代對象發生變化的時候,作為結果的迭代器因為是消耗型的,不會被錯誤地使用。
而 range() 方法就不同了,它接收的參數不是可迭代對象,本身是一種初次加工的過程,所以設計它為可迭代對象,既可以直接使用,也可以用于其它再加工用途。例如,zip() 等方法就完全可以接收 range 類型的參數。
也就是說,range() 方法作為一種初級生產者,它生產的原料本身就有很大用途,早早把它變為迭代器的話,無疑是一種畫蛇添足的行為。
對于這種解讀,你是否覺得有道理呢?歡迎就這個話題與我探討。
3、range 類型是什么?
以上是我對“為什么range()不產生迭代器”的一種解答。順著這個思路,我研究了一下它產生的 range 對象,一研究就發現,這個 range 對象也并不簡單。
首先奇怪的一點就是,它竟然是不可變序列!我從未注意過這一點。雖然說,我從未想過修改 range() 的值,但這一不可修改的特性還是令我驚訝。
翻看文檔,官方是這樣明確劃分的——有三種基本的序列類型:列表、元組和范圍(range)對象。(There are three basic sequence types: lists, tuples, and range objects.)
這我倒一直沒注意,原來 range 類型居然跟列表和元組是一樣地位的基礎序列!我一直記掛著字符串是不可變的序列類型,不曾想,這里還有一位不可變的序列類型呢。
那 range 序列跟其它序列類型有什么差異呢?
普通序列都支持的操作有 12 種。range 序列只支持其中的 10 種,不支持進行加法拼接與乘法重復。
那么問題來了:同樣是不可變序列,為什么字符串和元組就支持上述兩種操作,而偏偏 range 序列不支持呢?雖然不能直接修改不可變序列,但我們可以將它們拷貝到新的序列上進行操作啊,為何 range 對象連這都不支持呢?
且看官方文檔的解釋:
…due to the fact that range objects can only represent sequences that follow a strict pattern and repetition and concatenation will usually violate that pattern.
原因是 range 對象僅僅表示一個遵循著嚴格模式的序列,而重復與拼接通常會破壞這種模式…
問題的關鍵就在于 range 序列的 pattern,仔細想想,其實它表示的就是一個等差數列啊(喵,高中數學知識沒忘…),拼接兩個等差數列,或者重復拼接一個等差數列,想想確實不妥,這就是為啥 range 類型不支持這兩個操作的原因了。由此推論,其它修改動作也會破壞等差數列結構,所以統統不給修改就是了。
4、小結
回顧全文,我得到了兩個偏冷門的結論:range 是可迭代對象而不是迭代器;range 對象是不可變的等差序列。
若單純看結論的話,你也許沒有感觸,或許還會說這沒啥了不得啊。但如果我追問,為什么 range 不是迭代器呢,為什么 range 是不可變序列呢?對這倆問題,你是否還能答出個自圓其說的設計思想呢?(PS:我決定了,若有機會面試別人,我必要問這兩個問題的嘿~)
由于 range 對象這細微而有意思的特性,我覺得這篇文章寫得值了。本文是作為迭代器系列文章的一篇來寫的,所以對于迭代器的基礎知識介紹不多,另外,還有一種特殊的迭代器也值得單獨成文,那就是生成器了。
下面介紹了Python中的6種特殊數據類型:
1.list:列表
是一種有序的數據集合,在列表數據結構中的類型并不唯一
定義形式:L=['Micha',100,True]
輸出整個列表的時候顯示為['Micha',100,True]
輸出單個的數值則為:Micha
a.訪問,直接使用L[0]表示第一個元素或者使用L[-1]表示最后一個數據,以此類推,但是注意訪問不能越界(訪問的序號不能超過元素的總數)。
b.添加新元素:使用L.append(100)直接將100加入列表末尾,或者使用L.insert(0,'paul')將paul插入任意位置。
c.刪除元素:L.pop()刪除最后一個元素,或者L.pop(2)刪除第2個位置的元素。
d.替換元素:直接賦值就可以了L[2]=100
2.tuple:元組
是一種有序的列表,但是其一旦創立完畢就不能夠更改,即不能插入,刪除里面的元素,訪問的方式跟List結構一致。
a.t=()其打印后輸出的形式是()
若t中的數據為一個數字則需要在后面加逗號,以區分普通數字,如t=(1,),打印出(1,)而非1,多元素的話則沒有這個要求。
b.可以在不變的tuple中加入可變的List如t=(‘a’,'b',['A','B'])
3.dict:字典
d = {
'Adam': 95,
'Lisa': 85,
'Bart': 59
}
len()函數可以計算任意集合的大小
其中可以簡單地使用d[key]的形式來查找對應的?value,這和?list很像,不同之處是,list必須使用索引返回對應的元素,而dict使用key,當key不存在的時候,使用該key可能出現錯誤,因此:要避免?KeyError?發生,有兩個辦法:
一是先判斷一下?key?是否存在,用?in?操作符:
if'Paul' in d:
print d['Paul']
如果?'Paul'?不存在,if語句判斷為False,自然不會執行print d['Paul'],從而避免了錯誤。
二是使用dict本身提供的一個?get方法,在Key不存在的時候,返回None:
print d.get('Bart')
59
a.dict中的key不能重復,且dict中的存儲的對應值沒有順序,打印出的東西可能是無序的
b.dict的更新:使用d[‘paul']=72求解
c.dict遍歷:
d = {'Adam': 95, 'Lisa': 85, 'Bart': 59 }
for key in d:
...?????print key
遍歷只能獲得key的值,需要通過key值獲得對應的value
4.set:集合
無序但是所有元素唯一,不重復
a.定義:s = set(['A', 'B', 'C']),查看?set的內容:
print s
set(['A','C', 'B'])
可以用in來判斷是否存在于集合中
b.遍歷
s =set([('Adam', 95), ('Lisa', 85), ('Bart', 59)])
for xin s:
print x[0]+':',x[1]
c.添加元素到集合中
s.add(4)
d.刪除元素
s.remove(4)若該元素不在集合中將會報錯
5.Unicode編碼
Python在后來添加了對Unicode的支持,以Unicode表示的字符串用u'...'表示,比如:
printu'中文'
注意:?不加?u,中文就不能正常顯示中文。
a.轉義形式:?u'中文\n日文\n韓文'
b.輸出多行:
u'''第一行
第二行'''
c.raw+多行的形式:
ur'''Python的Unicode字符串支持"中文",
"日文",
"韓文"等多種語言'''
如果中文字符串在Python環境下遇到?UnicodeDecodeError,這是因為.py文件保存的格式有問題??梢栽诘谝恍刑砑幼⑨?/p>
# -*-coding: utf-8 -*-
目的是告訴Python解釋器,用UTF-8編碼讀取源代碼。然后用Notepad++另存為, 并選擇UTF-8格式保存。
6.raw的作用
如果一個字符串包含很多需要轉義的字符,對每一個字符都進行轉義會很麻煩。為了避免這種情況,我們可以在字符串前面加個前綴?r,表示這是一個“raw”字符串,里面的字符就不需要轉義了。例如:
r'\(~_~)//'
但是r'...'表示法不能表示多行字符串,也不能表示包含'和?"的字符串,如果要表示多行字符串。
quote函數一般用于處理URL鏈接里的特殊字符,比如一些非ASCII列表中的字母。
位置:該函數在Python27中位于urllib模塊下,在Python3中應該是向下移動一級目錄,位于urllib.parse模塊中。
功能:替換字符串string中的一些特殊字符,并使用%xx的方式替換該特殊字符(xx為該字符的(uft-8)十六進制數值)。正常字符ascii字母a-z,數字,還有符號'_.-'是不會被替換的。當然使用函數的第二個參數(默認值為/)可以指定哪些字符也不需要替換。
例子:
urllib.quote('/test')
'/test'
urllib.quote('/test',?safe='')
'%2Ftest'?#?2F?為/的uft-8的hex值。
其他:函數的第一個參數為需要轉換的字符串,格式應該為str或者bytes。
函數的第三個字符為編碼方式。
range 類型表示不可變的數字序列,通常用于在 for 循環中循環指定的次數。
range 構造器的參數必須為整數(可以是內置的 int 或任何實現了 __index__ 特殊方法的對象)。 如果省略 step 參數,其默認值為 1 。 如果省略 start 參數,其默認值為 0 ,如果 step 為零則會引發 ValueError。
如果 step 為正值,確定 range r 內容的公式為 r[i] = start + step*i 其中 i = 0 且 r[i] stop 。
如果 step 為負值,確定 range 內容的公式仍然為 r[i] = start + step*i ,但限制條件改為 i = 0 且 r[i] stop .
如果 r[0] 不符合值的限制條件,則該 range 對象為空。 range 對象確實支持負索引,但是會將其解讀為從正索引所確定的序列的末尾開始索引。
元素絕對值大于 sys.maxsize 的 range 對象是被允許的,但某些特性 (例如 len()) 可能引發 OverflowError。
一些 range 對象的例子:
range 對象實現了 一般 序列的所有操作,但拼接和重復除外(這是由于 range 對象只能表示符合嚴格模式的序列,而重復和拼接通常都會違反這樣的模式)。
start
start 形參的值 (如果該形參未提供則為 0 )
stop
stop 形參的值
step
step 形參的值 (如果該形參未提供則為 1 )
range 類型相比常規 list 或 tuple 的優勢在于一個 range 對象總是占用固定數量的(較?。﹥却妫徽撈渌硎镜姆秶卸啻螅ㄒ驗樗槐4媪? start , stop 和 step 值,并會根據需要計算具體單項或子范圍的值)。
range 對象實現了 collections.abc.Sequence ABC,提供如包含檢測、元素索引查找、切片等特性,并支持負索引
使用 == 和 != 檢測 range 對象是否相等是將其作為序列來比較。 也就是說,如果兩個 range 對象表示相同的值序列就認為它們是相等的。 (請注意比較結果相等的兩個 range 對象可能會具有不同的 start, stop 和 step 屬性,例如 range(0) == range(2, 1, 3) 而 range(0, 3, 2) == range(0, 4, 2) 。)
在 3.2 版更改: 實現 Sequence ABC。 支持切片和負數索引。 使用 int 對象在固定時間內進行成員檢測,而不是逐一迭代所有項。
在 3.3 版更改: 定義 '==' 和 '!=' 以根據 range 對象所定義的值序列來進行比較(而不是根據對象的標識)。
3.3 新版功能: start, stop 和 step 屬性。
1、Python類型操作符和內建函數總結
表4.5列出了所有操作符和內建函數,其中操作符順序是按優先級從高到低排列的。同一種灰度的操作符擁有同樣的優先級。注意在operator模塊中有這些(和絕大多數Python)操作符相應的同功能的函數可供使用。
表4.5 標準類型操作符和內建函數
操作符/函數
描 述
結 果a
字符串表示
``
對象的字符串表示
str
內建函數
cmp(obj1, obj2)
比較兩個對象
int
repr(obj)
對象的字符串表示
str
str(obj)
對象的字符串表示
str
type(obj)
檢測對象的類型
type
值比較
小于
bool
大于
bool
=
小于或等于
bool
=
大于或等于
bool
==
等于
bool
!=
不等于
bool
不等于
bool
對象比較
is
是
bool
is not
不是
bool
布爾操作符
not
邏輯反
bool
and
邏輯與
bool
or
邏輯或
bool
2、Python數值類型操作符和內建函數
一、工廠函數
數值工廠函數總結類(工廠函數) 操作
bool(obj) b 返回obj對象的布爾值,也就是 obj.__nonzero__()方法的返回值。
int(obj, base=10) 返回一個字符串或數值對象的整數表 示, 類似string.atoi();
從Python 1.6起, 引入了可選的進制參數。
long(obj, base=10) 返回一個字符或數據對象的長整數表 示,類似string.atol(),
從Python1.6起, 引入了可選的進制參數 float(obj) ,
返回一個字符串或數據對象的浮點數 表示,類似string.atof()。
complex(str) or返回一個字符串的復數表示,或 者根據給定的實數,
complex(real, imag=0.0) ?。耙粋€可選 的虛數部分)生成一個復數對象。
二、內建函數
1、分類
Python 有五個運算內建函數用于數值運算:
abs(num), coerce(num1,num2), divmod(num1,num2), pow(num1,num2,mod=1)和 round(flt,ndig=0)
其中abs()返回給定參數的絕對值。如果參數是一個復數, 那么就返回math.sqrt(num.real2 + num.imag2).
coerce()是一個數據類型轉換函數,不過它的行為更像一個運算符.數coerce()為程序員提供了不依賴Python 解釋器,而是自定義兩個數值類型轉換的方法。對一種新創建的數值類型來說, 這個特性非常有用.函數coerce()僅返回一個包含類型轉換完畢的兩個數值元素的元組.
divmod()內建函數把除法和取余運算結合起來, 返回一個包含商和余數的元組.對整數來說,它的返回值就是地板除和取余操作的結果.對浮點數來說,返回的商部分是math.floor(num1/num2),對復數來說,商部分是ath.floor((num1/num2).real).
pow()它和雙星號 (**)運算符都可以進行指數運算.不過二者的區別并不僅僅在于一個是運算符,一個是內建函數.在Python 1.5 之前,并沒有 ** 運算符,內建函數pow()還接受第三個可選的參數,一個余數參數.如果有這個參數的, pow() 先進行指數運算,然后將運算結果和第三個參數進行取余運算.這個特性主要用于密碼運算,并且比 pow(x,y) % z 性能更好, 這是因為這個函數的實現類似于C 函數pow(x,y,z).
round()用于對浮點數進行四舍五入運算。它有一個可選的小數位數參數.如果不提供小數位參數, 它返回與第一個參數最接近的整數(但仍然是浮點類型).第二個參數告訴round 函數將結果精確到小數點后指定位數.
2、函數int()/round()/math.floor()它們之間的不同之處:
函數 int()直接截去小數部分.(返回值為整數)
函數 floor() 得到最接近原數但小于原數的整數.(返回值為浮點數)
函數 round() 得到最接近原數的整數.(返回值為浮點數)
3、進制轉換函數:
返回字符串表示的8 進制和16 進制整數,它們分別是內建函數:
oct()和 hex(). oct(255)='0377'/hex(255)='0xff'
函數chr()接受一個單字節整數值(0到255),返回一個字符串(ASCII),其值為對應的字符.chr(97)='a'
函數ord()則相反,它接受一個字符(ASCII 或 Unicode),返回其對應的整數值.ord('A')=65
3、Python字符串函數
(一)標準類型操作符和標準內建函數
1)、標準類型操作符
,,=,=,==,!=,對象值得比較
注:做比較時字符串是按ASCII值的大小來比較的
is 對象身份比較
and,or,not 布爾類型
2)標準內建函數
type(obj)
cmp(obj1,obj2)
str(obj)和repr(obj) 或反引號運算符(``) 可以方便的以字符串的方式獲取對象的
內容、類型、數值屬性等信息。str()函數得到的字符串可讀性好, 而repr()函數得到的字符
串通??梢杂脕碇匦芦@得該對象, 通常情況下 obj == eval(repr(obj)) 這個等式是成立的
isinstance(obj,type) 判斷對象的類型
(二)序列操作
1、序列操作
字符串屬于序列對象,可以使用所有序列的操作和函數
切片 [] [:] [::]
簡單總結:
*索引(S[i])獲取特定偏移的元素。
——第一個元素偏移為0
——(S[0])獲取第一個元素。
——負偏移索引意味著從最后或右邊反向進行計數
——(S[-2])獲取倒數第二個元素(就像S[len(s)-2]一樣
*分片[S[i:j]提取對應的部分作為一個序列
——右邊界不包含在內
——分片的邊界默認為0和序列的長度,如果沒有給出的話S[:]
——(S[1:3])獲取了從偏移為1,直到但不包括偏移為3的元素
——(S[1:])獲取從偏移為1到末尾之間的元素
——(S[:3])獲取從偏移為0直到但不包括偏移為3的元素
——(S[:-1])獲取從偏移為0直到但不包括最后一個元素之間的元素
——(S[:])獲取從偏移為0到末尾之間的元素,這有效地實現了頂層S拷貝
拷貝了一個相同值,但是是不同內存區域的對象。對象字符串這樣不可變的對象不是很有用,但是對于可以實地修改的對象來說很有用。
比如列表。
擴展分片:第三個限制值 【步進】
完整形式:X[I:J:K]:這標識索引X對象的元素,從偏移為I直到J-1,每隔K元素索引一次。第三個限制值,K,默認為1
實例
Python Code
1
2
3
4
5
S='abcdefghijk'
S[1:10]
'bcdefghij'
S[1:10:2]
'bdfhj
也可以使用負數作為步進。
分片表達式
Python Code
1
2
"hello"[::-1]
'olleh'
通過負數步進,兩個邊界的意義實際上進行了反轉。
3、成員操作符 in ,not in
返回布爾值True 或False
可以使用string模塊來判斷輸入字符的合法性,可見成品中的idcheck.py
4、字符串連接
+ 連接字符串 ‘name’+' '+'jin'
字符串格式化 '%s %s' % ('name','jin')
join()方法 ' '.join(('name','jin')) ' '.join(['name','jin'])
5、刪除清空字符串
del aString
aString=''
(三)、序列函數
序列類型函數
len(str) 返回字串的長度
enumerate(iter):接受一個可迭代對象作為參數,返回一個enumerate
max(str)/min(str):max()和min()函數對其他的序列類型可能更有用,但對于string類型它們能很好地運行,返回最大或者最小的字符(按照ASCII 碼值排列),
zip([it0, it1,... itN]) 返回一個列表,其第一個元素是it0,it1,...這些元素的第一個元素組成的一個元組,第二個...,類推.
reversed(seq)c 接受一個序列作為參數,返回一個以逆序訪問的迭代器(PEP 322)
sorted(iter,func=None,key=None,reverse=False) 接受一個可迭代對象作為參數,返回一個有序的列表;可選參數func,key 和reverse 的含義跟list.sort()內建函數的參數含義一樣.
注意:
sorted等需要在原處修改的函數無法用在字符串對象,但可以產生新的對象
sum處理的對象是數字,不能用在字符串
sorted(s)
['a', 'e', 'e', 'g', 'g', 'g', 'o']
(四)只適合于字符串類型的函數
1)raw_input()函數
內建的raw_input()函數使用給定字符串提示用戶輸入并將這個輸入返回,下面是一個使
用raw_input()的例子:
user_input = raw_input("Enter your name: ")
prin user_input
2)str() and unicode()
str()和unicode()函數都是工廠函數,就是說產生所對應的類型的對象.它們接受一個任
意類型的對象,然后創建該對象的可打印的或者Unicode 的字符串表示. 它們和basestring 都
可以作為參數傳給isinstance()函數來判斷一個對象的類型
3)chr(), unichr(), and ord()
chr()函數用一個范圍在range(256)內的(就是0 到255)整數做參數,返回一個對應的字符.unichr()跟它一樣,只不過返回的是Unicode 字符
ord()函數是chr()函數(對于8 位的ASCII 字符串)或unichr()函數(對于Unicode 對象)
的配對函數,它以一個字符(長度為1 的字符串)作為參數,返回對應的ASCII 數值,或者Unicode
數值,如果所給的Unicode 字符超出了你的Python 定義范圍,則會引發一個TypeError 的異常
(五)、只適用于字符串的操作符
1、格式化操作符 %
字符串格式化符號
格式化字符 轉換方式
%c 轉換成字符(ASCII 碼值,或者長度為一的字符串)
%ra 優先用repr()函數進行字符串轉換
%s 優先用str()函數進行字符串轉換
%d / %i 轉成有符號十進制數
%ub 轉成無符號十進制數
%ob 轉成無符號八進制數
%xb/%Xb (Unsigned)轉成無符號十六進制數(x/X 代表轉換后的十六進制字符的大
小寫)
%e/%E 轉成科學計數法(e/E 控制輸出e/E)
%f/%F 轉成浮點數(小數部分自然截斷)
%g/%G %e 和%f/%E 和%F 的簡寫
%% 輸出%
格式化操作符輔助指令
符號 作用
* 定義寬度或者小數點精度
- 用做左對齊
+ 在正數前面顯示加號( + )
sp 在正數前面顯示空格
# 在八進制數前面顯示零('0'),在十六進制前面顯示'0x'或者'0X'(取決于
用的是'x'還是'X')
0 顯示的數字前面填充‘0’而不是默認的空格
% '%%'輸出一個單一的'%'
(var) 映射變量(字典參數)
m.n m 是顯示的最小總寬度,n 是小數點后的位數(如果可用的話)
2、字符串模板: 更簡單的替代品
由于新式的字符串Template 對象的引進使得string 模塊又重新活了過來,Template 對象
有兩個方法,substitute()和safe_substitute().前者更為嚴謹,在key 缺少的情況下它會報一
個KeyError 的異常出來,而后者在缺少key 時,直接原封不動的把字符串顯示出
3、原始字符串操作符( r/R )
字符串抑制轉義r'帶特殊符號的字串'
myfile=open(r'C:\new\text.data','w')
4、Unicode 字符串操作符( u/U )
u'abc' U+0061 U+0062 U+0063
u'\u1234' U+1234
u'abc\u1234\n' U+0061 U+0062 U+0063 U+1234 U+0012
(六)字符串對象的方法:
1、刪減
T2.lstrip() 移除字符串前面字符(默認空格),返回字符串
T2.rstrip() 移除字符串后面字符(默認空格),返回字符串
T2.strip() 移除字符串前后面空格,返回字符串 默認空格,可以其他字符 S.strip('"')
2、切割
partition(sep),
rpartition(sep),
splitlines([keepends]),#把S按照行分割符分為一個list,keepends是一個bool值,如果為真每行后而會保留行分割符
split([sep [,maxsplit]]),#以sep為分隔符,把S分成一個list。maxsplit表示分割的次數。默認的分割符為空白字符
rsplit([sep[,maxsplit]]) #從右到左切割
備注:
partition()函數族是2.5版本新增的方法。它接受一個字符串參數,并返回一個3個元素的 tuple 對象。
如果sep沒出現在母串中,返回值是 (sep, ‘’, ‘’);
否則,返回值的第一個元素是 sep 左端的部分,第二個元素是 sep 自身,第三個元素是 sep 右端的部分。
S.partition(';')
('', ';', ' generated by /sbin/dhclient-script\nnameserver 172.16.10.171\nnameserver 8.8.8.8\nnameserver 172.16.0.2\nnameserver 178.79.131.110\nnameserver 202.96.199.133\n')
參數 maxsplit 是分切的次數,即最大的分切次數,所以返回值最多有 maxsplit+1 個元素。
s.split() 和 s.split(‘ ‘)的返回值不盡相同
' hello world!'.split()
['hello', 'world!']
' hello world!'.split(' ')
['', '', 'hello', '', '', 'world!']
S.split('\n',3)
['; generated by /sbin/dhclient-script', 'nameserver 172.16.10.171', 'nameserver 8.8.8.8', 'nameserver 172.16.0.2\nnameserver 178.79.131.110\nnameserver 202.96.199.133\n']
超過最大切割個數后面的全部為一個元素
按行切割
S
'; generated by /sbin/dhclient-script\nnameserver 172.16.10.171\nnameserver 8.8.8.8\nnameserver 172.16.0.2\nnameserver 178.79.131.110\nnameserver 202.96.199.133\n'
S.splitlines()
['; generated by /sbin/dhclient-script', 'nameserver 172.16.10.171', 'nameserver 8.8.8.8', 'nameserver 172.16.0.2', 'nameserver 178.79.131.110', 'nameserver 202.96.199.133']
產生差異的原因在于當忽略 sep 參數或sep參數為 None 時與明確給 sep 賦予字符串值時 split() 采用兩種不同的算法。
對于前者,split() 先去除字符串兩端的空白符,然后以任意長度的空白符串作為界定符分切字符串
即連續的空白符串被當作單一的空白符看待;
對于后者則認為兩個連續的 sep 之間存在一個空字符串。因此對于空字符串(或空白符串),它們的返回值也是不同的:
''.split()
[]
''.split(' ')
['']
3、變形
lower(),#全部小寫
upper(),#全部小寫
capitalize(),#首字母大寫
swapcase(),#大小寫交換
title()#每個單詞第一個大寫,其他小寫
備注
因為title() 函數并不去除字符串兩端的空白符也不會把連續的空白符替換為一個空格,
所以建議使用string 模塊中的capwords(s)函數,它能夠去除兩端的空白符,再將連續的空白符用一個空格代替。
Python Code
1
2
3
4
' hello world!'.title()
' Hello World!'
string.capwords(' hello world!')
'Hello World!'
4、連接
join(seq)
join() 函數的高效率(相對于循環相加而言),使它成為最值得關注的字符串方法之一。
它的功用是將可迭代的字符串序列連接成一條長字符串,如:
conf = {'host':'127.0.0.1',
... 'db':'spam',
... 'user':'sa',
... 'passwd':'eggs'}
';'.join("%s=%s"%(k, v) for k, v in conf.iteritems())
'passswd=eggs;db=spam;user=sa;host=127.0.0.1'
S=''.join(T) #使用空字符串分割把字符列表轉換為字符串
5、查找
count( sub[, start[, end]]),#計算substr在S中出現的次數
find( sub[, start[, end]]),#返回S中出現sub的第一個字母的標號,如果S中沒有sub則返回-1。start和end作用就相當于在S[start:end]中搜索
index( substr[, start[, end]]),#與find()相同,只是在S中沒有substr時,會返回一個運行時錯誤
rfind( sub[, start[,end]]),#返回S中最后出現的substr的第一個字母的標號,如果S中沒有substr則返回-1,也就是說從右邊算起的第一次出現的substr的首字母標號
rindex( sub[, start[, end]])
T2.find('ie') 字符串方法調用:搜索
find()----找到的第一個符合字符的index
rfind()-----找到最后一個符合的字符的index
備注:
find()函數族找不到時返回-1,index()函數族則拋出ValueError異常。
另,也可以用 in 和 not in 操作符來判斷字符串中是否存在某個模板
6、替換
replace(old, new[,count]),#把S中的oldstar替換為newstr,count為替換次數。這是替換的通用形式,還有一些函數進行特殊字符的替換
translate(table[,deletechars]) #使用上面的函數產后的翻譯表,把S進行翻譯,并把deletechars中有的字符刪掉
備注:
replace()函數的 count 參數用以指定最大替換次數
translate() 的參數 table 可以由 string.maketrans(frm, to) 生成
translate() 對 unicode 對象的支持并不完備,建議不要使用
7、判定
isalnum(),#是否全是字母和數字,并至少有一個字符
isalpha(),是否全是字母,并至少有一個字符
isdigit(),是否全是數字,并至少有一個字符 ,如果是全數字返回True,否則返回False
islower(),#S中的字母是否全是小寫
isupper(),#S中的字母是否是大寫
isspace(),#是否全是空白字符,并至少有一個字符
istitle(),S是否是首字母大寫的
startswith(prefix[, start[, end]]), #是否以prefix開頭
endswith(suffix[,start[, end]]),#以suffix結尾
備注:
這些函數都比較簡單,顧名知義。需要注意的是*with()函數族可以接受可選的 start, end 參數,善加利用,可以優化性能。
另,自 Py2.5 版本起,*with() 函數族的 prefix 參數可以接受 tuple 類型的實參,當實參中的某人元素能夠匹配,即返回 True。
8、填充
字符串在輸出時的對齊:
center(width[, fillchar]), 字符串中間對齊
ljust(width[, fillchar]), 字符串左對齊,不足部分用fillchar填充,默認的為空格
rjust(width[, fillchar]), 字符串右對齊,不足部分用fillchar填充,默認的為空格
zfill(width), 把字符串變成width長,并在右對齊,不足部分用0補足
expandtabs([tabsize])把字符串中的制表符(tab)轉換為適當數量的空格。
fillchar 參數指定了用以填充的字符,默認為空格
zfill的z為zero的縮寫,顧名思義,是以字符0進行填充,用于數值輸出
expandtabs()的tabsize 參數默認為8。它的功能是把字符串中的制表符(tab)轉換為適當數量的空格。
9、編碼
encode([encoding[,errors]]),
decode([encoding[,errors]])
這是一對互逆操作的方法,用以編碼和解碼字符串。因為str是平臺相關的,它使用的內碼依賴于操作系統環境,
而unicode是平臺無關的,是Python內部的字符串存儲
Python中如何實現運算符的重載,即實現例如a+b這樣的運算符操作呢?
在C++中可以使用 operator 關鍵字實現運算符的重載。但是在Python中沒有類似這樣的關鍵字,所以要實現運算符的重載,就要用到Python的魔法函數。Python魔法函數是以雙下劃線開頭,雙下劃線結尾的一組函數。我們在類定義中最常用到的 __init__ 函數就是這樣一個魔法函數,它在創建類對象時被自動調用。
下面我們來看個簡單的例子。
上述代碼示例了幾個魔法函數的用法。 __add__ 函數對應了二元運算符+,當執行a+b語句時,python就會自動調用a. add (b)。 對于上述例子中的v1+v2+v3,則相當于調用了(v1. add(v2)). add(v3)。
代碼中還有一個在Python類定義經常使用的 __str__ 函數,當使用 str() 時會被調用。print函數對傳入的參數都調用了str()將其轉換成易讀的字符串形式,便于打印輸出,因而會調用類定義的__str__函數打出自定義的字符串。
代碼中還有一個特殊的 __call__ 函數,該函數在將對象采用函數調用方式使用時被調用, 例如v1()相當于v1. call ()。
以上就是魔法函數的基本使用方法。常見的魔法函數我們可以使用 dir() 函數來查看。
輸出結果為:
上述結果中形式為‘__函數名__’的函數為魔法函數,注意有些對象也是這種形式,例如__class__, __module__等, 這些不是魔法函數。具體的魔法函數說明可以參考Python官方說明文檔。
以上代碼在Python3.6運行通過.