python如何不在允许下列代码_运算符


python3.8引入了很多新特性,咱们今天在这里只说一个就是赋值表达式,很多小伙伴会很惊讶,我进来了你就给我说这个?那种语言没有赋值表达式?很low的东西!那你还真就说错了,python3.8以前没有赋值表达式,但有赋值语句,所以python3.8之前赋值必须单独占一行,不能和其他表达式混合计算,为什么呀?不就是赋值是语句不是表达式吗?


# python3.8 赋值表达式
res = (a := 3)
print(res)

# python3.8以前,语法错误
# res = (a = 3)


上面这段代码中“:=”就是赋值运算符,也叫海象运算符(因为很想海象的两只眼睛和长牙),它是原来的赋值运算符(=)的补充,能够完成和“=”一样的功能,但“:=”最大的特点就是它可以写赋值表达式:


3 + (a:=5) + 6  # (a:=5)就是赋值表达式


1. 优点

它的优点是可以防止多次计算重复值和可以写赋值表达式。例如:

在这个示例中,赋值表达式可以避免调用len()两次:


if (n := len(a)) > 10:
    print(f"List is too long ({n} elements, expected <= 10)")


类似的益处还可出现在正则表达式匹配中需要使用两次匹配对象的情况中,一次检测用于匹配是否发生,另一次用于提取子分组:


discount = 0.0
if (mo := re.search(r'(d+)% discount', advertisement)):
    discount = float(mo.group(1)) / 100.0


此运算符也适用于配合 while 循环计算一个值来检测循环是否终止,而同一个值又在循环体中再次被使用的情况:


while (block := f.read(256)) != '':
    process(block)


另一个值得介绍的用例出现于列表推导式中,在筛选条件中计算一个值,而同一个值又在表达式中需要被使用:


[clean_name.title() for name in names
 if (clean_name := normalize('NFC', name)) in allowed_names]


但海象运算符不应滥用,尽量不要有过多的嵌套,避免逻辑的混乱。

2.限制

为了避免模棱两可或用户混淆,在某些地方不允许使用赋值表达式:

  • 在表达式语句的顶层禁止使用非括号的赋值表达式。例:
y:= f(x)#无效
(y:= f(x))#有效,但不建议使用


  • 禁止在赋值语句右侧的顶层使用未加括号的赋值表达式。例:
y0 = y1:= f(x)#无效
y0 =(y1:= f(x))#有效,但不鼓励使用


  • 关键字参数的值禁止使用非括号的赋值表达式。例:
foo(x = y:= f(x))#无效
foo(x =(y:= f(x)))#有效,尽管可能会造成混淆


  • 在函数默认值的顶层禁止未括号的赋值表达式。例:
def foo(answer = p:= 42):#无效
    ...
def foo(answer =(p:= 42)):#有效,但样式不好


  • lambda函数中禁止使用非括号的赋值表达式。例:
(lambda:x:= 1)#无效
lambda:(x:= 1)#有效,但不太可能有用
(x:= lambda:1)#有效
lambda行:(m:= re.match(pattern,line))和m.group(1)#有效


  • f字符串内部的赋值表达式需要括号。例:
>>> f'{(x:= 10)}'#有效,使用赋值表达式
'10'
>>> x = 10
>>> f'{x:= 10}'#有效,将'= 10'传递给格式化程序
'10'