亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在Python中簡化循環金字塔?

如何在Python中簡化循環金字塔?

慕絲7291255 2019-10-09 17:44:02
在實體力學中,我經常使用Python并編寫類似于以下內容的代碼:for i in range(3):    for j in range(3):        for k in range(3):            for l in range(3):                # do stuff我經常這樣做,以至于我開始懷疑是否有更簡潔的方法可以做到這一點。當前代碼的缺點是:如果我遵守PEP8,那么我就不能超過每行79個字符的限制,并且沒有太多的空間,特別是如果這又是一個類的函數。
查看完整描述

3 回答

?
郎朗坤

TA貢獻1921條經驗 獲得超9個贊

根據您要執行的操作,您可以使用該itertools模塊來最大程度地減少for循環(或zip)。在這種情況下,itertools.product將創建您使用4個循環完成的工作:


>>> list(product(range(3),repeat=4))

[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 1, 0), (0, 0, 1, 1),

 (0, 0, 1, 2), (0, 0, 2, 0), (0, 0, 2, 1), (0, 0, 2, 2), (0, 1, 0, 0),

 (0, 1, 0, 1), (0, 1, 0, 2), (0, 1, 1, 0), (0, 1, 1, 1), (0, 1, 1, 2),

 (0, 1, 2, 0), (0, 1, 2, 1), (0, 1, 2, 2), (0, 2, 0, 0), (0, 2, 0, 1),

 (0, 2, 0, 2), (0, 2, 1, 0), (0, 2, 1, 1), (0, 2, 1, 2), (0, 2, 2, 0),

 (0, 2, 2, 1), (0, 2, 2, 2), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 0, 2),

 (1, 0, 1, 0), (1, 0, 1, 1), (1, 0, 1, 2), (1, 0, 2, 0), (1, 0, 2, 1),

 (1, 0, 2, 2), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 0, 2), (1, 1, 1, 0),

 (1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 2, 0), (1, 1, 2, 1), (1, 1, 2, 2),

 (1, 2, 0, 0), (1, 2, 0, 1), (1, 2, 0, 2), (1, 2, 1, 0), (1, 2, 1, 1),

 (1, 2, 1, 2), (1, 2, 2, 0), (1, 2, 2, 1), (1, 2, 2, 2), (2, 0, 0, 0),

 (2, 0, 0, 1), (2, 0, 0, 2), (2, 0, 1, 0), (2, 0, 1, 1), (2, 0, 1, 2),

 (2, 0, 2, 0), (2, 0, 2, 1), (2, 0, 2, 2), (2, 1, 0, 0), (2, 1, 0, 1),

 (2, 1, 0, 2), (2, 1, 1, 0), (2, 1, 1, 1), (2, 1, 1, 2), (2, 1, 2, 0),

 (2, 1, 2, 1), (2, 1, 2, 2), (2, 2, 0, 0), (2, 2, 0, 1), (2, 2, 0, 2),

 (2, 2, 1, 0), (2, 2, 1, 1), (2, 2, 1, 2), (2, 2, 2, 0), (2, 2, 2, 1),

 (2, 2, 2, 2)]

在您的代碼中,您可以執行以下操作:


for i,j,k,l in product(range(3),repeat=4):

    #do stuff

此函數等效于以下代碼,不同之處在于實際實現不會在內存中建立中間結果:


def product(*args, **kwds):

    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy

    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111

    pools = map(tuple, args) * kwds.get('repeat', 1)

    result = [[]]

    for pool in pools:

        result = [x+[y] for x in result for y in pool]

    for prod in result:

        yield tuple(prod)

編輯:正如@ PeterE在評論中所說,product()即使范圍的長度不同,也可以使用:


product(range(3),range(4),['a','b','c'] ,some_other_iterable)


查看完整回答
反對 回復 2019-10-09
?
慕尼黑的夜晚無繁華

TA貢獻1864條經驗 獲得超6個贊

使用的想法itertools.product是一個好主意。這是一種更通用的方法,將支持各種大小的范圍。


from itertools import product


def product_of_ranges(*ns):

    for t in product(*map(range, ns)):

        yield t


for i, j, k in product_of_ranges(4, 2, 3):

    # do stuff


查看完整回答
反對 回復 2019-10-09
?
繁華開滿天機

TA貢獻1816條經驗 獲得超4個贊

它不會更加簡潔,因為它將花費您一個生成器函數,但是至少您不會被PEP8所困擾:


def tup4(n):

    for i in range(n):

        for j in range(n):

            for k in range(n):

                for l in range(n):

                    yield (i, j, k, l)


for (i, j, k, l) in tup4(3):

    # do your stuff

(在python 2.x中,您應該使用xrange而不是range在generator函數中)


編輯:


當金字塔的深度已知時,上述方法應該很好。但是您也可以通過這種方式生成通用生成器,而無需任何外部模塊:


def tup(n, m):

    """ Generate all different tuples of size n consisting of integers < m """

    l = [ 0 for i in range(n)]

    def step(i):

        if i == n : raise StopIteration()

        l[i] += 1

        if l[i] == m:

            l[i] = 0

            step(i+ 1)

    while True:

        yield tuple(l)

        step(0)


for (l, k, j, i) in tup(4, 3):

    # do your stuff

(我用過,(l, k, j, i)因為在上面的生成器中,第一個索引首先變化)


查看完整回答
反對 回復 2019-10-09
  • 3 回答
  • 0 關注
  • 777 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號