導航:首頁 > 編程語言 > python中列表元素替換循環

python中列表元素替換循環

發布時間:2023-02-28 14:29:52

❶ 如何用 python 科學計算中的矩陣替代循環

因為在Mathematica中使用循環確實是低效的。。。。。。
深層次的原因涉及到Mathematica的底層實現所以我不太懂,但是至少從下面幾個例子可以看出Mathematica里確實有很多比循環更好的方法

求和
首先舉一個最簡單的求和例子,求的值。為了測試運行時間取n=10^6
一個剛接觸Mathematica的同學多半會這樣寫

sum = 0;
For[i = 1, i <= 10^6, i++,
sum += Sin[N@i]];
(*其中N@i的作用是把整數i轉化為浮點數,類似於C里的double*)
sum

為了便於計時用Mole封裝一下,運行時間是2.13秒,如下圖

然後一個有一定Mathematica經驗的同學多半會知道同樣作為循環的Do速度比For快,於是他可能會這么寫
然後一個有一定Mathematica經驗的同學多半會知道同樣作為循環的Do速度比For快,於是他可能會這么寫

sum = 0;
Do[sum += Sin[N@i], {i, 1, 10^6}];
sum

如下圖,用時1.37秒,比For快了不少

當然了知道Do速度比For快的同學不太可能不知道Sum函數,所以上面其實是我口胡的,他應該會這么寫

Sum[Sin[N@i], {i, 1, 10^6}]

如下圖,同樣的結果,只用了不到0.06秒

如果這位同學還知道Listable屬性並且電腦內存不算太小的話,他也可能會這么寫

Tr@Sin[N@Range[10^6]]

如下圖,只用了不到0.02秒,速度超過For循環的100倍

當然了這只是一個最簡單的例子,而且如果數據量更大的話最後一種方法就不能用了。但是這也足以說明在求和時用循環是低效的,無論是內置的Sum函數還是向量化運算,在效率上都遠遠高於循環
(這部分模仿了不同程序員如何編寫階乘函數這篇文章,強烈推薦對Mathematica有興趣的同學去看看)

迭代
接下來舉一個迭代的例子,(即Logistic map),取,為了測試運行時間同樣取n=10^6
還是先用For循環的做法

x = 0.5;
For[i = 1, i <= 10^6, i++,
x = 3.5 x (1 - x);
];
x

如下圖,運行時間2.06秒

(Do循環和For類似,篇幅所限這里就不寫了,有興趣的同學可以自行嘗試)
(Do循環和For類似,篇幅所限這里就不寫了,有興趣的同學可以自行嘗試)
然後看看內置的Nest函數

