我在学习协同过滤,遇到这样一段代码
def sim_distance(prefs,person1,person2):
# Get the list of shared_items
si={}
for item in prefs[person1]:
if item in prefs[person2]: si[item]=1
# if they have no ratings in common, return 0
if len(si)==0: return 0
# Add up the squares of all the differences
sum_of_squares=sum([pow(prefs[person1][item]-prefs[person2][item],2)
for item in prefs[person1] if item in prefs[person2]])
return 1/(1+sum_of_squares)
比较困惑的是下面这段代码,为什么sum里面可以写for 循环呢,这个是什么意思,为什么我写了个类似的函数就会报错
sum([pow(prefs[person1][item]-prefs[person2][item],2)
for item in prefs[person1] if item in prefs[person2]])
sum接受的第一個參數是個iterable。樓主想知道這個for循環的含義,要去查看一下生成器以及生成器相關的語法糖,這裡給樓主一個簡單的例子
[i for i in range(5)] # 结果为[0,1,2,3,4]
這邊的
for
或if
都跟sum
本身沒有什麼關係,如同@大鵪鶉所說,sum code> 接受一個可迭代的物件作為參數,至於這個範例中的可迭代物件就一個使用list comprehension 產生的list。
for
或是if
都跟sum
本身沒有什麼關係,如同 @大鹌鹑 所說,sum
接受一個可迭代的對象作為參數,至於這個例子中的可迭代對象就一個 使用 list comprehension 產生的 list。那就稍為介紹一下 list comprehension(串列產生式) 好了。
這是一個帶有 functional programming 味道的語法,直覺而優雅。
顧名思義,他是為了產生 串列 而被使用。
因此有一個重要的原則就是:
我們來看一下用法,非常簡單的,為了生成串列,所以我們字面上使用兩個成對的中括號
[]
( list 的字面產生語法),夾住一個for...in...
迭代式,利用for
走訪到的元素會被依序用來製造 list 中的各個元素。讓我們看例子,假設今天我們有一個整數的串列
lst
,我們想要製造另外一個串列lst2
,其中的每個元素都是lst
中元素的平方:我們使用了一個標準的
for...in...
迴圈來作到這件事,但同樣的事情,我們能夠用 list comprehension 作得更簡潔更優雅:在這個例子中,
for i in lst
會依序取出lst
中的元素進行平方運算後成為lst2
的新元素。 這讓人聯想到map
function,我們同樣可以使用 映射 來作到類似的效果:map
會依序走訪他第二個參數(一個可迭代對象)中的元素,並且將元素作為引數,調用他的第一個參數(一個單參數函數),也就是會依序取出 1, 2, 3 ,4 然後將之當成參數x
調用匿名函數lambda x:x**2
。但我們可以發現 list comprehension 更加直覺,我們可以說 list comprehension 中的
for
述句就是在map
的良好替代品。說到
map
就會想到filter
,他會對可迭代物件進行過濾的動作。比如說我想讓
lst2
裡面只出現奇數:filter
一樣會去走訪他的第二個參數(一個可迭代對象),並依序取出當成引數,調用他的第一個參數(一個單參數函數),若運算的結果為真(True
),則保留此回傳值作為新的元素,反之(False
)會被過濾掉。而現在
filter
那就稍為介紹一下 list comprehension(串列產生式) 好了。 🎜 🎜這是一個帶有 functional programming 味道的語法,直覺而優雅。 🎜 🎜顧名思義,他是為了產生 串列 而被使用。 🎜 🎜因此有一個重要的原則就是:🎜
🎜我們來看看用法,非常簡單的,為了產生串列,所以我們字面上使用兩個成對的中括號
[]
( list 的字面產生語法),夾住一個for...in...
迭代式,利用for
造訪的元素會被依序用來製造list 中的各個元素。 🎜 🎜讓我們來看例子,假設今天我們有一個整數的串列lst
,我們想要製造另外一個串列lst2
,其中的每個元素都是lst
中元素的平方:🎜 🎜我們使用了一個標準的for...in...
迴圈來做這件事,但同樣的事情,我們能夠用list comprehension 作得更簡潔更優雅:🎜 🎜在這個例子中,for i in lst
會依序取出lst
中的元素平方運算後成為lst2
的新元素。 這讓人聯想到map
function,我們同樣可以使用 映射 來做類似的效果:🎜 rrreee 🎜map
會依序走訪他第二個參數(一個可迭代物件)中的元素,並且將元素當作引數,呼叫他的第一個參數(一個單參數函數),也就是會依序取出1, 2, 3 ,4 然後將之當成參數x
呼叫匿名函數lambda x:x**2
。 🎜 🎜但我們可以發現 list comprehension 比較直覺,我們可以說 list comprehension 中的for
述句就是在map
的好替代品。 🎜🎜說到
map
就會想到filter
,他會對可迭代物件進行過濾的動作。 🎜 🎜比如說我想讓lst2
裡面只出現奇數:🎜 rrreee 🎜filter
一樣會去走訪他的第二個參數(一個可迭代對象),並依序取出當成引數,調用他的第一個參數(一個單參數函數),若運算的結果為真(True
),則保留此回傳值作為新的元素,反之(False
)會被過濾掉。 🎜 🎜而現在filter
也有了替代品,就是 list comprehension,我們可以這樣寫:🎜rrreee同樣也是簡單許多! 我們可以說 list comprehension 中的
if
述句就是filter
的好替代品。if
述句就是filter
的良好替代品。看到這裡,相信你已經明白:
rrreee這段代碼,是先執行了一個含有
for...in...
述句和if
述句的 list comprehension 來產生 list 後,才以該 list 作為引數調用sum
函數。結論:
for...in...
和if
與sum
沒有直接關係。for...in...
和if
是 list comprehension 的關鍵語法。list comprehension 可以幫助我們使用可迭代對象產生 list。
list comprehension 是
map
和filter
看到這裡,相信你已經明白:
for...in...
述句和if
述句的list comprehension 來產生list 後,才以該list 作為引數呼叫sum
函數。 🎜🎜結論:🎜
for...in...
和if
與sum
沒有直接關係。 🎜🎜for...in...
和if
是 list comprehension 的關鍵語法。 🎜🎜map
和filter
的好替代品。 🎜🎜 🎜