第四章 操作列表


4.1  遍歷整個列表

    我們經常需要遍歷列表中的所有元素,對每個列表執行相同的操作。在進行重復性的工作的時候這個很有用,重復性工作。例如,在游戲中,可能需要將每個界面元素平移相同的距離;對於包含數字的列表,可能需要對每個元素執行相同的統計運算;在網站中,可能需要顯示3文章中的每個標題。需要對列表中的每個元素都執行相同的操作時,可使用Python中的for循環。

    假如我們有一個魔術師的名單,需要將其中每個魔術師的名字都打印出來。為此,我們可以分別獲取名單中的每個名字,但這種做法會導致很多個問題。例如,如果名單過長,將包含大量重復的代碼。另外,每當名單中的長度發生變化時,都必須修改代碼。通過使用for循環,可讓Python去處理這些問題。

    下面使用for循環來打印魔術師名單中的所有名字:

 

magicians = ["alice","david","carolina"]
for magician in magicians:
print(magician)
運行結果:
alice
david
carolina
首先,我們像第三章那樣定義了一個列表。接下來,我們定義了一個for循環;這行代碼讓Python從列表magicians中去除一個名字,並將其存儲在變量
magician中。最后,我們讓Python打印前面存儲到變量magician中的名字。這樣,對於列表中的每個名字,Python都將重復執行。我們可以這樣解讀這些代碼
:對於列表magician中的每位魔術師,都將其名字打印出來。輸出很簡單,就是列表中所有的姓名:

4.1.1 深入地研究循環
循環這種概念很重要,尤其在操作重復性的問題的時候,使用自動循環會提高很多效率,而且它是讓計算機自動完成重復工作的常見方式之一。例如,在前
面的magicians.py中使用的簡單循環中,Python將首先讀取其中的第一行代碼:
for magician in magicians:
這行代碼,讓Python獲取列表中magicians中的第一個值("alice"),並將其存儲到變量magician中。接下來,Python讀取下一行代碼。
print(magician)
它讓Python打印magician的值---依然是"alice"。鑒於該列表還包含其他值,Python返回循環的第一行:
for magician in magicians:
python獲取列表中下一個名字——"david",並將其存儲到變量magician中,在執行下面的代碼:
print(magician)
Python再次打印變量magician的值"david"。接下來,Python再次執行整個循環,對列表中的最后一個值——"carolina"進行處理。至此,列表中沒有其
它的值了,因此Python接着執行程序的下一行代碼。在這個實例中,for循環后面沒有其他的代碼,因此程序就此結束。
剛開始使用循環時請牢記,對列表中的每個元素,都將執行循環制定的步驟,而不管列表包含多少元素。如果列表包含一百萬個元素,Python就重復執行一
百萬次,且通常速度非常快。
另外,編寫for循環時,對於用於存儲列表中每個值的臨時變量,可指定任何名稱。然而,選擇描述單個列表元素的有意義的名稱大有幫助。例如,對於小
貓列表,小狗列表和一般性列表,像下面這樣編寫for循環的第一行代碼是不錯的選擇:
for dog in dogs:
for cat in cats:
for item in list_of_items:
這些命名約定有助於我們明白for循環中將對每個元素執行的操作。使用單數和復數式名稱,可幫助我們判斷代碼處理的是單個列表元素還是整個列表。

4.1.2 在for循環中執行更多的操作
在for循環中,可對每個元素執行任何操作。
magicians = ["alice","david","carolina"]
for magician in magicians:
print(magician.title() + ", that was a greet trick!")
下面輸出結果表明,對於列表中的每位魔術師,都打印了一條個性化消息:
Alice, that was a greet trick!
David, that was a greet trick!
Carolina, that was a greet trick!
在for循環中,想包含多少行代碼都可以。在代碼行for magician in magicians后面,每個縮進的代碼行都是循環的一部分,且將針對列表中的每個值都
執行一次。因此,可對列表中能夠的每個值執行任意次數的操作。
下面再添加一行代碼,告訴每位魔術師,我們期待他的下一次表演:

magicians = ["alice","david","carolina"]
for magician in magicians:
print(magician.title() + ", that was a greet trick!")
print("I can't wait to see your next trick, " + magician.title() + ".\n" )
由於兩條print語句都縮進了,因此它們都將針對列表中的每位魔術師執行一次。第二條print語句中的換行符"\n"在每次迭代結束后都插入一
個空行,從而整潔地將針對各位魔術師的消息編組:
Alice, that was a greet trick!
I can't wait to see your next trick, Alice.

David, that was a greet trick!
I can't wait to see your next trick, David.

Carolina, that was a greet trick!
I can't wait to see your next trick, Carolina!
在for循環中,想包含多少行代碼都可以。實際上,我們會發現使用for循環對每個元素執行眾多不同的操作很有用。