Nest[3.5 # (1 - #) &, 0.5, 10^6]

如下圖,用時0.02秒,又是將近兩個數量級的效率差異

當然了Nest的使用涉及到純函數,對於Mathematica初學者來說可能有些難以理解,而且一些比較復雜的迭代不太容易寫成Nest的形式,但是在迭代時Nest(還包括Fold)的效率確實要好於循環
當然了Nest的使用涉及到純函數,對於Mathematica初學者來說可能有些難以理解,而且一些比較復雜的迭代不太容易寫成Nest的形式,但是在迭代時Nest(還包括Fold)的效率確實要好於循環
遍歷列表
依然舉一個簡單的例子:求一個列表中偶數的個數。為測試生成10^6個1到10之間的隨機整數

list = RandomInteger[{1, 10}, 10^6];
(*生成10^6個隨機整數*)

如果用For循環的話代碼是這樣的

num = 0;
For[i = 1, i <= 10^6, i++,
If[EvenQ@list[[i]], num++]
];
num

如下圖,用時1.73秒

保留上面的思路,單純的將For循環改為Scan (相當於沒有返回結果的Map),代碼如下

num = 0;
Scan[If[EvenQ@#, num++] &, list];
num

如下圖,用時0.91 秒

(Do循環用時1.00秒左右,篇幅所限就不傳圖了)

摒棄循環的思路,用其他內置函數寫

Count[list, _?EvenQ] // AbsoluteTiming
(*直接用Count數出list中偶數的個數*)
Count[EvenQ /@ list, True] // AbsoluteTiming
(*用Map對list中的每個數判斷是否偶數,然後用Count數出結果中True的個數*)
Select[list, EvenQ] // Length // AbsoluteTiming
(*選取list中的所有偶數,然後求結果列表長度*)
Count[EvenQ@list, True] // AbsoluteTiming
(*利用EvenQ的Listable屬性直接判斷list的每個數是否偶數,然後數出結果中True的個數*)
Sum[Boole[EvenQ@i], {i, list}]
(*對list中的每個元素判斷是否偶數,將結果相加*)

結果如下圖

這個遍歷的例子舉得不算特別恰當,但也能說明一些問題了:Mathematica中內置了許多神奇的函數,其中大部分只要使用得當效率都比循環高(而且不是一點半點)。就算非要用循環,也要記得(任何能用Do代替For的時候)
這個遍歷的例子舉得不算特別恰當,但也能說明一些問題了:Mathematica中內置了許多神奇的函數,其中大部分只要使用得當效率都比循環高(而且不是一點半點)。就算非要用循環,也要記得(任何能用Do代替For的時候)
Do比For快
,(遍歷列表時)
Scan比Do快
用向量(矩陣)運算代替循環
這個例子來自如何用 Python 科學計算中的矩陣替代循環? - Kaiser 的回答,我只是把代碼從Python翻譯成了Mathematica而已。選這個例子是因為它有比較明確的物理意義,而且效率對比非常明顯
代碼如下

AbsoluteTiming[
n = 100;
u = unew = SparseArray[{{1, _} -> 1}, {n, n}] // N // Normal;
For[k = 1, k <= 3000, k++,
For[i = 2, i < n, i++,
For[j = 2, j < n, j++,
unew[[i, j]] =
0.25 (u[[i + 1, j]] + u[[i - 1, j]] + u[[i, j + 1]] +
u[[i, j - 1]])
]
];
u = unew;
];
u1 = u;
]
(*用三重循環,迭代3000次*)
ArrayPlot[u1, DataReversed -> True, ColorFunction -> "TemperatureMap"]
(*用ArrayPlot繪圖*)

AbsoluteTiming[
n = 100;
u = SparseArray[{{1, _} -> 1}, {n, n}] // N // Normal;
Do[
u[[2 ;; -2, 2 ;; -2]] =
0.25 (u[[3 ;; -1, 2 ;; -2]] + u[[1 ;; -3, 2 ;; -2]] +
u[[2 ;; -2, 3 ;; -1]] + u[[2 ;; -2, 1 ;; -3]]),
{k, 1, 3000}];
u2 = u;
]
(*用矩陣運算,迭代3000次*)
ArrayPlot[u2, DataReversed -> True, ColorFunction -> "TemperatureMap"]
(*用ArrayPlot繪圖*)

運行結果For循環用時136秒,矩陣運算用時不足0.5秒,且兩者答案完全一樣。在演算法完全相同的情況下兩種寫法有著超過200倍的效率差距
(圖片太長了這里就不直接顯示了,鏈接放在下面)
http://pic4.mg.com/_b.png

===========================我是結尾的分隔線===============================
這個答案其實從一開始就跑題了,還寫了這么長的目的就在於希望讓大家切實地感受到循環的低效並安利一下Mathematica中其它高效的方法。正如wolray的答案中說的,既然選擇了使用Mathematica就應該多利用些MMA獨有的美妙函數,畢竟如果只是用循環的話C和Fortran之類的語言效率比MMA不知高到哪裡去了。。。。。。

然我也不是讓大家就不用循環了,畢竟很多時候循環的直觀性和易讀性帶來的便利遠遠比那點效率重要。只是希望大家在循環之前能稍稍想一下,自己的目的是不是
一定要用循環?可不可以用內置函數代替循環?就像上面的幾個例子,將循環換成內置函數程序的簡潔性和效率都大幅提高,長此以往相信你一定會愛上MMA的~

題外話——關於用編譯提速循環

MMA中如果一定要使用循環又對效率有一定要求的話,可以選擇使用編譯,效率能有極大的提高。比如上面的第4個例子使用Complie編譯過後的Do循環
用時只有1.86秒,速度提升了將近100倍。如果電腦中有C編譯器的話還可以在Compile中加入CompilationTarget ->
"C"選項,速度還能有所提升。編譯過後的代碼如下:

In[10]:= cf = Compile[{{n, _Integer}, {times, _Integer}},
Mole[{u},
u = ConstantArray[0., {n, n}];
u[[1]] = ConstantArray[1., n];
Do[
Do[u[[i, j]] =
0.25 (u[[i + 1, j]] + u[[i - 1, j]] + u[[i, j + 1]] +
u[[i, j - 1]]),
{i, 2, n - 1}, {j, 2, n - 1}
], {k, 1, times}];
u
]
];
u3 = cf[100, 3000]; // AbsoluteTiming
ArrayPlot[u3, DataReversed -> True, ColorFunction -> "TemperatureMap"]

Out[11]= {1.86055, Null}

前3個例子也都可以通過編譯提速很多,這里就不放代碼了,有興趣的同學可以自己動手試一試,如果遇到問題歡迎在評論中與我交流。
需要注意的是編譯有很多注意事項,這里推薦一篇寫的很好的教程,編譯中常見的問題裡面都有很好的講解:怎樣編譯(Compile)/編譯的通用規則/學會這6條,你也會編譯
但是一般來講編譯很麻煩,而且再怎麼編譯效率也很難趕上直接用C,所以個人並不特別建議MMA初學者學習編譯。

❷ python編程中編寫循環的技巧

編寫循環的技巧,for循環包含了常見的計數器式循環。由於通常for循環比while循環更容易寫,也執行得更快,所以for循環一般是你遍歷序列或其他可迭代對象時的首選。事實上,作為一條通用法則,你應該克制在Python中使用計數方式的誘惑——Python提供的迭代工具,能幫你把像C這樣低級語言中循環集合體的工作自動化。不過,有些情況下你還是需要以更為特定的方式進行迭代。例如,如果你需要在列表中每隔一個元素或每隔兩個元素進行訪問,或是要同時修改列表呢?如果在同一個for循環內,並行遍歷一個以上的序列呢?如果你也需要進行索引呢?
你總是可以用while循環和手動索引運算來編寫這些獨特的循環,但是python提供了一套內置函數,可以幫你在for循環內定製迭代:·內置函數range (Python 0.X及之後版本可用)返回一系列連續增加的整數,可作為for中的索引。內置函數zip (Python 2.0及之後版本可用)返回一系列並行元素的元組,可用於在for中內遍歷多個序列。內置函數enumerate (Python 2.3及之後版本可用)同時生成可迭代對象中元素的值和索引,因而我們不必再手動計數。內置函數map (Python 1.0及之後版本可用)在Python 2.X中與zip有著相似的效果,但是在3.X中 map 的這一角色被移除了。因為for循環可能會比基於while的計數器循環運行得更快,所以藉助這些工具並盡可能地使用for循環,會讓你受益匪淺。讓我們在常見的使用場景下,依次看一看這些內置函數吧。我們將會看到,它們的用法在Python 2.X和3.X中稍有不同,同時它們中的一些要比其他的更加有效。

❸ python中如何修改列表中元素

在python中,前綴r或r表示「自然字元串」,特殊字元失去意義,所見即所得,這個設計類似perl的「單引號字元串」。

一般字元串newlinesareindicatedby\\n

等價於「自然字元串」

rnewlinesareindicatedby\n

和一般字元串相比,自然字元串里的\不再具有特殊含義,於是可以省去了一個\

在描述正則表達式時,推薦使用自然字元串,否則整行都是轉義字元\

❹ python用for遍歷列表時不能修改列表值嗎

首先,可以肯定的是,for 循環遍歷時可以修改列表值。
那麼問題出在哪?在for 循環中的賦值語句magician='the Great' + magician,這個語句並沒有改變列表元素,在for magician in magicians中,magician 只是一個得到了列表元素的值的臨時變數,修改這個臨時變數並不會影響的列表裡的值。
原代碼相當於:magician =magicians[i], magician ='theGreat'+magician, 很明顯,這里沒有影響到列表元素,而是只改變了臨時變數。
可以使用以下代碼:
for i in range(len(magicians)):
magicians[i] = 'the Great' + magicians[i]

閱讀全文

與python中列表元素替換循環相關的資料

熱點內容
如何開啟app步數授權 瀏覽:22
linuxmaven路徑 瀏覽:135
python爬qq說說 瀏覽:416
linuxmap文件 瀏覽:67
轉轉app如何搜索快手主播 瀏覽:776
移動硬碟文件夾成0位元組 瀏覽:683
夢幻西遊解壓視頻大全 瀏覽:252
解壓小視頻手速 瀏覽:152
我的世界伺服器卡沒血如何修改 瀏覽:161
vba入門到精通pdf 瀏覽:113
tomcat怎麼一個伺服器部署 瀏覽:797
phphttps介面 瀏覽:895
javabyte數組int 瀏覽:810
公司網路共享的文件夾 瀏覽:1000
拍臉搭配衣服是什麼app 瀏覽:916
歐珀手機怎麼更改加密密碼 瀏覽:508
程序員那麼可愛陸漓氣人語錄 瀏覽:904
python中del刪除 瀏覽:461
華為雲耀伺服器和ecs區別 瀏覽:730
ruby語法編譯語言 瀏覽:573