[英]Python's list comprehensions and other better practices
這涉及將SAS中的雙向ANOVA程序轉換為Python的項目。
我周四開始嘗試學習這門語言,所以我知道我還有很大的提升空間。 如果我遺漏一些明顯的東西,請務必告訴我。 我還沒有Sage運行起來,也沒有numpy,所以現在,這都是非常普通的Python 2.6.1。 (便攜式)
主要查詢:需要一組良好的列表推導,這些列表推導可以按因子A,因子B,整體以及因子A和B(AxB)的每個級別的組中的列表中的樣本列表中提取數據。
完成一些工作后,數據采用以下形式(3層嵌套列表):
反應[A] [B] [n]的
(意為[a1 [b1 [n1,...,nN] ... [bB [n1,... nN]]],...,[aA [b1 [n1,...,nN] .. 。[bB [n1,... nN]]]希望這很清楚。)
我的例子中的因子水平:A = 3(0-2),B = 8(0-7),N = 8(0-7)
byA= [[a[i] for i in range(b)] for a[b] in response]
(有人可以解釋為什么這種語法有效嗎?我偶然發現它試圖看看解析器會接受什么。我沒有看到那種語言附加到其他地方的行為,但它真的很好。網站上的任何好鏈接或關於該主題的書籍編輯:運行之間變量的持久性解釋了這種奇怪。它不起作用。)
byB=lstcrunch([[Bs[i] for i in range(len(Bs)) ]for Bs in response])
(值得注意的是, zip(*response)
幾乎可以實現我想要的。上面的版本實際上並沒有工作,我記得。我還沒有經過仔細的測試。)
byAxB= [item for sublist in response for item in sublist]
(從Alex Martelli在本網站上的回復中竊取。再次有人可以解釋為什么 ?列表理解語法在我讀過的文本中沒有得到很好的解釋。)
ByO= [item for sublist in byAxB for item in sublist]
(顯然,我只是重復使用前面的理解,因為它做了我需要的。編輯:)
我希望它們能夠以相同的數據類型結束相同的數據類型,至少在有問題的因素循環時,可以應用和使用相同的平均值/ sum / SS / et cetera函數。
這很容易被更清潔的東西取代:
def lstcrunch(Dlist):
"""Returns a list containing the entire
contents of whatever is imported,
reduced by one level.
If a rectangular array, it reduces a dimension by one.
lstcrunch(DataSet[a][b]) -> DataOutput[a]
[[1, 2], [[2, 3], [2, 4]]] -> [1, 2, [2, 3], [2, 4]]
"""
flat=[]
if islist(Dlist):#1D top level list
for i in Dlist:
if islist(i):
flat+= i
else:
flat.append(i)
return flat
else:
return [Dlist]
哦,當我談論這個主題時,將變量識別為列表的首選方法是什么? 我一直在使用:
def islist(a):
"Returns 'True' if input is a list and 'False' otherwise"
return type(a)==type([])
分手查詢:有沒有辦法明確強制淺拷貝轉換為深? 復制? 或者,類似地,當復制到變量時,有沒有辦法聲明賦值也應該替換指針,而不僅僅是值? (分配不會傳播到其他淺層副本)同樣,使用它也可能是有用的,不時,所以能夠控制它何時發生或不發生聲音真的很好。 (當我通過調用准備我的表格插入時,我真的全身心投入:response = [[[0] * N] * B] * A)
編輯 :進一步調查導致大部分工作正常。 我已經上課並測試了它。 它工作正常。 我將保留列表理解表格以供參考。
def byB(array_a_b_c):
y=range(len(array_a_b_c))
x=range(len(array_a_b_c[0]))
return [[array_a_b_c[i][j][k]
for k in range(len(array_a_b_c[0][0]))
for i in y]
for j in x]
def byA(array_a_b_c):
return [[repn for rowB in rowA for repn in rowB]
for rowA in array_a_b_c]
def byAxB(array_a_b_c):
return [rowB for rowA in array_a_b_c
for rowB in rowA]
def byO(array_a_b_c):
return [rep
for rowA in array_a_b_c
for rowB in rowA
for rep in rowB]
def gen3d(row, col, inner):
"""Produces a 3d nested array without any naughty shallow copies.
[row[col[inner]] named s.t. the outer can be split on, per lprn for easy display"""
return [[[k for k in range(inner)]
for i in range(col)]
for j in range(row)]
def lprn(X):
"""This prints a list by lines.
Not fancy, but works"""
if isiterable(X):
for line in X: print line
else:
print x
def isiterable(a):
return hasattr(a, "__iter__")
感謝大家的回應。 由於我的gnosis改進,已經看到代碼質量明顯改善。 當然,還有進一步的想法。
byAxB= [item for sublist in response for item in sublist]
再次有人可以解釋原因嗎?
我相信AM能夠給你一個很好的解釋。 這是我在等待他出現時的刺痛。
我會從左到右接近這個。 拿這四個字:
for sublist in response
我希望你能看到與常規for
循環的相似之處。 這四個字正在做好基礎工作,以便對每個sublist
進行response
。 似乎response
是一個列表列表。 在這種情況下, sublist
將是每次迭代通過response
的列表。
for item in sublist
這又是另一種for
在決策圈。 鑒於我們首先聽說過前一個“循環”中的sublist
,這表明我們現在遍歷子列表,一次一個item
。 如果我在沒有理解的情況下編寫這些循環,它將如下所示:
for sublist in response:
for item in sublist:
接下來,我們看看剩下的單詞。 [
, item
和]
。 這實際上意味着,收集列表中的項目並返回結果列表。
每當您在創建或理解列表迭代時遇到問題,請寫出相關的for
循環,然后壓縮它們:
result = []
for sublist in response:
for item in sublist:
result.append(item)
這將壓縮為:
[
item
for sublist in response
for item in sublist
]
列表理解語法在我讀過的文本中沒有得到很好的解釋
Dive Into Python有一個專門用於列表推導的部分 。 還有這個很好的教程可供閱讀。
更新
我忘了說些什么。 列表推導是實現傳統上使用map
和filter
完成的另一種方式。 如果你想提高你的理解能力,理解map
和filter
工作方式是個好主意。
對於復制部分,查看復制模塊,python只是在創建第一個對象后使用引用,因此其他“副本”中的任何更改都會傳播回原始文件,但復制模塊會生成對象的真實副本,您可以指定幾個復制模式
在您的數據結構中產生正確級別的遞歸有時會很奇怪,但我認為在您的情況下它應該相對簡單。 為了在我們做的時候測試它,我們需要一個樣本數據,比如說:
data = [ [a,
[b,
range(1,9)]]
for b in range(8)
for a in range(3)]
print 'Origin'
print(data)
print 'Flat'
## from this we see how to produce the c data flat
print([(a,b,c) for a,[b,c] in data])
print "Sum of data in third level = %f" % sum(point for point in c for a,[b,c] in data)
print "Sum of all data = %f" % sum(a+b+sum(c) for a,[b,c] in data)
對於類型檢查,通常你應該避免它,但如果你必須,因為你不想在字符串中進行遞歸,你可以這樣做
if not isinstance(data, basestring) : ....
如果你需要展平結構,你可以在Python文檔中找到有用的代碼(表達它的其他方式是chain(*listOfLists))
和列表理解[ d for sublist in listOfLists for d in sublist ]
:
from itertools import flat.chain
def flatten(listOfLists):
"Flatten one level of nesting"
return chain.from_iterable(listOfLists)
如果您有不同深度的數據,這不起作用。 對於重量較重的扁平劑,請參見: http : //www.python.org/workshops/1994-11/flatten.py ,
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.