簡體   English   中英

Python的列表推導和其他更好的實踐

[英]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有一個專門用於列表推導的部分 還有這個很好的教程可供閱讀。

更新

我忘了說些什么。 列表推導是實現傳統上使用mapfilter完成的另一種方式。 如果你想提高你的理解能力,理解mapfilter工作方式是個好主意。

對於復制部分,查看復制模塊,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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM