我在学习协同过滤,遇到这样一段代码
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]])
怪我咯2017-04-17 17:54:13
The first parameter accepted by sum is an iterable. If you want to know the meaning of this for loop, you need to check the generator and the syntactic sugar related to the generator. Here is a simple example for you [i for i in range(5)] # 结果为[0,1,2,3,4]
PHP中文网2017-04-17 17:54:13
The for
or if
here have nothing to do with sum
itself. As @大quail said, sum
accepts an iterable object as a parameter. As for the iterable object in this example, it is a list generated using list comprehension. for
或是 if
都跟 sum
本身沒有什麼關係,如同 @大鹌鹑 所說,sum
接受一個可迭代的對象作為參數,至於這個例子中的可迭代對象就一個 使用 list comprehension 產生的 list。
那就稍為介紹一下 list comprehension(串列產生式) 好了。
這是一個帶有 functional programming 味道的語法,直覺而優雅。
顧名思義,他是為了產生 串列 而被使用。
因此有一個重要的原則就是:
當今天代碼的目的是為了要生成一個 list ,那我們應當考慮使用他,否則完全不應該使用
我們來看一下用法,非常簡單的,為了生成串列,所以我們字面上使用兩個成對的中括號 []
( list 的字面產生語法),夾住一個 for...in...
迭代式,利用 for
走訪到的元素會被依序用來製造 list 中的各個元素。
讓我們看例子,假設今天我們有一個整數的串列 lst
,我們想要製造另外一個串列 lst2
,其中的每個元素都是 lst
中元素的平方:
lst = [1, 2, 3, 4]
lst2 = []
for i in lst:
lst2.append(i**2)
我們使用了一個標準的 for...in...
迴圈來作到這件事,但同樣的事情,我們能夠用 list comprehension 作得更簡潔更優雅:
lst = [1, 2, 3, 4]
lst2 = [i**2 for i in lst]
在這個例子中,for i in lst
會依序取出 lst
中的元素進行平方運算後成為 lst2
的新元素。 這讓人聯想到 map
function,我們同樣可以使用 映射 來作到類似的效果:
lst = [1, 2, 3, 4]
lst2 = map(lambda x:x**2, lst) # Python2
lst2 = list(map(lambda x:x**2, lst)) # Python3
map
會依序走訪他第二個參數(一個可迭代對象)中的元素,並且將元素作為引數,調用他的第一個參數(一個單參數函數),也就是會依序取出 1, 2, 3 ,4 然後將之當成參數 x
調用匿名函數 lambda x:x**2
。
但我們可以發現 list comprehension 更加直覺,我們可以說 list comprehension 中的 for
述句就是在 map
的良好替代品。
說到 map
就會想到 filter
,他會對可迭代物件進行過濾的動作。
比如說我想讓 lst2
裡面只出現奇數:
lst = [1, 2, 3, 4]
lst2 = filter(lambda x:x%2!=0, map(lambda x:x**2, lst)) # Python2
lst2 = list(filter(lambda x:x%2!=0, map(lambda x:x**2, lst))) # Python3
filter
一樣會去走訪他的第二個參數(一個可迭代對象),並依序取出當成引數,調用他的第一個參數(一個單參數函數),若運算的結果為真( True
),則保留此回傳值作為新的元素,反之( False
)會被過濾掉。
而現在 filter
#🎜🎜#When the purpose of today’s code is to generate a list, then we should consider using it, otherwise we should not use it at all #🎜🎜#
[]
(the literal generation syntax of list), clamp A for...in...
iteration, the elements visited using for
will be used to create each element in the list in sequence. #🎜🎜#
#🎜🎜#Let's look at an example. Suppose today we have a sequence of integers lst
, and we want to create another sequence lst2
in which each element is Is the square of the elements in lst
: #🎜🎜#
lst = [1, 2, 3, 4]
lst2 = [i**2 for i in lst if i%2!=0]
#🎜🎜#We used a standard for...in...
loop to do this, but for the same thing, we can use list comprehension Make it more concise and elegant: #🎜🎜#
sum([pow(prefs[person1][item]-prefs[person2][item],2)
for item in prefs[person1] if item in prefs[person2]])
#🎜🎜#In this example, for i in lst
will sequentially take out the elements in lst
and perform a square operation to become the new element of lst2
element. This is reminiscent of the map
function. We can also use map to achieve similar effects: #🎜🎜#
rrreee
#🎜🎜#map
will sequentially visit the elements in its second parameter (an iterable object), and use the elements as arguments to call its first parameter (a single-parameter function) , that is, 1, 2, 3, and 4 will be taken out in sequence and then used as parameters x
to call the anonymous function lambda x:x**2
. #🎜🎜#
#🎜🎜#But we can find that list comprehension is more intuitive, and we can say that the for
statement in list comprehension is a good substitute for map
. #🎜🎜#
map
, filter
will come to mind, which will perform filtering actions on iterable objects. #🎜🎜#
#🎜🎜#For example, I want only odd numbers to appear in lst2
: #🎜🎜#
rrreee
#🎜🎜#filter
will also access its second parameter (an iterable object), take it out as arguments in sequence, and call its first parameter (a single-parameter function). If the result of the operation is true ( True
), the returned value will be retained as a new element, otherwise ( False
) will be filtered out. #🎜🎜#
#🎜🎜#Now filter
also has a replacement, which is list comprehension. We can write like this: #🎜🎜#rrreee
It’s also much simpler! We can say that the if
statement in list comprehension is a good substitute for 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...
statement and a if
statement to generate a list. The sum
function is called with this list as an argument. #🎜🎜#
for...in...
and if
are not directly related to sum
. #🎜🎜##🎜🎜#
for...in...
and if
are the key syntax of list comprehension. #🎜🎜##🎜🎜#
map
and filter
. #🎜🎜##🎜🎜#
#🎜🎜#