4.1.3 在for循環結束后執行一些操作
for循環結束后再怎么做呢?通常,我們需要提出總結性輸出或接着執行程序必須完成的其他任務。
在for循環后面,沒有縮進的代碼都只執行一次,而不會重復執行。下面來打印一條向全體魔術師致謝的消息,感謝它們的精彩表演。想要在打印給各位
魔術師的消息后面打印一條給全體魔術師的致謝消息,需要將相應的代碼放在for循環后面,且不縮進:
magicians = ["alice","david","carolina"]
for magician in magicians:
print(magician.title() + ", that was a great trick!")
print("I can't wait to see your next trick, " + magician.title() + ".\n" )
print("Thank you,everyone. That was a great magic show!")
我們在前面看到了,開頭兩條print語句針對列表中每位魔術師重復執行。然而,由於第三條print語句沒有縮進,因此只執行一次:
Alice, that was a great trick!
I can't wait to see your next trick, Alice.

David, that was a great trick!
I can't wait to see your next trick, David.

Carolina, that was a great trick!
I can't wait to see your next trick, Carolina.

Thank you,everyone. That was a great magic show!
使用for循環處理數據是一種對數據集執行整體操作的不錯的方式。例如,你可能使用for循環來初始化游戲——遍歷角色列表,將每個角色都顯示到屏幕
上;再在循環后面添加一個不縮進的代碼塊,在屏幕上繪制所有角色后顯示一個play Now按鈕。

4.2 避免縮進錯誤
Python根據縮進來判斷代碼行與前一個代碼行的關系。在前面的實例中,向各位魔術師顯示消息的代碼行是for循環的一部分,因為它們縮進了。Python通
過縮進讓代碼更易讀;簡單地說,它要求我們使用縮進讓代碼整潔而結構清晰。在較長的Python程序中,我們將看到縮進程度各不相同的代碼塊,這讓我們隊程
序的組織結構有大致的認識。
當我們開始編寫必須正確縮進的代碼時,需要注意一些常見的縮進錯誤。例如,有時候,程序員會將不需要縮進的代碼塊縮進,而對於必須縮進的代碼塊卻
忘了縮進。通過查看這樣的錯誤示例,有助於我們以后避開它們,以及在它們出現在程序中時進行修復。

4.2.1 忘記縮進
對於位於for語句后面且屬於循環組成部分的代碼行,一定要縮進。如果我們忘記縮進,Python會提醒:
magicians = ["alice","david","carolina"]
for magician in magicians:
print(magician.title() + ", that was a great trick!")
print語句應縮進卻沒有縮進。Python沒有找到期望縮進的代碼塊時,會讓我們知道代碼行有問題。
  File "/home/zhuzhu/title4/magicians.py", line 3
    print(magician.title() + ", that was a great trick!")
        ^
IndentationError: expected an indented block
提示我們代碼沒有縮進,預期應該出現縮進的,通常,將緊跟在for語句后面的代碼行縮進,可消除這種縮進錯誤。

4.2.2 忘記縮進額外的代碼行
magicians = ["alice","david","carolina"]
for magician in magicians:
print(magician.title() + ", that was a great trick!")
print("I can't wait to see your next trick, " + magician.title() + ".\n" )
magicians = ["alice","david","carolina"]
for magician in magicians:
print(magician.title() + ", that was a great trick!")
print("I can't wait to see your next trick, " + magician.title() + ".\n" )
print("Thank you,everyone. That was a great magic show!")
由於第三條print代碼行被縮進,它將針對列表中的每位魔術師執行一次
Alice, that was a great trick!
I can't wait to see your next trick, Alice.

Thank you,everyone. That was a great magic show!
David, that was a great trick!
I can't wait to see your next trick, David.

Thank you,everyone. That was a great magic show!
Carolina, that was a great trick!
I can't wait to see your next trick, Carolina.

Thank you,everyone. That was a great magic show!
這也是一個邏輯錯誤,與4.2.2節的錯誤類似。Python不知道你的本意,只要代碼符合語法,它就會運行。如果原本只應執行一次的操作執行了多次,請確
定我們是否不應該縮進執行該操作的代碼。

4.2.5 遺漏了冒號:
for語句在末尾冒號告訴Python,下一行是循環的第一行。
magicians = ["alice","david","carolina"]
for magician in magicians
print(magician.title() + ", that was a great trick!")
運行:
 File "/home/zhuzhu/title4/magicians.py", line 2
    for magician in magicians
                            ^
SyntaxError: invalid syntax (語法無效)
如果我們不小心遺漏了冒號,將導致語法錯誤,運行會提示無效語法,因為Python不知道我們意欲何為。這種錯誤雖然易於消除,但並不那么容
易發現。程序員為找出這樣的單字符錯誤,花費的時間多的令人驚訝。這樣的錯誤之所以難以發現,是因為通常在我們的意料之外。

