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
列表理解产生 - 列表!它不适合现有列表中的单个赋值.(虽然你可以折磨语法来做那个...)
虽然目前还不清楚你要从代码中做什么,但我认为它更类似于循环列表(流控制)与生成列表(列表理解)
循环遍历列表如下:
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)
因人而异
这是一个很棒的教程.
n1k*_*1t4 17
Python 3.8将引入赋值表达式。
这是一个新符号::=允许分配(除其他外)理解。
从上面链接的PEP(适用于SO的格式)的以下代码片段可以看出,它将在计算/内存方面带来很多潜在的节省:
语法和语义
在大多数可以使用任意Python表达式的情况下,都会出现一个命名表达式。这是以下形式
NAME := expr,其中expr是除加括号的元组的其它任何有效的Python表达式,并且NAME是一个标识符。这样的命名表达式的值与合并的表达式相同,另外还有一个副作用,即为目标分配了该值:
处理匹配的正则表达式
Run Code Online (Sandbox Code Playgroud)if (match := pattern.search(data)) is not None: # Do something with match使用2-arg iter()不能轻易重写的循环
Run Code Online (Sandbox Code Playgroud)while chunk := file.read(8192): process(chunk)重用计算成本很高的值
Run Code Online (Sandbox Code Playgroud)[y := f(x), y**2, y**3]在理解过滤器子句及其输出之间共享子表达式
Run Code Online (Sandbox Code Playgroud)filtered_data = [y for x in data if (y := f(x)) is not None]
最近发布的Alpha版本已经提供了此功能(不建议用于生产系统!)。您可以在此处找到Python 3.8的发布时间表。
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)
列表推导用于它们的返回值,它们在内部进行循环...如果您想要的是循环,那么只需编写一个循环...谁将阅读代码试图理解它的作用将会很多(&和无论谁在几周内包括你自己.
简而言之:你没有.列表推导用于生成列表,而不是修改现有列表.如果要修改列表,请使用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程序员一直都在讨厌它,你可以使用一些函数:
如果要分配的变量是全局变量,那么您可以这样做
globals().update(var=value)
Run Code Online (Sandbox Code Playgroud)如果要分配的变量是可变序列或映射(例如列表或字典)
list.__setitem__(index, value)
Run Code Online (Sandbox Code Playgroud)