【问题标题】:One line for looping with operation in python在python中循环操作的一行
【发布时间】:2017-10-08 02:01:58
【问题描述】:

我对循环代码有优化问题:

我的代码是这样的:

total = 0
result = []
for test in testing:
    total += test.amount
    result.append({'category': test.category, 'value': test.amount})

我需要将代码优化为一行。我试图将代码更改为

total = 0 
result = [ {'category': test.category, 'value': test.amount} for test in testing]

但我无法优化操作总数

感谢您的帮助。

【问题讨论】:

  • 您需要描述您的问题,而不仅仅是说您有问题。更具体一些,告诉我们您尝试了什么
  • @shafeen 我需要将代码优化为一行。我试图将代码更改为 total = 0 result = [ {'category': test.category, 'value': test.amount} for test in testing] 但我无法优化操作总数
  • 你在优化什么?你试过什么?
  • “优化代码到一行”是什么意思,优化是什么意思?
  • 单行并不意味着它会是最优的。

标签: python for-loop optimization


【解决方案1】:

我计时了几个变体供您比较:

from functime import functime


class test_class:

    def __init__(self, amt=10, cat='A'):

        self.amount = amt
        self.category = cat


def func_1(testing):

    total = 0
    result = []
    for test in testing:
        total += test.amount
        result.append({'category': test.category, 'value': test.amount})

    return


def func_2(testing):

    result = [{'category': test.category, 'value': test.amount} for test in testing]
    total = sum([i['value'] for i in result])

    return


def func_3(testing):

    result = [{'category': test.category, 'value': test.amount} for test in testing]
    total = sum([test.amount for test in testing])

    return


def func_4(testing):

    result, totals = [], []
    for test in testing:
        totals.append(test.amount)
        result.append({'category': test.category, 'value': test.amount})

    total = sum(totals)

    return


def func_5(testing):

    result = [{'category': test.category, 'value': test.amount} for test in testing]
    total = sum(test.amount for test in testing)

    return

我将省略函数调用和打印语句以节省空间:

--------------------
10 variables / 10000 iterations
--------------------

func_1: 0.0898552949414
func_2: 0.0572853889704
func_3: 0.0666673211647
func_4: 0.0676401432815
func_5: 0.0496420416234

--------------------
100 variables / 10000 iterations
--------------------

func_1: 0.371173584934
func_2: 0.310192364417
func_3: 0.330012053177
func_4: 0.53144825992
func_5: 0.377762000408

--------------------
1000 variables / 10000 iterations
--------------------

func_1: 3.60984478132
func_2: 3.05880308072
func_3: 3.29883265808
func_4: 4.98255212296
func_5: 3.36148284866

【讨论】:

  • 你的make example测试给我很有趣
  • 我正在尝试 pip install functime not found
  • 嘿@Evan 我刚刚更新了我的解决方案,它与其他解决方案的表现如何?
  • @XeroSmith 将其更改为 sum([d['value'] for d in result]) 仍然会提高速度,就像我之前在评论中提到的那样
  • @KomangSuryadana functime 只是我为 timeit 制作的包装器
【解决方案2】:

关于您的代码的一些有趣观察:

  • 递增total 和构建result 列表是独立的
  • 使用native python constructs 可以快速完成这两个操作
    result = [{'category': test.category, 'value': test.amount} for test in testing]
    total = sum(d['value'] for d in result)
    

    编辑显示总数是通过遍历字典列表并对每个字典的 value 键求和获得的。

    顺便说一句,这两行都是optimised python 构造。

  • 【讨论】:

    • sum(test.amount for _ in result) 更改为sum([test.amount for _ in result]) 将加速该功能。您可以查看我的答案以了解计时结果。
    • 我现在看到我没有将这些确切的比较放在我的答案中,但是在回到代码之后我的评论仍然正确(快 0.05 秒)。
    • +1 以确保您的答案的完整性。我有点惊讶,我本来预计在求和之前构建列表会产生一些开销。
    • @XeroSmith 我认为创建生成器可能会有一些开销,并使用 StopIteration 异常停止它,如果您不创建列表,这一切都会发生。生成器非常适合减少使用的内存量,但看起来它们在速度方面并没有那么高效。
    【解决方案3】:

    按照您的要求,我想出了如何在一条线上完成所有操作。这绝对不是要走的路,但这里有几个选择:

    def one_line():
        return [(a[0][0], a[1]) for a in [ (t, [tuple(t.append(t.pop()+test.amount) or te for te in [{'category': test.category, 'value': test.amount}])[0] for test in testing ]) for t in [[0]] ] ][0]
    
    def one_line_alternative():
        return next(map(lambda a: (a[0].pop(),a[1]), [ (t, list(map(lambda test: next((t.append(t.pop()+test.amount)) or te for te in [{'category': test.category, 'value': test.amount}]), testing)) ) for t in [[0]] ]))
    

    这是与 Evan Nowak 最快答案的比较。我使用了 10 个变量、50000 次迭代,以及 Evan Nowak 对 10 个变量的最快优化。

    One Line:  2.8529339203163353
    One Line Alternative:  2.859311107199918
    Evan Nowak's fastest optimization:  2.3440381323539983
    

    因此,正如预期的那样,将所有内容放在一条线上并不是一个好主意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-03
      • 2014-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 1970-01-01
      相关资源
      最近更新 更多