動手練一練
pizzas = ["New York Style","Chicago Style","California Style"]
for pizza in pizzas:
print("I like to eat " + pizza.title() + " .")
print("I can't wait to eat " + pizza.title() + " next time!\n")
print("I like kinds of all style pizza !")

運行結果如下:
I like to eat New York Style .
I can't wait to eat New York Style next time!

I like to eat Chicago Style .
I can't wait to eat Chicago Style next time!

I like to eat California Style .
I can't wait to eat California Style next time!

I like kinds of all style pizza !

animals = ["lion","tiger","wolf","leopard"]
for animal in animals:
print(animal.title() + "s are good at hunting.")
print("Any of these animals like eating meat!")
首先定義了一個動物列表,使用for循環遍歷列表中每一個動物,第一個print打印所以動物的一個共性,屬於for循環的;第二個print在for循環外
面,當運行結束for循環后進行運行,屬於總結性的語言,所以只會打印一次:
Lions are good at hunting.
Tigers are good at hunting.
Wolfs are good at hunting.
Leopards are good at hunting.
Any of these animals like eating meat!

4.3 創建數值列表
需要存儲一組數字的原因有很多,例如,在游戲中,需要跟蹤每個角色的位置,還可能需要跟蹤玩家的幾個最高得分。在數據可視化中,處理的幾乎都是
數字(如溫度、距離、人口數量、經度和緯度等等)組成的集合。
列表非常適合用於存儲數字集合,而且Python提供了很多工具,可幫助我們處理數字列表。明白如何有效地使用這些工具后,即便包含數百萬個元素,我們
編寫的代碼也能很好的運行。

4.3.1
使用函數range()
for value in range(1,6):
print(value)
這樣,輸出將從1開始,到5結束:
1
2
3
4
5
使用range()函數時,如果輸出不符合預期,請嘗試將指定的值加1或減1.

4.3.2 使用range()函數創建數字列表
numbers = list(range(1,6))
print(numbers)
結果如下:
[1, 2, 3, 4, 5]
使用函數range()時,還可指定步長。例如,下面的代碼打印1~10內的奇數:
numbers = list(range(1,10,2))
print(numbers)

在這個實例中,函數range()從2開始數,然后不斷地加2,直到達到或超過終值(10),因此輸出的結果如下:
[1, 3, 5, 7, 9]
使用函數range()幾乎能夠創建任何需要的數字集,例如,如何創建一個列表,其中包含前10個整數(既1~10)的平方呢?在Python中,兩個星號(**)表示
乘方運算。下面的代碼演示了如何將前10個整數的平方加入到一個列表中:
squares = []
for num in range(1,11):
square = num**2
squares.append(square)
print(squares)
首先,我們創建了一個空列表;接下來,使用函數range()讓Python遍歷1~10的值。在循環中,計算當前值的平方,並將結果存儲到變量square中,然后
將新計算的到的平方值附加到列表squares的末尾。最后,循環結束后,打印列表squares
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
創建更復雜的列表時,可使用上述兩種方法中的任何一種。有時候,使用臨時變量會讓代碼更易讀;而在其他情況下,這樣只會讓代碼無所謂地變長。我們
應該考慮的是,編寫清晰易懂且能完成所需功能的代碼;等到審核代碼時,在考慮采用更高效的方法。

squares = [value**2 for value in range(1,11)]
print(squares)
要使用這種語法,首先指定一個描述性的列表名,如squares;然后指定一個左方括號,並定義一個表達式,用於生成你要存儲得到列表中的值。在這個示
例中,表達式為value**2,它計算平方值。接下來,編寫一個for循環,用於給表達式提供值,再加上右方括號。在這個實例中,for循環為for value in
range(1,11),它將值1~10提供給表達式value**2.請注意,這里的for語句末尾沒有冒號。
結果與我們在前面看到的平方數列表相同:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
要創建自己的列表解析,需要經過一定的練習,但能夠熟練地創建常規列表后,你會發現這樣做是完全值得的。當你覺得編寫三四行代碼來生成列表有點繁
復時,就應該考慮創建列表解析了。
其實,我挺喜歡列表解析的,這種方法太省事了,又不用定義列表,只需要把語句寫在括號里面,好省事,很方便,要多嘗試使用這種方式,創建簡短的數
列表表示方式。

