社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python 3.8 新运算符 := 让我们懒出新高度

Python开发者 • 8 月前 • 244 次点击  

背景

Python 的语法风格确实是懒人福音,真是做到了多写一行都是罪。就拿 Python-3.8 版本来说吧,为了少写一行代码,直接搞出了一个新的运算符 `:= `。

先给结论!这个运算符不是必要的。也就是说没有它我们也能写程序,只是有了它之后我们的代码可以更加简洁。

下面我就来说一下这个运算符的故事!


阶段 一

这个阶段大家做事都中规中矩,代码上直抒胸臆。给个例子吧。假设我们有一个函数,它是用来处理列表的,它会在处理之前检查一下列表的长度,当长度大于 7 时直接退出。阶段一这个时候的代码看起来如下。

def fun(lst=None):    """    Parameters:        lst: 列表        Return:        None    """    #     if len(lst) > 7:        print(f"len(lst) = {len(lst)}  gt 7 , not supported .")        return         # 其它逻辑

这里有一个小小的问题,就是 `len(lst)` 在命中 if 的语句时候它还会在 print 语句里面再被计算一次。如果计算本身的开销就比较高,少计算一次就非常有吸引力了,阶段二就是向这个方向进化的。


阶段二

阶段二的写法也是非常直接,只要保存一下第一次计算的结果,第二次的时候直接取结果,这样就不用再计算一次了。上代码

def fun(lst=None):    """    Parameters:        lst: 列表        Return:        None    """    #     n = len(lst)    if n > 7:        print(f"len(lst) = {n}  gt 7 , not supported .")        return         # 其它逻辑

阶段二的写法也不是完全没有可以改进的地方,我们看 n 其实只在 if 块里面有用到,但是它的声明位置是在 if 之外的。这个就给人一种,这个 n 非常重要后面的代码还会用到它的感觉。也就是说这种写法没有办法表现出 n 就是一个临时变量

好在这种语义已经可以在 Python-3.8 这个版本中表达了,不过我们要借助全新的运算符 `:=` 来实现。 详细的请看阶段三。


阶段三

阶段三是真正的做到了形与意合,并且没有什么学习成本,语法上可以说是一看就懂,我直接上代码。

def fun(lst=None):    """    Parameters:        lst: 列表        Return:        None    """    #         if (n:= len(lst)) > 7:        print(f"len(lst) = {n}  gt 7 , not supported .")        return         # 其它逻辑

现在从词法上看,就能非常明确地知道 n 只在 if 语句内起作用。由于阶段三只是阶段二的语法糖,也就是说从作用域上来讲 n 在 if 语句之后还是可以正常访问,这个应该就是唯一美中不足的地方了吧。


为什么说  :=  是语法糖

这一点是从官方文档上不能直接看出来的,需要我们去看 fun 函数两种不同写法,编译出来的字节码。

In [1]: import dis
In [2]: def fun(lst=None): ...: """ ...: Parameters: ...: lst: 列表 ...: ...: Return: ...: None ...: """ ...: # ...: ...: if (n:= len(lst)) > 7: ...: print(f"len(lst) = {n} gt 7 , not supported .") ...: return ...:
In [3]: dis.dis(fun) 1 0 RESUME 0
11 2 LOAD_GLOBAL 1 (NULL + len) 14 LOAD_FAST 0 (lst) 16 PRECALL 1 20 CALL 1 30 COPY 1 32 STORE_FAST 1 (n) 34 LOAD_CONST 1 (7) 36 COMPARE_OP 4 (>) 42 POP_JUMP_FORWARD_IF_FALSE 21 (to 86)
12 44 LOAD_GLOBAL 3 (NULL + print) 56 LOAD_CONST 2 ('len(lst) = ') 58 LOAD_FAST 1 (n) 60 FORMAT_VALUE 0 62 LOAD_CONST 3 (' gt 7 , not supported .') 64 BUILD_STRING 3 66 PRECALL 1 70 CALL 1 80 POP_TOP
13 82 LOAD_CONST 4 (None) 84 RETURN_VALUE
11 >> 86 LOAD_CONST 4 (None) 88 RETURN_VALUE
In [4]: def fun(lst=None): ...: """ ...: Parameters: ...: lst: 列表 ...: ...: Return: ...: None ...: """ ...: # ...: n = len(lst) ...: if n > 7: ...: print(f"len(lst) = {n} gt 7 , not supported .") ...: return ...:
In [5]: dis.dis(fun) 1 0 RESUME 0
10 2 LOAD_GLOBAL 1 (NULL + len) 14 LOAD_FAST 0 (lst) 16 PRECALL 1 20 CALL 1 30 STORE_FAST 1 (n)
11 32 LOAD_FAST 1 (n) 34 LOAD_CONST 1 (7) 36 COMPARE_OP 4 (>) 42 POP_JUMP_FORWARD_IF_FALSE 21 (to 86)
12 44 LOAD_GLOBAL 3 (NULL + print) 56 LOAD_CONST 2 ('len(lst) = ') 58 LOAD_FAST 1 (n) 60 FORMAT_VALUE 0 62 LOAD_CONST 3 (' gt 7 , not supported .') 64 BUILD_STRING 3 66 PRECALL 1 70 CALL 1 80 POP_TOP
13 82 LOAD_CONST 4 (None) 84 RETURN_VALUE
11 >> 86 LOAD_CONST 4 (None) 88 RETURN_VALUE

可以看到阶段三和阶段二的字节码是一模一样的。

推荐阅读  点击标题可跳转

1、Python-3.12.3 新版本发布 & 性能提升

2、用Python写个自动批改作业系统!

3、进程监控神器Supervisor:让你的Python应用稳如老狗!

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/169872
 
244 次点击