6.序列:字元串,清單和元祖
6.1序列
6.1.1标準類型操作符
6.1.2序列類型操作符
成員關系操作符(in,not in)
判斷一個元素是否屬于一個序列
字元串判斷一個字元是否屬于這個字元串
元祖判斷一個對象是否屬于該對象序列
in/not in 操作符傳回值為True/False
例: obj [not] in sequence
序列類型操作符
序列類型符作用
seq[ind]獲得下标為ind的元素
seq[ind1:ind2]獲得下标從ind1到ind2間的元素集合
seq * expr序列重複seq1和seq2
seq1 + seq2連續序列seq1和seq2
obj in seq判斷obj元素是否包含在seq中
obj not in seq判斷obj元素是否不包含在seq中
連接配接操作符(+)
将兩個相同類型的序列做連接配接
seq1 + seq2
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> a + b
[1, 2, 3, 4, 5, 6]
推薦extend()做合并連接配接
>>> a =[1,2,3]
>>> b =[4,5,6]
>>> a.extend(b)
>>> a
>>> print a.extend(b)
None
重複操作符(*)
用來拷貝多份序列
sequence * copies_int
copies_int必須是整數
>>> a * 8
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]
切片操作符([],[:],[::])
sequence[index]
sequence是序列名稱,index是想要通路的元素對應偏移量,偏移量可以是正值,範圍從0到便宜最大值(比序列長度少1),用len()函數可以得到序列長度,範圍在 0<= index <=len(sequence)-1
負索引範圍是-1到序列的負長度, -len(sequence),-len(sequence)<=index<=-1,正負索引差別在于正索引以序列的開始為起點,負索引以序列的結束為起點
直接通路序列的一個一個元素
>>> print('a','b','c')[1]
b
一次得到多個元素
seq[start_index:end_index]
得到從起始索引到結束索引(不包括結束索引的對應元素)之間的一片元素
如果沒有提供或用None作為索引值,切片操作會從最開始處開始,或者到最結尾處結束
>>> seq = ['a','b','c','d','e']
>>> seq[1:2]
['b']
>>> seq[0:2]
['a', 'b']
>>> seq[0:1]
['a']
>>> seq[:1]
>>> seq[:]
['a', 'b', 'c', 'd', 'e']
>>> seq[1:]
['b', 'c', 'd', 'e']
用步長索引進行擴充的切片操作
>>> s= 'abcdefg'
>>> s[::-1]
'gfedcba'
>>> s[::2]
'aceg'
>>> s[::1]
'abcdefg'
>>> ('a','b','c')[-100:100]
('a', 'b', 'c')
每次都把位于最後的一個字元去掉:
>>> s = 'abcde'
>>> i = -1
>>> for i in range(-1,-len(s), -1):
... print s[:i]
...
abcd
abc
ab
a
但第一次疊代的時候如何顯示整個字元串?
我們用NONE作為索引值
>>> for i in [None] + range(-1,-len(s),-1):
... print s[:i]
abcde
6.1.3 内建函數(BIFs)
類型函數
序列類型轉換工廠函數
函數含義
list(iter)把可疊代對象轉換成清單
str(obj)把obj對象轉換成字元串(對象的字元串表示法)
unicode(obj)把對象轉換成Unicode字元串(使用預設編碼)
basestring()抽象工廠函數,其作用僅僅是為了str和unicode函數提供父類,是以不能被執行個體化,也不能被調用
tuple(iter)把一個可疊代對象轉換成一個元祖對象
Operational
序列類型可用内建參數
函數名功能
enumerate(iter)接受一個可疊代對象作為參數,傳回一個enumerate對象,該對象生成由iter每個元素的index值和item值組成的元祖
len(seq)傳回seq的長度
max(iter,key=None) or
max(arg0,arg1...,key=None) 傳回iter或(arg0,arg1...)中最大值,如果指定了key,這個 key必須是一個可以傳給sort()方法的回調函數
max(arg0,arg1...,key=None) 同上
reversed(seq) 接受一個序列作為參數,傳回一個逆序通路的疊代器
sorted(iter,
func=None,
key=None,
reverse=False) 接受一個可疊代對象作為參數,傳回一個有序的清單
sum(seq,init=0) 傳回seq和可選參數int的綜合,效果等同reduce (operator,add,seq,int)
zip([it0,it1,...itN]) 傳回一個清單,其第一個元素是it0,it1,...這些元素的第一個 元素組成的一個元祖,第二個...類推
6.2 字元串
字元串的建立和指派
>>> aString = 'Hello World!'
>>> another = "Python is cool!"
>>> print aString
Hello World!
>>> another
'Python is cool!'
>>> s = str(range(4))
>>> s
'[0, 1, 2, 3]'
通路字元串的值
>>> aString[0]
'H'
>>> aString[1:5]
'ello'
>>> aString[6:]
'World!'
改變字元串
>>> aString = aString[:6] + 'Python'
>>> aString
'Hello Python'
>>> aString = 'different string altogether'
'different string altogether'
删除字元和字元串
>>> aString = aString[:3] + aString[4:]
'Helo World!'
>>> aString = ''
''
>>> del aString
>>> aString
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'aString' is not defined
>>>
6.3 字元串和操作符
6.3.1 标準類型操作符
>>> str1 = 'abc'
>>> str2 = 'lmn'
>>> str3 = 'xyz'
>>> str1 < str2
True
>>> str1 != str2
>>> str1 < str3 and str2 == 'zyz'
False
6.3.2 序列操作符
切片([]和[:])
正向索引
反向索引
預設索引
字元串'abcd',正索引和負索引
正索引0 1 2 3
字元串a b c d
負索引-4 -3 -2 -1
正向索引時,索引開始于0,結束于總長度-1
final_index = len(aString) - 1 = 4 - 1 = 3
'a'
>>> aString[1:3]
'bc'
>>> aString[2:4]
'cd'
>>> aString[4]
IndexError: string index out of range
反向索引,從-1開始,向字元串開始的方向技術,到字元串長度的負數為索引的結束
final_index = -len(aString) = -4
>>> aString[-1]
'd'
>>> aString[-3:-1]
>>> aString[-4]
如果開始索引或結束索引沒有被指定,則分别以字元串的第一個和最後一個索引值為預設值
>>> aString[2:]
>>> aString[1:]
'bcd'
>>> aString[:-1]
'abc'
>>> aString[:]
'abcd'
成員操作符(in,not in)
>>> 'bc' in 'abcd'
>>> 'n' in 'abcd'
>>> 'nm' not in 'abcd'
string子產品預定義的字元串:
>>> import string
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'
>>> string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'
辨別符檢查(idcheck.py)
# vi idcheck.py
------------------------------------
#!/usr/bin/env python
import string
alphas = string.letters + '_'
nums = string.digits
all_letters = alphas + nums
print 'Welcome to the Identifier Checker v1.0'
print 'Testees must be at least 2 chars long.'
while True:
myInput = raw_input('Identifier to test? ')
if len(myInput) > 1:
if myInput[0] not in alphas:
print 'invalid: first symbol must be alphabetic'
else:
for otherChar in myInput[1:]:
if otherChar not in all_letters:
print 'invalid: remaining symbols must be alphanumeric'
break
else:
print "okay as an identifier"
break
else:
print 'Testees must be at least 2 chars long.'
連接配接符( + )
通過連接配接轉換符來從原有字元串獲得一個新的字元串
>>> s = 'abcdefghighlmn'
>>> import string
>>> string.upper(s[:3] + s[10])
'ABCH'
推薦使用join()方法把它們連接配接在一起
>>> '%s %s' %('Spanish','Inquisition')
'Spanish Inquisition'
>>> s = ' '.join(('Spanish','Inquisition','Made Easy'))
'Spanish Inquisition Made Easy'
>>> ('%s%s' % (s[:3],s[10])).upper()
'SPAQ'
編譯時字元串連接配接
>>> foo = "Hello"'world!'
>>> foo
'Helloworld!'
>>> 'http://''localhost'':8000''/cgi-bin/friends2.py'
'http://localhost:8000/cgi-bin/friends2.py'
普通字元串轉化為Unicode字元串
>>> 'Hello' + u' ' + 'World' + u'!'
u'Hello World!'
重複操作符( * )
建立一個包含原有字元串多個拷貝的新串
>>> 'Ni!' * 3
'Ni!Ni!Ni!'
>>> '*'*40
'****************************************'
>>> print '-' * 20, 'Hello World!', '-' * 20
-------------------- Hello World! --------------------
>>> who = 'knights'
>>> who * 2
'knightsknights'
>>> who
'knights'
注:原變量不會被修改
6.4 隻适用于字元串的操作符
6.4.1 格式化操作符(%)
字元串格式化符号
格式化字元轉換方式
%c轉換成字元(ASCII碼值,或者長度為一的字元串)
%r優先用repr()函數進行字元串轉換
%s優先用str()函數進行字元串轉換
%d / %i轉換成有符号的十進制數
%u轉換成無符号的十進制數
%o轉換成無符号的八進制數
%x/%X轉成無符号十六進制數(x/X代表轉換後的十六進制字元的大小寫)
%e/%E轉換成科學技術法
%f/%F轉換成浮點數
%g/%G%e和%f/%E和%F的簡寫
%%輸出%
格式化操作符輔助指令
符号作用
*定義寬度或者小數點精度
-用做左對齊
+在正數前面顯示加号( + )
<sp>在正數前面顯示空格
#在八進制數前面顯示零('0'),在十六進制前面顯示'0x'或者'OX'
0顯示數字前面填充 '0'而不是預設的空格
%'%%'輸出一個單一的'%'
(var)映射變量(字典參數)
m,nm是顯示的最小總寬度,n是小數點後的位數(如果可用的話)
十六進制輸出:
>>> "%x" % 108
'6c'
>>> "%X" % 108
'6C'
>>> "%#X" % 108
'0X6C'
>>> "%#x" % 108
'0x6c'
浮點數和科學技術法形式輸出:
>>> '%f' % 1234.567890
'1234.567890'
>>> '%.2f' % 1234.567890
'1234.57'
>>> '%E' % 1234.567890
'1.234568E+03'
>>> '%e' % 1234.567890
'1.234568e+03'
>>> '%g' % 1234.567890
>>> '%G' % 1234.567890
>>> '%e' % (1111111111111111L)
'1.111111e+15'
整數和字元串輸出:
>>> "we are at %d%%" % 100
'we are at 100%'
>>> 'Your host is: %s' % 'earth'
'Your host is: earth'
>>> "%+d" % 4
'+4'
>>> "%+d" % -4
'-4'
>>> 'Host: %s Port: %d' % ('mars',80)
'Host: mars Port: 80'
>>> num = 123
>>> 'dec: %d/oct: %#o/hex: %#X' %(num,num,num)
'dec: 123/oct: 0173/hex: 0X7B'
>>> "MM/DD/YY = %02d/%02d/%d" % (2, 15, 67)
'MM/DD/YY = 02/15/67'
>>> w, p = 'Web','page'
>>> 'http://xxx.yyy.zzz/%s/%s.html' % (w, p)
'http://xxx.yyy.zzz/Web/page.html'
上面的例子都是使用的元祖類型的參數作轉換,下面我們将把字典類型的參數提供給格式化操作符
>>> 'There are %(howmany)d %(lang)s Quotation Symbols' % \
... {'lang':'Python','howmany': 3}
'There are 3 Python Quotation Symbols'
6.4.2 字元串模闆:更簡單的替代品
新式的字元串模闆的優勢是不用去記住所有的相關細節,而是像現在的shell風格的腳本語言裡面那樣使用美元符号($)
>>> from string import Template
>>> s = Template('There are ${howmany} ${lang} Quotation Symbols')
>>> print s.substitute(lang = 'Python',howmany = 3)
There are 3 Python Quotation Symbols
>>> print s.substitute(lang = 'Python')
File "/usr/lib/python2.7/string.py", line 172, in substitute
return self.pattern.sub(convert, self.template)
File "/usr/lib/python2.7/string.py", line 162, in convert
val = mapping[named]
KeyError: 'howmany'
>>> print s.safe_substitute(lang = 'Python')
There are ${howmany} Python Quotation Symbols
6.4.3 原始字元串操作符(r/R)
>>> '\n'
'\n'
>>> r'\n'
'\\n'
>>> print r'\n'
\n
我們要找一對原始的\n字元而不是換行,我們使用一個簡單的正規表達式,作用是查找用來表示空白字元的反斜線-字元對(backslash-character pairs)
>>> import re
>>> m = re.search('\\[rtfvn]',r'Hello World!\n')
>>> if m is not None: m.group()
>>> m = re.search(r'\\[rtfvn]',r'Hello World!\n')
>>> if m is not None: m.group()
6.4.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
6.5 内建函數
6.5.1 标準類型函數
cmp()
同比較操作符一樣,内建的cmp()函數也根據字元串的ASCII碼值進行比較
Type "help", "copyright", "credits" or "license" for more information.
>>> str = 'abc'
>>> str3 = 'xyz'
>>> cmp(str1,str2)
-1
>>> cmp(str3,str1)
1
>>> cmp(str2,'lmn')
6.5.2 序列類型函數
len()
>>> len(str)
3
>>> len('Hello World!')
12
max() and min()
>>> max(str2)
'n'
>>> min(str3)
'x'
>>> min('ab12cd')
'1'
>>> min('AB12CD')
>>> min('ABabCDcd')
'A'
enmerate()
>>> s = 'foobar'
>>> for i,t in enumerate(s):
... print i,t
0 f
1 o
2 o
3 b
4 a
5 r
zip()
>>> zip(s, t)
[('f', 'o'), ('o', 'b'), ('a', 'r')]
6.5.3 字元串類型函數
raw_input()
>>> user_input = raw_input("Enter your name: ")
Enter your name: John Doe
>>> user_input
'John Doe'
>>> len(user_input)
8
str() and unicode()
>>> not isinstance('foo',unicode)
>>> isinstance(u'',basestring)
>>> not isinstance('foo',basestring)
chr(),unichr(),and ord()
chr()用一個(0,255)整數做參數,傳回一個對應字元,unichr()跟它一樣,傳回的是Unicode字元
ord()以一個字元長度為1的字元串作為參數,傳回對應的ASCIIshu
>>> chr(65)
>>> ord('a')
97
>>> unichr(12345)
u'\u3039'
>>> chr(12345)
ValueError: chr() arg not in range(256)
>>> ord(u'\ufffff')
TypeError: ord() expected a character, but string of length 2 found
>>> ord(u'\u2345')
9029
6.6 字元串内建函數
方法描述
string.capitalize()把字元串的第一個字元大寫
string.center(width)傳回一個原字元串居中,并使用空格填充至長度width的新字元串
string.count(str,beg=0,
end=len(string))傳回str在string裡面出現的次數,如果beg或者end指定則傳回制定範圍内str出現的次數
string.decode(encoding='UTF-8',
errors="strict")以encoding指定的編碼格式解碼string
string.encode(encoding='UTF-8',
errors="strict")以encoding指定的編碼格式編碼string
string.endswith(obj,beg=0,
end=len(string))檢查字元串是否以obj結束
string.expandtabs(tabsize=8)把字元串string中的tab轉換成空格 預設空格數tabsize為8
string.find(str,beg=0,end=len(string))檢查str是否包含在string中,如果beg和
end指定範圍,是傳回開始的索引值,否傳回-1
string.index(str,beg=0,end=len(string))跟find()方法一樣,差別在str不在string會報一個異常
string.isalnum()如果string至少有一個字元并且所有字元都是字母或數字傳回True否則false
string.isalpha()如果string至少有一個字元并且所有字元都是字母傳回True否則false
string.isdecimal()如果string隻包含十進制數傳回True,否則False
string.isdigit()如果string隻包含數字傳回True,否則False
string.islower()如果string中包含至少一個區分大小寫的字元,并且這些字元都是小寫,則傳回True,否則False
string.isnumeric()如果string中隻包含數字字元,則傳回True,否則False
string.isspace()如果string中隻包含空格,則傳回True,否則False
string.istitle()如果string是标題化(見title()),則傳回True,否則False
string.isupper()如果string中包含至少一個區分大小寫的字元,并且這些字元都是大寫,則傳回True,否則False
string.join(seq)将seq中所有元素合并為一個新字元串
string.1just(width)傳回一個原字元串左對齊,并使用空格填充至長度width的新字元串
string.lower()轉換string中所有大寫字元為小寫
string.partition(str)有點像find()和split()的結合體,從str出現的第一個位置起,把字元串string分成一個3元素的元祖
string.replace(str1,str2,
num=string.count(str1))把string中的str1替換成str2,如果num指定,則替換不超過num次
string.rfind(str,beg=0,end=len(string))類似find(),不過是從右邊開始查找
string.rindex(str,beg=0,end=len(string))類似index(),不過是從右邊開始查找
string.rjust(width)傳回一個原字元串右對齊,并使用空格填充至長度width的新字元串
string.rpartition(str)類似partition(),不過是從右邊開始查找
string.rstrip()删除string字元串末尾空格
string.split(str="",num=string.count(str))以str為分隔符切片string,如果num有 指定值,則僅分隔num個子字元串
string.splitlines(num=string.count("\n")) 按照行分隔,傳回一個包含各行作為元 素的清單,如果num指定僅切片num個行
string.startswith(obj,beg=0,end=len(string)) 檢查字元串是否是以obj開頭,是則 傳回True,否則傳回False,如果beg 和end指定值,則在指定範圍内
string.strip([obj])在string商執行lstrip()和rstrip()
string.swapcase()翻轉string中的大小寫
string.title傳回标題化的string,就是說所有單詞都是以答謝開始,其餘字母均小寫
string.translate(str,del="")根據str給出的表轉換string的字元,要過濾掉的字元放到del參數中
string.upper()轉換string中的小寫字母為大寫
string.zfill(width)傳回長度位width的字元串,原字元串string右對齊,前面填充0
例:
>>> quest = "what is your favorite color?"
>>> quest.capitalize()
'What is your favorite color?'
>>> quest.center(40)
' what is your favorite color? '
>>> quest.count('or')
2
>>> quest.endswith('blue')
>>> quest.endswith('color?')
>>> quest.find('or',30)
>>> quest.find('or',22)
25
>>> quest.find('or',10)
16
>>> ':'.join(quest.split())
'what:is:your:favorite:color?'
>>> quest.replace('favorite color','quest')
'what is your quest?'
>>> quest.upper()
'WHAT IS YOUR FAVORITE COLOR?'
6.7.1 特殊字元串和控制字元
反斜杠開頭的轉義字元
/X八進制十進制十六進制字元說明
\0000 0 0x00NUL空字元Nul
\a000 7 0x07BEL響鈴字元
\b010 8 0x08BS倒退
\t011 9 0x09HT橫向制表符
\n012 10 0x0ALF換行
\v013 11 0x0BVT縱向制表符
\f014 12 0x0CFF換頁
\r015 13 0x0DCR回車
\e033 14 0x1BESC轉義
\"042 15 0x22"雙引号
\'017 16 0x27'單引号
\\134 17 0x5C\反斜杠
6.7.2 三引号
>>> hi = '''hi there'''
>>> hi
'hi there'
>>> print hi
hi there
6.7.3 字元串不變性
>>> 'abc' + 'def'
'abcdef'
>>> s = 'abc'
>>> s = s + 'def'
>>> id(s)
140396947277704
>>> s += 'def'
140396946511408
對字元串的一個或多個字元做修改,需要用現在的字元串子串來建構一個新串,然後把這個新串賦給原來的變量:
>>> s = '%sC%s' % (s[0:2],s[3:])
'abCdef'
>>> s[0:3] + 'DEF'
'abCDEF'
6.8.1 術語
6.8.2 Unicode
Unicode 是用來支援多語言的工具
6.8.3 怎麼用Unicode?
>>> "Hello World"# ASCII string
'Hello World'
>>> u"Hello World"# Unicode string
u'Hello World'
6.8.4 Codecs是什麼?
codec 是C0der/DECoder的首字母組合,它定義了文本跟二進制的轉換方式
6.8.5 編碼解碼
例: 簡單Unicode字元串例子(uniFile.py)
# vi uniFule.py
------------------------------
'''
An example of reading and writing Unicode strings:Writes
a Unicode string to a file in utf-8 and reads it back in.
CODEC = 'utf-8'
FILE = 'unicode.txt'
hello_out = u"Hello world\n"
bytes_out = hello_out.encode(CODEC)
f = open(FILE,"w")
f.write(bytes_out)
f.close()
f = open(FILE,"r")
bytes_in = f.read()
hello_in = bytes_in.decode(CODEC)
print hello_in,
6.8.6 把Unicode應用到實際應用中
確定以下方面對Unicode的支援
資料庫伺服器(MySQL,PostgreSQL,SQL Server等等)
資料庫擴充卡(MySQLdb等等)
Web開發架構(mod_python,cgi,Zope,Plane,Django等等)
6.8.7 從現實中得來的教訓
6.8.8 Python的Unicode支援
内建的unicode()
呢見的decode()/encode()方法
Unicode類型
Unicode序數
強制類型轉換
異常
标準編碼
RE 引擎對Unicode的支援
正規表達式引擎需要Unicode支援,詳見6.9節的re子產品
表6.0 常用 Unicode編輯碼
編碼描述
utf-8變量長度為8的編碼(預設編碼)
utf-16變量長度位16的編碼(大/小端)
utf-16-le小端UTF-16編碼
utf-16-be大端UTF-16編碼
ascii7-bit 7位ASCII碼表
iso-8859-1ISO 8859-1(Latin-1)碼表
unicode-escape
raw-unicode-escape
nativePython用的内部格式
字元串格式化操作符
>>> u"%s %s" % (u"abc","abc")
u'abc abc'
6.9 相關子產品
Python标準庫裡面與字元串有關的主要子產品
子產品描述
string字元串操作相關函數和工具,比如Template類
re正規表達式:強大的字元串模式比對子產品
struct字元串和二進制之間的轉換
c/StringIO字元串緩沖對象,操作方法類似file對象
base64Base 16,32,64資料編解碼
codecs解碼器注冊和基類
crypt進行單方面加密
difflib找出序列間的不同
hashlib多種不同安全雜湊演算法和資訊摘要算法的API
hmaHMAC資訊鑒權算法的 Python實作
md5RSA的MD%資訊摘要鑒權
rotor提供多平台的加解密服務
shaNIAT的安全雜湊演算法SHA
stringprep提供用于IP協定的Unicode字元串
textwrap文本打包和填充
unicodedataUnicode資料庫
核心子產品: re
正規表達式(RE)提供了進階的字元串模式比對方案
6.10 字元串關鍵點總結
你可以把字元串看成是Python的一種資料類型,在Python單引号或者雙引号之間的字元數組或者是連續的字元集合
不可分字元類型
字元串格式化操作符(%)提供類似于printf()那樣的功能
三引号
原始字元串對每個特殊字元串都使用它的原意
Python字元串不是通過NUL或者'\0'來結束的
6.11 清單
像字元串類型一樣,清單類型也是序列式的資料類型,可以通過下标或者切片的操作來通路某一個或者某一塊連續的元素,與字元串不同在于,字元串隻能由字元組成,且不可變,而清單能保留任意數目的Python對象的靈活容器
清單可讀寫,元組不可變,隻讀
建立類表類型資料并指派
>>> aList = [123, 'abc', 4.56,['inner','list'],7-9j]
>>> anotherList = [None, 'something']
>>> print anotherList
[None, 'something']
>>> aListThatStartedEmpty = []
>>> print aListThatStartedEmpty
[]
>>> list('foo')
['f', 'o', 'o']
如何通路清單中的值
>>> aList[0]
123
>>> aList[1:4]
['abc', 4.56, ['inner', 'list']]
>>> aList[:3]
[123, 'abc', 4.56]
>>> aList[3][1]
'list'
更新清單
>>> aList
[123, 'abc', 4.56, ['inner', 'list'], (7-9j)]
>>> aList[2]
4.56
>>> aList[2]= 'float replacer'
[123, 'abc', 'float replacer', ['inner', 'list'], (7-9j)]
>>> anotherList.append("hi,i'm new here")
[None, 'something', "hi,i'm new here"]
>>> aListThatStartedEmpty.append('not empty anymore')
['not empty anymore']
如何删除清單中的元素或者清單(本身)
>>> del aList[1]
[123, 'float replacer', ['inner', 'list'], (7-9j)]
>>> aList.remove(123)
['float replacer', ['inner', 'list'], (7-9j)]
6.12 操作符
6.12.1 标準類型操作符
>>> list1 = ['abc',123]
>>> list2 = ['xyz',789]
>>> list3 = ['abc',123]
>>> list1 < list2
>>> list2 < list3
>>> list2 > list3 and list1 == list3
6.12.2 序列類型操作符
切片([])和[:])
清單切片傳回時一個對象或幾個對象的集合
>>> num_list = [43,-1.23,-2,6.19e5]
>>> str_list = ['jack','jumped','over','candlestick']
>>> mixup_list = [4.0,[1,'x'],'beef',-1.9+6j]
清單切片也支援正負索引值
>>> num_list[1]
-1.23
>>> num_list[1:]
[-1.23, -2, 619000.0]
>>> num_list[2:-1]
[-2]
>>> str_list[2]
'over'
>>> str_list[:2]
['jack', 'jumped']
>>> mixup_list
[4.0, [1, 'x'], 'beef', (-1.9+6j)]
>>> mixup_list[1]
[1, 'x']
清單元素可以是一個序列類型,可以在結果中進行再切片和改變切片結果
>>> mixup_list[1][1]
>>> mixup_list[1][1] = -64.875
[4.0, [1, -64.875], 'beef', (-1.9+6j)]
>>> num_list
[43, -1.23, -2, 619000.0]
>>> num_list[2:4]=[16.0,-49]
[43, -1.23, 16.0, -49]
>>> num_list[0]
43
>>> num_list[0]=[65535L,2e30,76.45-1.3j]
[[65535L, 2e+30, (76.45-1.3j)], -1.23, 16.0, -49]
成員關系操作(in,not in)
檢查一個對象是否是一個清單的成員
>>> mixup_list
>>> 'beef' in mixup_list
>>> 'x' in mixup_list
>>> 1 in mixup_list[1]
>>> -49 in num_list
>>> 34 in num_list
>>> [65535L, 2e+30, (76.45-1.3j)] in num_list
連接配接操作符允許我們把多個清單對象合并在一起,連接配接操作隻能在同類型之間進行
>>> num_list + mixup_list
[43, -1.23, -2, 619000.0, 4.0, [1, 'x'], 'beef', (-1.9+6j)]
>>> str_list + num_list
['jack', 'jumped', 'over', 'candlestick', 43, -1.23, -2, 619000.0]
連接配接操作符左右兩邊必須使用相同類型值
>>> num_list + 'new item'
TypeError: can only concatenate list (not "str") to list
使用append()解決添加不同類型值方法
>>> num_list.append('new item')
[43, -1.23, -2, 619000.0, 'new item']
>>> num_list * 2
[43, -1.23, -2, 619000.0, 43, -1.23, -2, 619000.0]
>>> num_list * 3
[43, -1.23, -2, 619000.0, 43, -1.23, -2, 619000.0, 43, -1.23, -2, 619000.0]
>>> hr ='-'
>>> hr *=30
>>> hr
'------------------------------'
6.12.3 清單類型操作符和清單解析
>>> [ i * 2 for i in [8,-2,5]]
[16, -4, 10]
>>> [ i for i in range(8) if i % 2 == 0]
[0, 2, 4, 6]
6.13 内建函數
6.13.1 标準類型函數
>>> list1,list2 = [123,'xyz'],[456,'abc']
>>> cmp(list1,list2)
>>> cmp(list2,list1)
>>> list3 = list2 +[789]
>>> list3
[456, 'abc', 789]
>>> cmp(list2,list3)
1.對兩個清單的元素進行比較
2.如果比較的元素師同類型的,則比較其值,傳回結果
3.如果兩個元素不是同一種類型,則檢查它們是否是數字
a.如果是數字,執行必要的數字強制類型轉換,然後比較
b.如果有一方的元素數字,則另一方的元素大"大"
c.否則,通過類型名字的字母順序進行比較
4.如果有一個清單首先到達末尾,則另一個長一點的清單大"大".
5.如果我們用盡了兩個清單的元素而且所有元素都是相等的,那麼結果就是個平局,傳回0
6.13.2 序列類型函數
>>> len(num_list)
4
>>> len(num_list*2)
>>> max(str_list)
>>> max(num_list)
619000.0
>>> min(str_list)
'candlestick'
>>> min(num_list)
-2
sorted() and reversed()
>>> s = ['They','stamp','them','when',"they're",'small']
>>> for t in reversed(s):
... print t,
small they're when them stamp They
>>> sorted(s)
['They', 'small', 'stamp', 'them', "they're", 'when']
enumerate() and zip()
>>> albums = ['tales','robot','pyramid']
>>> for i,album in enumerate(albums):
... print i,album
0 tales
1 robot
2 pyramid
>>> fn = ['ian','stuart','david']
>>> ln = ['bairnson','elliott','paton']
>>> for i,j in zip(fn,ln):
... print('%s %s' % (i,j)).title()
Ian Bairnson
Stuart Elliott
David Paton
sum()
>>> import operator
>>> reduce(operator.add, a)
15
>>> sum(a)
list() and tuple()
>>> aList = ['tao',93,99,'time']
>>> aTuple = tuple(aList)
>>> aList,aTuple
(['tao', 93, 99, 'time'], ('tao', 93, 99, 'time'))
>>> aList == aTuple
>>> anotherList = list(aTuple)
>>> aList == anotherList
>>> anotherList
['tao', 93, 99, 'time']
>>> aList is anotherList
>>> [id(x) for x in aList, aTuple, anotherList]
[3073736588L, 3073705020L, 152603948]
元組與清單的轉換,雖然有相同的資料集合,但不是指向同一個對象,是以清單不可能等于元組
6.13.3 清單類型内建函數
6.14 清單類型的内建函數
用dir()方法來得到它所有的方法和屬性
>>> dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
清單類型内建函數
List.MethodOperation
list.append(obj)想清單中添加一個對象obj
list.count(obj)傳回一個對象obj在清單中出現的次數
list.extend(seq)把序列seq的内容添加到清單中
list.index(obj,i=0,j=len(list))傳回list[k] == obj的k值,并且k的範圍在
i<=k<j;否則引發ValueError異常
list.insert(index,obj)在索引量為index的位置插入對象obj
list.pop(index=-1)删除并傳回指定位置的對象,預設是最後一個對象
list.remove(obj)從清單中删除對象obj
list.reverse()原地翻轉清單
list.sort(func=None,
key=None,reverse=False)以指定的方式排序清單中的成員,如果func和key參數指定,則按照指定的方式比較各個元素,如果reverse 标志被置為True,則清單以反序排列
>>> music_media = [45]
>>> music_media
[45]
>>> music_media.insert(0,'compact disc')
['compact disc', 45]
>>> music_media.append('long playing record')
['compact disc', 45, 'long playing record']
>>> music_media.insert(2,'8-track tape')
['compact disc', 45, '8-track tape', 'long playing record']
找出元素在清單中的索引值,我們用in操作符和index()方法實作這兩個需求
>>> 'cassette' in music_media
>>> 'compact disc' in music_media
>>> music_media.index(45)
>>> music_media.index('8-track tape')
>>> music_media.index('cassette')
ValueError: 'cassette' is not in list
解決方法,先用in檢查,然後再用index()找到這個元素的位置
>>> for eachMediaType in (45,'8-track tape','cassette'):
... if eachMediaType in music_media:
... print music_media.index(eachMediaType)
sort()和reverse()方法,排序翻轉
>>> music_media.sort()
[45, '8-track tape', 'compact disc', 'long playing record']
>>> music_media.reverse()
['long playing record', 'compact disc', '8-track tape', 45]
注:那些可以改變對象值的可變對象的方法是沒有範圍值的
>>> music_media.sort() # 沒有輸出
但字元串的類似方法确實有傳回值
>>> 'leanna,silly girl!'.upper()
'LEANNA,SILLY GIRL!'
extend()方法接受一個清單内容然後把它的所有元素追加到另一個清單中
>>> new_media = ['24/96 digital audio disc','DVD Audio disc','Super Audio CD']
>>> music_media.extend(new_media)
['long playing record', 'compact disc', '8-track tape', 45, '24/96 digital audio disc', 'DVD Audio disc', 'Super Audio CD']
>>> motd = []
>>> motd.append('MSG OF THE DAY')
>>> f = open ('/etc/motd','r')
>>> motd.extend(f)
>>> f.close()
>>> motd
['MSG OF THE DAY', 'Welcome to Ubuntu 12.04.3 LTS (GNU/Linux 3.8.0-29-generic i686)\n', '\n', ' * Documentation: https://help.ubuntu.com/\n', '\n', ' System information as of Mon Oct 21 20:13:01 CST 2013\n', '\n', ' System load: 0.0 Processes: 72\n', ' Usage of /: 10.1% of 8.59GB Users logged in: 1\n', ' Memory usage: 5% IP address for eth0: 192.168.100.91\n', ' Swap usage: 0%\n', '\n', ' Graph this data and manage this system at https://landscape.canonical.com/\n', '\n']
6.15 清單的特殊特性
6.15.1 用清單建構其他資料結構
用清單模拟堆棧
把清單作為堆棧用于存儲和取回輸入的字元串
# vi stack.py
-------------------------
stack = []
def pushit():
stack.append(raw_input('Enter new string:').strip())
def popit():
if len(stack) == 0:
print 'Cannot pop from an empty stack!'
else:
print 'Removed[',`stack.pop()`, ']'
def viewstack():
print stack
CMDs = {'u':pushit,'o':popit, 'v':viewstack}
def showmenu():
pr ="""
p(U)sh
p(O)p
(V)iew
(Q)uit
Enterchoice: """
while True:
while True:
try:
choice = raw_input(pr).strip()[0].lower()
except (EOFError,KeyboardInterrupt,IndexError):
choice = 'q'
print '\nYou picked: [%s]' % choice
if choice not in 'uovq':
print 'Invalid option,try again'
else:
break
if choice == 'q':
break
CMDs[choice]()
if __name__ == '__main__':
showmenu()
隊列
隊列是一種先進先出的資料類型,它的工作原理類似超市中排隊交錢或者銀行裡面的排隊,隊列的第一個人首先接受服務,新的元素通過"入隊"的方式添加進隊列的末尾,"出隊"就是從隊列的頭部删除
把清單用隊列來存儲和取回菜單驅動應用裡面輸入的字元串,用到了append()和pop()方法
# vi queue.py
--------------------------
queue = []
def enQ():
queue.append(raw_input('Enter new string: ').strip())
def deQ():
if len(queue) == 0:
print 'Cannot pop from an empty queue!'
print 'Removed [',`queue.pop(0)`,']'
def viewQ():
print queue
CMDs = {'e':enQ, 'd':deQ, 'v':viewQ}
pr = """
(E)nqueue
(D)equeue
Enter chioce: """
except(EOFError,KeyboardInterrupt,IndexError):
if choice not in 'devq':
6.16 元組
如何建立一個元組并給它指派
注:隻有一個元素的元組需要在元組分隔符裡加一個逗号() 防止跟普通分組操作符混淆
>>> aTuple = (123,'abc',4.56,['inner','tuple'],7-9j)
>>> anotherTuple = (None,'something to see here')
>>> print aTuple
(123, 'abc', 4.56, ['inner', 'tuple'], (7-9j))
>>> print anotherTuple
(None, 'something to see here')
>>> emptiestPossibleTuple = (None)
>>> print emptiestPossibleTuple
(None,)
>>> tuple('bar')
('b', 'a', 'r')
如何通路元組中的值
>>> aTuple[1:4]
('abc', 4.56, ['inner', 'tuple'])
>>> aTuple[:3]
(123, 'abc', 4.56)
>>> aTuple[3][1]
'tuple'
如何更新元組
>>> aTuple = aTuple[0],aTuple[1],aTuple[-1]
>>> aTuple
(123, 'abc', (7-9j))
>>> tup1 = (12,34.56)
>>> tup2 = ('abc','xyz')
>>> tup3 = tup1 + tup2
>>> tup3
(12, 34.56, 'abc', 'xyz')
移除一個元組的元素是不可能的,但可以把不需要的元素丢棄後從新組成一個元組
6.17 元組操作符和内建函數
6.17.1 标準類型操作符,序列類型操作符和内建函數
建立,重複,連接配接操作
>>> t = (['xyz',123],34,-130.4)
>>> t
(['xyz', 123], 34, -130.4)
>>> t * 2
(['xyz', 123], 34, -130.4, ['xyz', 123], 34, -130.4)
>>> t = t + ('free','easy')
(['xyz', 123], 34, -130.4, 'free', 'easy')
成員關系操作,切片操作
>>> 23 in t
>>> 123 in t
>>> t[0][1]
>>> t[1:]
(34, -130.4, 'free', 'easy')
内建函數
>>> str(t)
"(['xyz', 123], 34, -130.4, 'free', 'easy')"
>>> len(t)
5
>>> max(t)
'free'
>>> min(t)
-130.4
>>> cmp (t,(['xyz', 123], 34, -130.4, 'free', 'easy'))
>>> list(t)
[['xyz', 123], 34, -130.4, 'free', 'easy']
操作符
>>> (4, 2) < (3, 5)
>>> (2, 4) < (3, 5)
>>> (2, 4) == (3, 5)
>>> (2, 4) == (2, 4)
6.17.2 元組類型操作符和内建函數,内建方法
因為元組不可變,是以諸如排序,替換,添加這些操作對元組來說就無法實作
6.18 元組的特殊特性
6.18.1 不可變性給元組帶來什麼影響?
比如我們把資料傳給一個不了解的API時,可以確定我們的資料不會被修改,同樣如果我們操作從一個函數傳回的元組,可以通過内建list()函數把它轉換成一個清單.
6.18.2 元組也不是那麼"不可變"
>>> s = 'first'
>>> s = s + ' second'
'first second'
>>> t = ('third','fourth')
('third', 'fourth')
>>> t = t + ('fifth','sixth')
('third', 'fourth', 'fifth', 'sixth')
雖然元組對象本身不可變,但不意味元組包含的可變對象也不可變
>>> t = (['xyz',123],23,-102.3)
(['xyz', 123], 23, -102.3)
>>> t[0][1] = ['abc','def']
(['xyz', ['abc', 'def']], 23, -102.3)
6.18.3 預設集合類型
>>> 'abc',-4.23e93,18+6.6j,'xyz'
('abc', -4.23e+93, (18+6.6j), 'xyz')
>>> x,y = 1,2
>>> x,y
(1, 2)
所有函數傳回的多對象(不包括有符号封裝的)都是元組類型
注:有符号封裝的多對象集合其實是傳回的一個單一的容器對象
def foo1():
return obj1,obj2,obj3
def foo2():
return [obj1,obj2,obj3]
def foo3():
return(obj1,obj2,obj3)
>>> def fool():
... return '1','2','3'
>>> fool()
為了避免副作用,建議總是顯示的用圓括号表達式表示元組或者建立一個元組
>>> 4,2 < 3,5
(4, True, 5)
>>> (4,2) < (3,5)
第一個例子中小于号優先級高于逗号,2<3的結果成了元組變量的第二個元素
6.18.4 單元素元組
>>> ['abc']
['abc']
>>> type(['abc'])
<type 'list'>
>>> ('xyz')
'xyz'
>>> type(('xyz'))
<type 'str'>
由圓括号包裹的一個單一進制素首先被作為分組操作,而不是作為元組的分界符
變通的方法是在第一個元素後面添加一個逗号來表明這是一個元組而不是在做分組操作
>>> ('xyz',)
('xyz',)
>>> type(('xyz',))
<type 'tuple'>
6.18.5 字典的關鍵字
注: 通過内建的list()和tuple()轉換函數進行在清單和元組之間轉換
6.19 相關子產品
子產品内容
數組一種受限的可變序列類型,所有元素必須相同類型
copy提供深淺拷貝能力
operator包含函數調用形式的序列操作符,operator.concat(m,n)相當于連接配接操作(m+n)
reperl風格的正規表達式
StringIO/cStringIO把長字元串作為檔案來操作,比如read(),seek()
Textwrap用作包裹/填充文本函數,也有一個類
types包含Python支援的所有類型
collections高性能容器資料類型
6.20 拷貝Python對象
淺拷貝和深拷貝
對象指派實際上是簡單的對象引用,當你建立一個對象,然後把它賦給另一個變量時,Python并沒有拷貝這個對象,而是拷貝了這個對象的引用
建立一對通用檔案,名為person,然後分别為他倆拷貝一份
>>> person = ['name',['savings',100.00]]
>>> hubby = person[:]
>>> wifey = list(person)
>>> [id(x) for x in person,hubby,wifey]
[146186380, 146316620, 146316844]
為他們建立了初始有$100的個人存款賬戶,使用者名改為定制的名字,但是當丈夫取走50後,他的行為影響到了他妻子的賬戶,雖然我們進行了分開的拷貝 WHY?
>>> hubby[0] = 'joe'
>>> wifey[0] = 'jane'
>>> hubby,wifey
(['joe', ['savings', 100.0]], ['jane', ['savings', 100.0]])
>>> hubby[1][1] = 50.00
(['joe', ['savings', 50.0]], ['jane', ['savings', 50.0]])
原因我們僅僅做了一個淺拷貝,對一個對象進行淺拷貝其實是新建立了一個類型跟原對象一樣,其内容是原來對象元素的引用,換句話說,這個拷貝對象本身就是新的,但它的内容不是,序列類型對象的淺拷貝是預設類型拷貝,并可以利用以下方式實施:
1.完全切片操作[:],2.利用工廠函數,比如list(),dict()等
3.使用copy子產品的copy函數
當妻子名字被指派,丈夫名字沒受影響的原因是在這兩個清單對象中,第一個對象時不可變的(字元串類型),第二個是可變的(清單類型),淺拷貝時,字元串被顯式拷貝,并新建立了一個字元串對象,而清單元素隻是把它的引用複制了一下,并不是它的成員,是以改變名字無問題,改變清單就會有問題
BEFORE:
[id(x) for x in hubby]
[9919616,11826320]
[id(x) for x in wifey]
AFTER:
[id(x) for x in bubby]
[12092832,11826320]
[12191712,11826320]
如果需要将兩個人分離賬戶,得到一個完全拷貝即深拷貝--建立一個新的容器對象,包含原有對象元素(引用) 全新拷貝的引用需要copy.deepcopy()函數
>>> hubby = person
>>> import copy
>>> wifey = copy.deepcopy(person)
[148843244, 148843244, 146186380]
(['joe', ['savings', 50.0]], ['jane', ['savings', 100.0]])
驗證結果,四個對象都不同
>>> [id(x) for x in hubby]
[148673792, 148841004]
>>> [id(x) for x in wifey]
[148590496, 148843404]
注:
1.非容器類型(字元串,數字和其他"原子"類型對象,像代碼,類型和xrange對象)無法拷貝,淺拷貝用來完全切片
2.元組變量隻包含院子類型,對深拷貝不會進行,如果我們把賬戶資訊改成元組類型,即使使用deepcopy操作也隻能得到一個淺拷貝
>>> person = ['name',('savings',100.00)]
>>> newPerson = copy.deepcopy(person)
>>> [id(x) for x in person,newPerson]
[3073351596L, 148843532]
>>> [id(x) for x in person]
[3073474432L, 148628364]
>>> [id(x) for x in newPerson]
注:copy子產品隻有兩個可用函數
copy()進行淺拷貝 deepcopy()進行深拷貝
6.21 序列類型小結
系列類型操作符,内建函數和方法
Operator,Built-in
Function or MethodStringListTuple
[] (list creation) *
() *
"" *
append() *
capitalize() *
center() *
chr() *
cmp() *
count() *
decode() *
encode() *
endswith() *
expandtaba() *
extend() *
find() *
..................
輸入一串數字從大到小排列
----------------------------------
usr_input = raw_input("please input sth: ").strip()
usr_input_list = list(usr_input)
usr_input_list.sort()
usr_input_list.reverse()
for i in range(len(usr_input_list)):
print usr_input_list[i],
-----------------------------------
用字典序從大到小排列
for i in reversed(usr_input_list):
print i,
把測試得分放到一個清單中,算出平均分
---------------------------------------
try:
usr_input_1 = int(raw_input("please input the first word: ").strip())
usr_input_2 = int(raw_input("please input the second word: ").strip())
usr_input_3 = int(raw_input("please input the third word: ").strip())
except:
print "please input the number!"
list = [usr_input_1,usr_input_2,usr_input_3]
average = sum(list)/len(list)
print "The list is %s" %list
print "The average of the list is %i" %average
周遊字元串
----------------------------
>>> test_string = "34ghf3d978jfs23"
>>> for i in test_string:
... print i,
3 4 g h f 3 d 9 7 8 j f s 2 3
本文轉自 showerlee 51CTO部落格,原文連結:http://blog.51cto.com/showerlee/1330264,如需轉載請自行聯系原作者