動手試一試
4-3 數到20:
使用一個for循環打印數字1~20(含);
4-4 一百萬:
創建一個列表,其中包含數字1~1000000,在使用一個for循環將這些數字打印出來(如果輸出的時間太長,按Ctrl + C停止輸出,或關閉
輸出窗口)。
4-5 計算1~1000000的總和:
創建一個列表,其中包含數字1~1000000,在使用min()函數和max()函數核實該列表確實是從1開始,從1000000結束的。
另外,對這個列表調用函數sum(),看看Python將一百萬個數字相加需要多長時間。
4-6 奇數:
通過給函數range()指定第三個參數來創建一個列表,其中包含1~20的奇數;在使用一個for循環將這些數字都打印出來;
4-7 3的倍數:
創建一個列表,其中包含3~30內能被3整除的數字;在使用一個for循環將這個列表中的數字都打印出來;
4-8 立方:
將同一個數字乘三次成為立方。例如,在Python中,2的立方用2**3表示。請創建一個列表,其中包含前10個整數(即1~10)的立方,在使用
一個for循環將這些立方數都打印出來;
4-9立方解析:
使用列表解析生成一個列表,其中包含前10個整數的立方。
分析:里面的試題主要考察我們for循環的使用,已經min()函數、max()函數和sum()函數等,要多嘗試使用列表解析,因為我覺得這真是一個很好的方法,只需
一步就能產生我們需要的列表,要記住函數range()的差一性,list()函數是生成列表的。表達式的情況,對數字列表進行操作。
4-3:本題就是練習我們for循環的使用,還有range()函數的差一性
for num in range(1,21):
print(num)
4-4:本題還是鍛煉我們for循環的使用情況,以及range()函數的差一性,但是想告訴我們,Python可以處理很大的數字,並不簡單是書上很小的數
for num in range(1,1000001):
print(num)

運行的時候,遍歷1~1000000還是花費了十幾秒的時間,要記得差一性,比我們想要的數加一
4-5:本題是要使用list()函數創建列表,然后驗證最大值,最小值,並對數字進行求和
numbers = list(range(1,1000001))
print(min(numbers))
print(max(numbers))
print(sum(numbers))

運行結果如下:
1
1000000
500000500000
python計算的速度挺快的,但是在生成列表的時候,還是會花費一點時間的,可以看出最小值確實是1,最大值確實是1000000

4-6:本題主要考察的是range()函數的步長問題,可以制定一個步長在使用的過程中
numbers = list(range(1,20,2))
print(numbers)

nums = [value for value in range(1,20,2)]
print(nums)
使用了兩種方法創建列表,第一種方法是list()函數,第二種是列表解析,當然,如果沒有表達式的話,函數list()方法方便一點,如果有表達是的話,列表解
析就方便很多了,這本題中主要考察的是range()函數的步長,能夠自定義步長值,另外要注意,我們要使用步長的時候,一定要定義range()函數的初始值,第
一個參數是起始值,第二個參數是結束值,第三個參數是步長值。
4-7:本題主要考察我們創建變形的列表,要使用表達式的情況,可以使用循環代碼,也可以使用列表解析

numbers = []
#首先創建一個空列表用於存儲生成的列表數字
for num in range(1,11):
number = num * 3
numbers.append(number)
print(numbers)

digits = [value * 3 for value in range(1,11)]
print(digits)
第一種方法,由於要生成一個列表,首先我們定義了一個空的列表,然后定義一個循環,把每次生成的數值添加到這個空列表的末尾,最后生成我們所需的列表
,第二種方法是使用列表解析,可以看出,我們只需要一條語句就生成了一個數字列表,只要我們知道了列表的表達式就可。
4-8:本題跟上一題相似,只是列表表達式的方式不一樣而已,解決的思路都是一樣的
numbers = []
#首先創建一個空列表用於存儲生成的列表數字
for num in range(1,11):
number = num ** 3
numbers.append(number)
print(numbers)

digits = [value ** 3 for value in range(1,11)]
print(digits)
可以看出我們只是修改了一下列表的表達式而已,在解決問題的時候首先是思考如何去解決問題,想好了之后在編寫代碼,首先我們要生成一個列表,這個列表
是包含自然是1~10的立方,那么我們要先生成1~10的自然數,這時候就用到我們的range()函數了,然后把生成的數進行變化添加到一個列表中即可,只需要每
次生成之后就添加到新的列表中即可。

4.4 使用列表的一部分
在第三章中,我們學習了如何訪問單個列表元素。在本章中,我們一直在學習如何處理列表所有的元素。我們還可以處理列表的部分元素——Python稱之
為切片。

4.4.1 切片
要創建切片,可指定要使用的第一個元素和最后一個元素的索引。與函數range()一樣,Python在到達我們指定的第二個索引前面的元素后停止。要輸出列
表中的前三個元素,需要制定索引0~3,這將輸出分別為0、1和2的元素。
下面的示例處理的是一個運動隊員列表:
players.py
players = ["charles","martina",'michael','florence','eli']
print(players[0:3])
代碼打印列表的一個切片,其中只包含前三名隊員。輸出的也是一個列表,其中包含前三名隊員:
['charles', 'martina',
'michael']
我們可以生成列表的任何子集,例如,如果我們要提取列表的第2~4個元素,可將起始索引制定為1,並將終止索引制定為4:
players = ["charles","martina",'michael','florence','eli']
print(players[1:4])
這一次,切片始於"martina",終於"florence":
['martina', 'michael', 'florence']
如果沒有制定第一個索引,Python將自動從列表開頭開始:
players = ["charles","martina",'michael','florence','eli']
print(players[:4])

