在Lambda中使用__iadd__吗?

时间:2019-05-01 14:23:28

标签: python python-3.x lambda

我正试图解决这个小挑战:

  

您想要一个defaultdict,每次使用一个默认值   查找不存在的密钥,即计数器;第一个   不存在的密钥,第二个为第二个,等等。

我能够像这样解决它

from collections import defaultdict

def f(a=[0]):
    a[0]+=1
    return a[0]

s=defaultdict(f)

奖励是尝试在一行中做到这一点。

s=defaultdict(lambda a=[0]: (a[0]+=1))
  

SyntaxError:语法无效_________ ^

有没有办法在lambda中做到这一点?更新可变的默认arg并返回?

5 个答案:

答案 0 :(得分:6)

有两个问题:

  1. /path/to/script是语句,而不是表达式。您可以显式调用chmod +x my-script除了 ...
  2. ... += ...未定义__iadd__int刚实现为__iadd__

您需要做的是显式调用a[0] += 1以更新默认列表值的第0个元素。这将返回a[0] = a[0] + 1,而不是__setitem__,因此,您还需要一个None表达式来返回a[0]的值(自or起):

a[0]

(我自己写None or x == x。)

答案 1 :(得分:3)

operator进行救援:

d = defaultdict(lambda a = [0]: operator.setitem(a, 0, a[0] + 1) or a[0])

答案 2 :(得分:2)

进口是否算作您一行的一部分?

否则,您可以使用itertools.count

rdd = sc.parallelize([(['1', '2', '3'], 'abc'), (['4', '5', '6'], 'xyz')])
r = rdd.flatMap(lambda item: [(k, item[1]) for k in item[0]])
r.collect() # to show result

如果他们这样做,您可以使用稍微难看的骇客

<select name="apisel" id="apisel" onchange="SelectedIndexChanged">
@foreach (var item in Model.APIs)
{
    @if (item.isSelected)
    {
    <option value="@item.ApiID" selected="selected">
        @item.ApiTitle
    </option>
    }
    else
    {
    <option value="@item.ApiID">
        @item.ApiTitle
    </option>
   }
}

答案 3 :(得分:2)

虽然有很多方法可以解决这一问题,但我看到很多关于operator.iadd是否可以在此处使用的问题。

不能。

当然,它会出现

s = defaultdict(lambda a=[0]: operator.iadd(a[0], 1))

可以,但是不能。

原因来自offical docs

  

许多操作都有“就地”版本。下面列出的函数比通常的语法提供对原始操作符的更原始的访问;例如,语句x + = y等效于x = operator.iadd(x,y)。另一种表达方式是说z = operator.iadd(x,y)等效于复合语句z = x; z + = y。

     

在这些示例中,请注意,当调用就地方法时,计算和分配是在两个单独的步骤中执行的。下面列出的就地函数仅执行第一步,即调用就地方法。第二步,分配,未处理。

     

对于不可变的目标(例如字符串,数字和元组),将计算更新后的值,但不会将其分配回输入变量:

>>> a = 'hello'
>>> iadd(a, ' world')
'hello world'
>>> a
'hello'
  

对于诸如列表和字典之类的可变目标,就地方法将执行更新,因此无需后续分配。

由于int对象是不可变的,因此无法使用a[0]更新iadd

(我知道其他答案中已经提到了这一点;我只是认为带有Python文档链接的明确答案可能会有所帮助。)

答案 4 :(得分:1)

如何使用诸如列表之类的可变类型来跟踪计数?

s = defaultdict(lambda a=[] : len(a.__iadd__([1])))

要减少内存使用量:

s = defaultdict(lambda a=[0] : a.__iadd__([a.pop() + 1])[0])