现在已经接受了PEP 572,Python 3.8注定要有赋值表达式,所以我们可以使用赋值表达式with,即
with (f := open('file.txt')):
for l in f:
print(f)
Run Code Online (Sandbox Code Playgroud)
代替
with open('file.txt') as f:
for l in f:
print(f)
Run Code Online (Sandbox Code Playgroud)
它会像以前一样工作.
as关键字与withPython 3.8中的语句有什么用?这不是针对Python的禅宗:"应该有一个 - 最好只有一个 - 显而易见的方法." ?
当最初提出的功能,它并没有明确规定是否赋值表达式应中括号with和
with f := open('file.txt'):
for l in f:
print(f)
Run Code Online (Sandbox Code Playgroud)
可以工作.但是,在Python 3.8a0中,
with f := open('file.txt'):
for l in f:
print(f)
Run Code Online (Sandbox Code Playgroud)
会引发
File "<stdin>", line 1
with f := open('file.txt'):
^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)
但括号表达式有效.
考虑以下列表理解
[ (x,f(x)) for x in iterable if f(x) ]
Run Code Online (Sandbox Code Playgroud)
这将根据条件过滤可迭代f并返回对x,f(x).这种方法的问题f(x)是计算两次.如果我们可以这样写,那就太好了
[ (x,fx) for x in iterable if fx where fx = f(x) ]
or
[ (x,fx) for x in iterable if fx with f(x) as fx ]
Run Code Online (Sandbox Code Playgroud)
但是在python中我们必须使用嵌套的理解来编写,以避免重复调用f(x),这使得理解看起来不那么清晰
[ (x,fx) for x,fx in ( (y,f(y) for y in iterable ) if fx ]
Run Code Online (Sandbox Code Playgroud)
有没有其他方法可以使它更加pythonic和可读?
更新
即将推出的python 3.8!PEP
# Share a subexpression between a comprehension filter clause and its output
filtered_data = [y …Run Code Online (Sandbox Code Playgroud) python list-comprehension python-3.x python-3.8 python-assignment-expression
在 Python (3.11) 中,为什么在 f 字符串内使用赋值表达式(“海象运算符”)时需要用括号括起来?
例如:
#!/usr/bin/env python
from pathlib import Path
import torch
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
ckpt_dir = Path("/home/path/to/checkpoints")
_ckpt = next(ckpt_dir.iterdir())
print(_ckpt)
sdict = torch.load(_ckpt, map_location=DEVICE)
model_dict = sdict["state_dict"]
for k, v in model_dict.items():
print(k)
print(type(v))
print(_shape := v.size())
print(f"{(_numel := v.numel())}")
print(_numel == torch.prod(torch.tensor(_shape)))
Run Code Online (Sandbox Code Playgroud)
上面的代码块 withprint(f"{_numel := v.numel()}")相反不会解析。
解析/AST 创建是否要求这样做?
Python 3.8引入了赋值表达式,如PEP 572中所述。有没有办法在Python 3.7.x中测试此新功能?
过去,新的语言功能已使用__future__导入功能反向移植到早期的Python版本。
__future__赋值表达式有导入吗?python python-3.x python-3.7 python-3.8 python-assignment-expression
我有以下表达:
>>> a = 3
>>> b = 2
>>> a == (a := b)
False
Run Code Online (Sandbox Code Playgroud)
现在,a == 2手术后,正如预期的那样。结果就是我想要的,即a在分配之前与分配的 RHS 进行比较。
颠倒等号运算符的顺序会颠倒结果:
>>> a = 3
>>> b = 2
>>> (a := b) == a
True
Run Code Online (Sandbox Code Playgroud)
PEP-572 相对优先级部分中似乎没有任何与此极端情况直接相关的内容。下一节,更改评估顺序提到评估顺序是从左到右。这就是这里发生的情况吗(存储 的值a,更新它,然后比较与 update a,然后与其新值进行比较)?
这种行为是在哪里定义的,它的可靠性如何?
在Effective Python一书中,作者建议使用赋值表达式来避免理解中的冗余,例如:
def fun(i):
return 2 * i
result = {x: y for x in [0, 1, 2, 3] if (y := fun(x)) > 3}
Run Code Online (Sandbox Code Playgroud)
代替
result = {x: fun(x) for x in [0, 1, 2, 3] if fun(x) > 3}
Run Code Online (Sandbox Code Playgroud)
result有价值{2: 4, 3: 6}。
作者指出
如果推导式在推导式的值部分使用海象运算符并且没有条件,它会将循环变量泄漏到包含范围中。[...] 最好不要泄漏循环变量,因此我建议仅在推导式的条件部分使用赋值表达式。
然而,在上面的例子中, y在程序结束时设置为 6。因此,赋值表达式中的变量泄漏了,尽管它是在条件中定义的。
列表推导式也会发生同样的事情:
>>> _ = [(x, leak) for x in range(4) if (leak := 2 * x) > 3]
>>> leak
6
Run Code Online (Sandbox Code Playgroud)
甚至对于生成器表达式:
>>> …Run Code Online (Sandbox Code Playgroud) 在我看来,将经典的while循环与Assignment-expressions -loops互换可以使代码看起来很棒不是那么简单。
考虑example1:
>>> a = 0
>>> while (a := a+1) < 10:
... print(a)
...
1
2
3
4
5
6
7
8
9
Run Code Online (Sandbox Code Playgroud)
和example2:
>>> a = 0
>>> while a < 10:
... print(a)
... a += 1
...
0
1
2
3
4
5
6
7
8
9
Run Code Online (Sandbox Code Playgroud)
您将如何修改example1以具有相同的输出(不跳过0)example2?(a = 0当然,无需更改)
#Python新闻:Guido接受了PEP572。Python现在具有赋值表达式。
Run Code Online (Sandbox Code Playgroud)if (match := (pattern.search) pattern.search(data)) is not None: print((match.group) mo.group(1)) filtered_data = [y for x in data if (y := f(x)) is not None](在第二行代码中更正我的)
如前所述,PEP 572-赋值表达式描述了它在Python 3.8中的存在:
这是创建一种使用符号在表达式中分配变量的方法的建议
NAME := expr。
我已经遍历了描述和示例,并且看到了这是避免重复调用或分配的便捷方法,因此可以代替:
match1 = pattern1.match(data)
match2 = pattern2.match(data)
if match1:
return match1.group(1)
elif match2:
return match2.group(2)
Run Code Online (Sandbox Code Playgroud)
或更有效的:
match1 = pattern1.match(data)
if match1:
return match1.group(1)
else:
match2 = pattern2.match(data)
if match2:
return match2.group(2)
Run Code Online (Sandbox Code Playgroud)
现在可以说:
if match1 := pattern1.match(data):
return …Run Code Online (Sandbox Code Playgroud) 这是一个元编程问题:我想了解为什么python开发人员在new中引入了另一个运算符:=。我知道这是干什么的 但是,我想知道为什么开发人员选择一个新的符号而不是重复使用例如as运算符。
即为什么认为最好写
while (command := input("> ")) != "quit":
print("You entered:", command)
Run Code Online (Sandbox Code Playgroud)
而不是
while input("> ") as command != "quit":
print("You entered:", command)
Run Code Online (Sandbox Code Playgroud) python language-design python-3.x python-3.8 python-assignment-expression
我想知道是否可以使用“海象运算符”根据某些条件以及现有条件来分配值。例如,post_url如果该字符串包含某个子字符串,则将该字符串分配给:
if post_url := data.get("Post url") and ("youtube" in data.get("Post url")):
# Do something with post_url
else:
# Do something else
Run Code Online (Sandbox Code Playgroud)
然而,这只是post_url由于操作的评估而分配布尔值and。
Python 3.8引入了“海象运算符”:=来进行赋值表达式。我认为他们考虑过使用该关键字as但拒绝了。是否存在as阻止将其用于赋值表达式的现有语法情况?
要使用 Python 文档中的示例:
# Actual Python 3.8 syntax
if (n := len(a)) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
# Why not this?
if (len(a) an n) > 10:
print(f"List is too long ({n} elements, expected <= 10)")
Run Code Online (Sandbox Code Playgroud)
这是另一个例子:
# Actual Python 3.8 syntax
while (block := f.read(256)) != '':
process(block)
# Why not this?
while f.read(256) as block:
process(block)
Run Code Online (Sandbox Code Playgroud) python ×12
python-assignment-expression ×12
python-3.8 ×9
python-3.x ×6
f-string ×1
pep ×1
python-3.7 ×1