由於沒有制定起始索引,Python從列表開頭開始提取:
['charles', 'martina', 'michael', 'florence']
要讓切片終止於列表末尾,也可使用類似的語法。例如,如果要提取從第3個元素到列表末尾所有元素,可將起始索引制定為2,並省略終止索引:
players = ["charles","martina",'michael','florence','eli']
print(players[2:])

Python將返回從第3個元素到末尾的所有元素:
['michael', 'florence', 'eli']
無論列表多長,這種語法都能夠讓我們輸出從特定位置到列表末尾的所有元素。本書前面說過,負數索引返回離列表末尾相應距離的元素,因此我們可以
輸出列表末尾的任何切片。例如,如果我們要輸出名單上的最后三名隊員,可使用切片players[-3:]
players = ["charles","martina",'michael','florence','eli']
print(players[-3:])
上述代碼打印最后三名隊員的名字,即便隊員名單的長度發生變化,也依然如此。

4.4.2 遍歷切片
如果要遍歷列表的部分元素,可在for循環中使用切片。在下面的實例中,我們遍歷前三名隊員,並打印它們的名字:
players = ["charles","martina",'michael','florence','eli']
#thired_players = players[:3]
#print(thired_players
print("Here are the first three players on my team:")
for player in players[0:3]:
print(player)
代碼沒有遍歷整個隊員列表,而只遍歷前三名隊員:
Here are the first three players on my team:
charles
martina
michael
在很多情況下,切片都很有用。例如,編寫游戲時,我們可以在玩家退出游戲時將其最終得分加入到一個列表中。然后,為獲取該玩家的三個最高得分,我
們可以將該列表按降序排列,在創建一個只包含前三個得分的切片。處理數據時,可使用切片來進行批量處理;編寫Web應用程序時,可使用切片來分頁顯示信
息,並在每頁顯示數量合適的信息。
切片的功能確實很好用,在我們要求一個列表前三個,后三個的時候很好用,在使用切片的時候可能會使用sorted()函數對切片進行處理,這些都是需要注
意的,切片,原列表的一部分,切片的用途,當我們需要使用原切片的一部分的時候我們就會用到切片的功能。

4.4.3 復制列表
我們經常需要根據既有列表創建全新列表。下面來介紹列表復制的工作原理,以及復制列表可提供極大幫助的一種情形。
要復制列表,可創建一個包含整個列表的切片,方法是同時省略起始索引和終止索引([:])。這讓Python創建一個始於第一個元素,終止於最后一個元素的
切片,即復制整個列表。
假如,假設有一個列表,其中包含我們最喜歡的四種食品,而我們還想創建另一個列表,在其中包含一位朋友喜歡的所有食品。不過,我們喜歡的食品,這
位朋友都喜歡,因此我們可以通過復制來創建這個列表:
foods.py
my_foods = ["pizza",'noodle','falafel']
friend_foods = my_foods[:]

print("My favorite foods are: ")
print(my_foods)

print("\nMy friend's favorite foods are: ")
print(friend_foods)
 我們首先創建了一個名為my_foods的列表,然后創建了一個friend_foods的新列表。我們不制定任何索引的情況下從列表my_foods中提取一個切片,從而
創建了這個列表的副本,再將該副本存儲到變量friend_foods中。打印每個列表后,我們發現它們包含的食品相同:
My favorite foods are:
['pizza', 'noodle', 'falafel']

My friend's favorite foods are:
['pizza', 'noodle', 'falafel']
為核實我們確實有兩個列表,下面在每個列表中都添加一種食品,並核實每個列表都記錄了相應任意喜歡的食品:
my_foods = ["pizza",'noodle','falafel']
friend_foods = my_foods[:]
my_foods.append("cannoli")
friend_foods.append("ice cream")

print("My favorite foods are: ")
print(my_foods)

print("\nMy friend's favorite foods are: ")
print(friend_foods)
 與前一個示例一樣,我們首先將my_foods的元素復制到新列表friend_foods中。接下來,在每個列表中都添加一種食品:在列表my_foods中添加"cannno"
,而在friend_foods中添加"ice cream"。最后,打印這兩個列表,核實這兩種食品包含在正確的列表中。
My favorite foods are:
['pizza', 'noodle', 'falafel', 'cannoli']

