如何在列表理解中进行分配?

xun*_*ang 45 python list-comprehension

我想在列表推导中使用赋值运算符.我怎样才能做到这一点?

以下代码是无效的语法.我的意思是如果匹配则设置lst[0]为空字符串:''pattern

[ lst[0] = '' for pattern in start_pattern if lst[0] == pattern ]
Run Code Online (Sandbox Code Playgroud)

谢谢!

daw*_*awg 25

看起来你在Python中使用循环结构混淆列表理解.

列表理解产生 - 列表!它不适合现有列表中的单个赋值.(虽然你可以折磨语法来做那个...)

虽然目前还不清楚你要从代码中做什么,但我认为它更类似于循环列表(流控制)与生成列表(列表理解)

循环遍历列表如下:

for pattern in patterns:
   if lst[0] == pattern: lst[0]=''
Run Code Online (Sandbox Code Playgroud)

这是一种合理的方法,这是你在C,Pascal等中所做的.但你也可以只测试一个值的列表并进行更改:

if lst[0] in patterns: lst[0] = ''
Run Code Online (Sandbox Code Playgroud)

或者,如果您不知道索引:

i=lst.index[pattern]
lst[i]=''
Run Code Online (Sandbox Code Playgroud)

或者,如果您有列表列表并想要更改每个子列表的每个第一个元素:

for i, sublst in enumerate(lst):
    if sublst[i][0] in patterns: sublist[i][0]=''
Run Code Online (Sandbox Code Playgroud)

等等等

如果要对列表的每个元素应用某些内容,则可以使用列表推导,映射或Python工具包中的许多其他工具之一.

就个人而言,我通常更倾向于使用列表推导来创建列表:

 l=[[ x for x in range(5) ] for y in range(4)]  #init a list of lists...
Run Code Online (Sandbox Code Playgroud)

哪个更自然:

l=[]
for i in range(4):
   l.append([])
   for j in range(5):
      l[i].append(j)      
Run Code Online (Sandbox Code Playgroud)

但要修改相同的列表列表,哪个更容易理解?

这个:

l=[['new value' if j==0 else l[i][j] for j in range(len(l[i]))] for i in range(len(l))]
Run Code Online (Sandbox Code Playgroud)

或这个:

for i,outter in enumerate(l):
    l[i][0]='new value'               
Run Code Online (Sandbox Code Playgroud)

因人而异

是一个很棒的教程.

  • 这应该写成`if lst [0] in patterns:lst [0] =''`. (3认同)

n1k*_*1t4 17

Python 3.8将引入赋值表达式

这是一个新符号::=允许分配(除其他外)理解。

从上面链接的PEP(适用于SO的格式)的以下代码片段可以看出,它将在计算/内存方面带来很多潜在的节省:

语法和语义

在大多数可以使用任意Python表达式的情况下,都会出现一个命名表达式。这是以下形式NAME := expr,其中 expr是除加括号的元组的其它任何有效的Python表达式,并且NAME是一个标识符。

这样的命名表达式的值与合并的表达式相同,另外还有一个副作用,即为目标分配了该值:

  1. 处理匹配的正则表达式

    if (match := pattern.search(data)) is not None:
        # Do something with match
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用2-arg iter()不能轻易重写的循环

    while chunk := file.read(8192):
        process(chunk)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 重用计算成本很高的值

    [y := f(x), y**2, y**3]
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在理解过滤器子句及其输出之间共享子表达式

    filtered_data = [y for x in data if (y := f(x)) is not None]
    
    Run Code Online (Sandbox Code Playgroud)

最近发布的Alpha版本已经提供了此功能(不建议用于生产系统!)。您可以在此处找到Python 3.8的发布时间表

  • 不幸的是,您不能使用下标分配给表达式。`a[i] := 'foo'` 将抛出异常:`SyntaxError: 无法使用带有下标的赋值表达式` (7认同)
  • python 中的“None”不是错误的吗?即:“is not None”是否必要,如果需要,何时? (2认同)

650*_*502 9

Python语言对表达式和语句有不同的概念.

即使语法有时会让你认为它是一个表达式(例如a=b=99有效但是是一个特殊的语法案例,并不意味着它b=99是一个类似于C的表达式),所以赋值是一个陈述.

列表推导是表达式,因为它们返回一个值,在某种意义上,它们执行的循环是一个事件,主要点是返回的列表.

语句可以包含表达式,但表达式不能包含语句.

也就是说,列表项分配在内部转换为方法调用(以允许创建类似列表的对象),方法调用是表达式.因此,您可以在技术上使用表达式中的列表项分配:

[ lst.__setitem__(0, '') for pattern in start_pattern if lst[0] == pattern ]
Run Code Online (Sandbox Code Playgroud)

然而,这被认为是不好的,因为它损害了可读性,并且读取源代码的容易程度是Python语言的主要焦点.你应该写例如......

for pattern in start_pattern:
    if lst[0] == pattern:
        lst[0] = ''
Run Code Online (Sandbox Code Playgroud)

顺便说一句,感谢in操作员相当于更具可读性

if lst[0] in start_pattern:
    lst[0] = ''
Run Code Online (Sandbox Code Playgroud)

列表推导用于它们的返回值,它们在内部进行循环...如果您想要的是循环,那么只需编写一个循环...谁将阅读代码试图理解它的作用将会很多(&和无论谁在几周内包括你自己.


Col*_*ant 6

简而言之:你没有.列表推导用于生成列表,而不是修改现有列表.如果要修改列表,请使用for循环,因为这就是它们的用途.

编写该代码的Pythonic方法如下:

for pattern in start_pattern:
    if lst[0] == pattern:
        lst[0] = ''
        #the following assumes that pattern will never be ''
        #if that's possible, you can ignore this bit
        break
Run Code Online (Sandbox Code Playgroud)

但是,如果你真的,真的想在一个内部完成任务,并且不介意每个处理你的代码的Python程序员一直都在讨厌它,你可以使用一些函数: