我正在尝试输入提示海象运算符表达式,即
while (var: int := some_func()): ...
我怎样才能做到这一点?
我想避免在字典理解中对平均值进行双重评估,并且我尝试使用海象运算符:
>>> dic = {"A": [45,58,75], "B": [55,82,80,92], "C": [78,95,90], "D":[98,75]}
>>> q = {x: (mean := (sum(dic[x]) // len(dic[x]))) for x in dic if mean > 65}
Run Code Online (Sandbox Code Playgroud)
但这给了我以下错误:
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
q = {x: (mean := (sum(dic[x]) // len(dic[x]))) for x in dic if mean > 65}
File "<pyshell#2>", line 1, in <dictcomp>
q = {x: (mean := (sum(dic[x]) // len(dic[x]))) for x in dic if mean > 65}
NameError: name …Run Code Online (Sandbox Code Playgroud) 我刚刚了解到新的 walrus 运算符 ( :=) 不能用于设置实例属性,它应该是无效的语法(引发 a SyntaxError)。
为什么是这样? (你能提供一个提到这个的官方文档的链接吗?)
我查看了PEP 572,找不到是否/在哪里记录了这一点。
研究
这个答案在没有解释或来源的情况下提到了这个限制:
您不能在对象属性上使用 walrus 运算符
示例代码
class Foo:
def __init__(self):
self.foo: int = 0
def bar(self, value: int) -> None:
self.spam(self.foo := value) # Invalid syntax
def baz(self, value: int) -> None:
self.spam(temp := value)
self.foo = temp
def spam(self, value: int) -> None:
"""Do something with value."""
Run Code Online (Sandbox Code Playgroud)
尝试导入Foo结果为SyntaxError:
self.spam(self.foo := value)
^
SyntaxError: cannot use assignment expressions with …Run Code Online (Sandbox Code Playgroud) PEP 572引入了赋值运算符(“海象运算符”)。
以下代码有效并输出empty
def say_empty():
return ''
if a := say_empty():
print("not empty")
else:
print("empty")
Run Code Online (Sandbox Code Playgroud)
我试图否定这个条件:
def say_empty():
return ''
if not a := say_empty():
print("empty")
else:
print("not empty")
Run Code Online (Sandbox Code Playgroud)
这就提出了一个SyntaxError
if not a := say_empty():
^
SyntaxError: cannot use assignment expressions with operator
Run Code Online (Sandbox Code Playgroud)
给定的错误很明显,但是我想知道为什么要实施此限制。
PEP 572 解释了为什么在迭代中使用赋值会出现问题(并引发SyntaxError),但我没有找到任何有关布尔值的信息。
我有一个简单的函数,应该根据模式或None不匹配的情况输出前缀。尝试做海象似乎不起作用。任何想法?
import re
def get_prefix(name):
if m := re.match(f'^.+(\d\d)-(\d\d)-(\d\d\d\d)$', name) is not None:
return m.group(3) + m.group(2) + m.group(1)
get_prefix('abc 10-12-2020')
Run Code Online (Sandbox Code Playgroud)
追溯
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in get_prefix
AttributeError: 'bool' object has no attribute 'group'
Run Code Online (Sandbox Code Playgroud) 我有以下表达:
>>> 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,然后与其新值进行比较)?
这种行为是在哪里定义的,它的可靠性如何?
为什么我不能使用 walrus 运算符:=来分配属性?它在分配给局部变量时起作用:
my_eyes = ["left", "right"]
if saved_eye := my_eyes.index("left"):
print(saved_eye)
# outputs >>> 0
Run Code Online (Sandbox Code Playgroud)
但如果我尝试分配给对象属性,则会出现语法错误:
class MyEyes:
def __init__(self):
self.eyes = ["left", "right"]
self.saved_eye = None
def ohyes(self):
if self.saved_eye := self.eyes.index("left"):
print(self.saved_eye)
x = MyEyes()
x.ohyes()
# raises
# >>> if self.saved_eye := self.eyes.index("left"):
# >>> SyntaxError: cannot use assignment expressions with attribute
Run Code Online (Sandbox Code Playgroud)
我的意思是我可以使用临时局部变量绕过错误,但为什么会发生这种情况?我相信 100% 这是合法的语法。
是否有在 1 个 if 语句中包含两个海象运算符的正确方法?
if (three:= i%3==0) and (five:= i%5 ==0):
arr.append("FizzBuzz")
elif three:
arr.append("Fizz")
elif five:
arr.append("Buzz")
else:
arr.append(str(i-1))
Run Code Online (Sandbox Code Playgroud)
该示例适用于three但five将“未定义”。
我正在尝试在 f 字符串中使用命名表达式:
print(f"{(a:=5 + 6) = }")
Run Code Online (Sandbox Code Playgroud)
返回:
(a:=5 + 6) = 11
Run Code Online (Sandbox Code Playgroud)
但我希望有这样的事情:
a = 11
Run Code Online (Sandbox Code Playgroud)
通过组合海象运算符和 f 字符串是否可能(这样我就不必a在单独的步骤中首先声明变量)?
python string-interpolation python-3.x f-string walrus-operator
我正在尝试使用 Walrus operator 获取用户的输入:=,但如果用户只输入Enter密钥 as input,则 python 脚本将终止。如何捕获此错误并确保用户不仅按下了Enter键?
有这个答案,但它不适用于海象运算符。
这段没有 walrus 运算符的代码将成功检查是否不仅Enter按下了键:
while True:
answer = input("Please enter something: ")
if answer == "":
print("Invalid! Enter key was pressed.")
continue
else:
print("Enter wasn't pressed!")
# do something
Run Code Online (Sandbox Code Playgroud)
如果用户只按下Enter,则整个脚本将终止。
while answer := input("Please enter something: "):
# if user pressed only `Enter` script will terminate. following will never run
if answer == "":
print("enter was pressed")
else:
print("Enter …Run Code Online (Sandbox Code Playgroud) python ×10
walrus-operator ×10
python-3.x ×4
python-3.9 ×2
f-string ×1
python-3.8 ×1
python-assignment-expression ×1
syntax-error ×1