My friend's favorite foods are:
['pizza', 'noodle', 'falafel', 'ice cream']
輸出結果表明,"cannoli"包含在你喜歡的食品列表中,而"ice cream"沒有。"ice cream"包含在你朋友喜歡的食品列表中,而"cannoli"沒有。倘若我們
只是簡單地將my_foods賦給friend_foods,就不能得到兩個列表。例如,下面演示了在不使用切片的情況下復制列表的情況:
my_foods = ["pizza",'noodle','falafel']
#這行不通
friend_foods = my_foods
my_foods.append("cannoli")
friend_foods.append("ice cream")

print("My favorite foods are: ")
print(my_foods)

print("\nMy friend's favorite foods are: ")
print(friend_foods)
這里將my_foods賦給friend_foods,而不是將my_foods的副本存儲到friend_foods.這種語法實際上是讓Python將新變量friend_foods關聯到包含在
my_foods中的列表,因此這兩個變量都指向同一個列表。鑒於此,當我們將"cannoli"添加到my_foods中時,它也將出現在friend_foodsz中;同樣,雖然
"ice cream"好像只被加入到了friend_foods中,但它也將出現在這兩個列表中。
輸出表明,兩個列表是相同的,這並非我們想要的結果:
My favorite foods are:
['pizza', 'noodle', 'falafel', 'cannoli', 'ice cream']

My friend's favorite foods are:
['pizza', 'noodle', 'falafel', 'cannoli', 'ice cream']

下面來分析這種情況,因為我也是不太懂這種情況,但是學了之后了解了這樣的情況,Python中存儲元素的原理,怎樣開辟空間:

    當采用賦值的方式生成friend_foods的時候,my_foods和friend_foods公用一個內存,在Python中沒有開辟新的內存,上圖所示,只是關聯到了一起,所以當我們賦值的時候就變成下面的樣子:

    當我們向my_foods列表添加新的元素的時候,元素添加到原來的內存中;當我們向friend_foods中添加元素的時候,新的元素也是添加到了原來的內存列表中,所以采用賦值的時候,Python不會開辟新的內存,只是將兩個變量關聯到了一起,如上圖所以,所以最后兩者的結果還是一樣的。

    下面我們看使用切片的時候的情況:

     由於采用的是切片,切片開辟了一個新的內存列表,用於存儲friend_foods,當我們添加新的元素的時候如下圖:

    由於是兩個不同的內存開辟的列表,當向my_foods添加新的元素時,只添加到my_foods的內存列表中;當向friend_foods添加新的元素時,只向friend_foods所屬的內存列表中添加新的元素,所以輸出結果是不一樣的。

    因而,賦值和切片在Python中的運行機制是不一樣的,當我們賦值的時候,一定要注意這一點,以前沒有怎么注意,以后要注意。尤其在復制操作的時候。

總結:當我們讓一個參數等於另外一個參數的時候,直接a = b,這個時候是進行的賦值,當兩個參數之間進行賦值的時候,是共用的一個內存,Python

里面是沒有新開辟空間的。

動手試一試

    4-10 切片:選擇你在本章編寫的一個程序,在末尾添加幾行代碼,以完成如下任務。

    1、打印消息”The first three items in the list are:",在使用切片來打印列表的前三個元素;

    2、打印消息"Three items from the middle of list are: ",在使用切片來打印列表中間的三個元素;

    3、打印消息"The last three items in the list are: ",在使用切片來打印列表末尾三個元素。

    4-11 你的比薩和我的比薩:在你為完成練習4-1而編寫的程序中,創建比薩列表的副本,並將其存儲到變量friend_pizzas中,在完成如下任務。

    1、在原來的比薩列表中添加一種比薩;

    2、在列表friend_pizzas中添加另一種比薩;

    3、核實你有兩個不同的列表。為此,打印消息"My favorite pizzas are:",再使用一個for循環來打印第二個列表。核實新增的比薩被添加到了正確的列表中。

    4-10:本題主要考察列表切片的表示方法,如何進行列表切片的表示,尤其是L.[-1]表示最后一個元素,這種方法的使用很關鍵,考察最后幾個元素的時候都會用到,列表切片的表示是從第幾個元素到第幾個元素,中間用冒號進行分割。

    digits = [2,3,8,9,0,3,5,7]
    print("The first three items in the list are: ")
    print(digits[:3])

    print("\nThree items from the middle of the list are: ")
    print(digits[2:5])

    print("\nThe last three items in the list are: ")
    print(digits[-3:])

    運行結果如下:

    The first three items in the list are:
    [2, 3, 8]

    Three items from the middle of the list are:
    [8, 9, 0]

    The last three items in the list are:
    [3, 5, 7]

    4-11 本題主要考察的是切片的使用,已經列表的復制的方法,列表復制要通過切片來完成,Python的工作原理決定的。

    pizzas = ["New York Style","Chicago Style","California Style"]
    friend_pizzas = pizzas[:]

    pizzas.append("noodle")
    friend_pizzas.append("rice")

    print("My favorite pizzas are: ")
    for pizza in pizzas:
        print(pizza)
    print(pizzas)
 
    print("\nMy friend's favorite pizzas are: ")
    for friend_pizza in friend_pizzas:
        print(friend_pizza)
    print(friend_pizzas)

運行結果:

My favorite pizzas are:
New York Style
Chicago Style
California Style
noodle
['New York Style', 'Chicago Style', 'California Style', 'noodle']

My friend's favorite pizzas are:
New York Style
Chicago Style
California Style
rice
['New York Style', 'Chicago Style', 'California Style', 'rice']

 

4.5 元祖

    列表非常適合用於存儲在程序運行期間可能變化的數據集。列表是可以修改的,這對處理網站的用戶列表或游戲中的角色列表至關重要。然而,有時候我們需要創建一系列不可修改的元素,元祖可以滿足這種需求。Python將不能修改的值稱為不可變的,而不可變的列表被稱為元祖

4.5.1  定義元祖

    元祖看起來猶如列表,但使用圓括號而不是方括號來標識。定義元祖后,就可以使用索引來訪問其元素,就像訪問列表元素一樣。

    例如,如果有一個大小不應改變的矩形,可將其長度和寬度存儲在一個元祖中,從而確保它們是不能修改的:

    dimensions.py

    dimensions = (200,50)
    print(dimensions[0])
    print(dimensions[1])

    我們首先定義了元祖dimensions,為此我們使用了圓括號而不是方括號。接下來,我們分別打印該元祖的各個元素,使用的語法與訪問列表元素時使用的語法相同:

    200

    50

    由定義我們知道元祖的元素是不可以修改的,下面我們來嘗試修改元素dimensions中的一個元素,看看結果如何:

    dimensions = (200,50)
    dimensions[0] = 250
    print(dimensions)
    代碼試圖修改第一個元素的值,導致Python返回類型錯誤消息。由於試圖修改元祖的操作是被禁止的,因此Python指出不能給元祖的元素賦值:

    Traceback (most recent call last):
      File "/home/zhuzhu/title4/dimensions.py", line 2, in <module>
      dimensions[0] = 250
    TypeError: 'tuple' object does not support item assignment

    代碼試圖修改矩形的尺寸時,Python報告錯誤,這很好,因為這正是我們希望的。

4.5.2  遍歷元祖中的所有值

    像列表一樣,也可以使用for循環來遍歷元組中的所有值:

    dimensions = (200,50)
    for dimension in dimensions:
         print(dimension)

    就像遍歷列表時一樣,Python返回元組中所有的元素:

    200

    50

4.5.3  修改元組變量

    雖然不能修改元組的元素,但可以給存儲元組的變量賦值。因此,如果要修改前述矩形的尺寸,可重新定義整個元組:

    dimensions = (200,50)
    print("Original dimensions: ")
    for dimension in dimensions:
        print(dimension)

    dimensions = (400,100)
    print("\nModified dimensions: ")
    for dimension in dimensions:
         print(dimension)

    我們首先定義了一個元組,並將其存儲的尺寸打印了出來;接下來,將一個新元組存儲到變量dimensions中;然后,打印新的尺寸。這次,Python不會報告任何錯誤,因為給元組變量賦值是合法的:

    Original dimensions:
    200
    50

    Modified dimensions:
    400
    100

    相比於列表,元組是更簡單的數據結構.如果需要存儲的一組值在程序的整個生命周期內都不變,可使用元組。

 

動手試一試

    4-13 自助餐: 有一家自助式餐廳,只提供五種簡單的食品。請想出五種簡單的食品,並將其存儲在一個元祖中。

    1、使用一個for循環將該餐館提供的五種食品都打印出來;

    2、嘗試修改其中的一個元素,核實Python確實會拒絕我們這樣做;

    3、餐館調整了菜單,替換了它提供的某中兩種實物。請編寫一個這樣的代碼塊;給元組變量賦值,並使用一個for循環將新元組中的每個元素都打印出來。

    分析:本題主要考察元組的性質及用法,我們知道,元組中的元素是不可以修改的,但是元組是可以重新賦值的,我們雖然不能修改元組中的元素,但是我們可以整體修改元組,元組其他的性質跟列表的性質都是一樣的,就是不能對元組本身就行修改,比如添加,刪除,賦值等。

    cafeterias = ("rice","noodle","porridge","hamburger","pizza")
    for cafeteria in cafeterias:
         print(cafeteria)

    cafeterias[-1] = "dami"

    運行結果如下:

rice

noodle
porridge
hamburger
pizza
Traceback (most recent call last):
  File "/home/zhuzhu/title4/Cafeterias.py", line 5, in <module>
    cafeterias[-1] = "dami"
TypeError: 'tuple' object does not support item assignment

從運行結果可以看出,當我們試圖修改元組的元素是,發生了錯誤,提示我們不能修改元組的元組值

 

cafeterias = ("rice","noodle","porridge","hamburger","pizza")
print("Original menu: ")
for cafeteria in cafeterias:
print(cafeteria)

#cafeterias[-1] = "dami"
cafeterias = ("pizza",'hamburger','rice','milk','Drumsticks')
print("\nModified menu: ")
for cafeteria in cafeterias:
print(cafeteria)

運行結果如下:
Original menu:
rice
noodle
porridge
hamburger
pizza

Modified menu:
pizza
hamburger
rice
milk
Drumsticks
從運行結果可以看出,雖然我們不能修改元組中元素的值,但我們可以整體重新給元組進行賦值,這樣是允許的,因而我們可以對元組重新賦值,這是允許的,
也是合法的,系統不會報錯。

4.6 設置代碼格式
隨着我們編寫的程序越來越長,有必要了解一些代碼格式設置的約定。請花時間讓我們的代碼進可能易於閱讀;讓代碼易於閱讀有助於我們掌握程序是做什
么的,也可以幫助他人理解我們編寫的代碼。
為確保所有人編寫的代碼的結構都大致一致,Python程序員都遵循一些格式設置約定。學會編寫整潔的Python后,就能明白他人編寫的Python代碼的整體
結構——只要他們和你遵循相同的指南。要稱為專業程序員,應從現在開始就遵循這些指南,以養成良好的習慣。

4.6.1 格式設置指南
若要提出Python語言修改建議,需要編寫Python改進提案(Python Enhancement Proposal,PEP).PEP8是最古老的PEP之一,它向Python程序員提供了代
碼格式設置指南。PEP8的篇幅很長,但大都與復雜的編碼結構相關。
Python格式設置指南的編寫者深知,代碼被閱讀的次數比編寫的次數多。代碼編寫出來后,調試時你需要閱讀它;給程序添加新功能時,需要花很長的時間
閱讀代碼;與其他程序員分享代碼時,這些程序員也將閱讀它們。
如果一定要在代碼易於編寫和易於閱讀之間做出選擇,Python程序員幾乎總是選擇后者。下面的指南可幫助我們從一開始就編寫除清晰的代碼。

4.6.2 縮進
PEP 8建議每級縮進都使用四個空格,這即可提高可讀性,又留下了足夠的多級縮進空間。
在字處理文檔中,大家常常使用制表符而不是空格來縮進。對於字處理文檔來說,這樣做的效果很好,但混合使用制表符和空格會讓Python解釋器感到迷惑
。每款文本編輯器都提供了一種設置,可將輸入的制表符轉換為指定數量的空格。我們在編寫代碼時應該使用制表符鍵,但一定要對編輯器進行設置,使其在文
檔中插入空格而不是制表符。
在程序中混合制表符和空格可能導致極難解決的問題。如果我們混合使用了制表符和空格,可將文件中所有的制表符轉換為空格,大多數編輯器都提供了這
樣的功能。

4.6.3 行長
很多Python程序員都建議每行不超過80字符。最初制定這樣的指南時,在大多數計算機中,終端窗口每行只能容納79字符;當前,計算機屏幕每行可容納的
字符數多得多,為何還要使用79字符的標准行長呢?這里有別的原因。專業程序員通常會在同一個屏幕上打開多個文件,使用標准行長可以讓我們在屏幕上並排
打開兩三個文件時能同時看到各個文件的整行。PEP 8還建議注釋的行長都不超過72字符,因為有些工具為大型項目自動生成文檔時,會在每行注釋開頭添加格式
化字符。
PEP 8中有關行長的指南並非不可逾越的紅線,有些小組將最大行長設置為99字符。在學習期間,我們不用過多考慮代碼的行長,但別忘了,協作編寫程序,
大家幾乎都遵守PEP 8指南。在大多數編輯器中,都可設置一個視覺標志——通常是一條豎線,讓你知道不能越過的界限在什么地方。

4.6.4 空行
要將程序不同部分分開,可使用空行。我們應該使用空行來組織程序文件,但也不能濫用;只要按本書的示例展示的那樣做,就能掌握其中的平衡。例如,
如果我們有5行創建列表的代碼,還有3行處理該列表的代碼,那么用一個空行將這兩部分隔開是合適的。然而,我們不應該使用三四個空行將它們隔開。
空行不會影響代碼的運行,但會影響代碼的可讀性。Python解釋器根據水平縮進情況來解讀代碼,但不關心垂直間距。

 

 

 

   

 

 

 







 
 


 


 
 


 
 
 




 
 


 
 


 







 
        
 


 

Original menu:
rice
noodle
porridge
hamburger
pizza

Modified menu:
pizza
hamburger
rice
milk
Drumsticks


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM