高版本Python3代码如何让低版本Python3解释器也能够执行

为了增加代码的可迁移性,公司要求我们的代码应该在Python3.6及之后的所有版本上都可以直接跑。而我们知道,Python3.6及之后的各个版本差别还是有的,而且有的是致命的,直接导致代码报错。

例如Python3.8及之后fstring的{x=}在低版本就不能用,会报语法错误。如果是异常倒还好处理,try-except然后except里写个低版本的代码就可以了,但是语法错误会导致解释器拒绝执行,因此写在try里都没有用:

a='123'
try:
    print(f'{a=}')
except:
    print(f'a={a}')

使用Python3.6执行结果:
在这里插入图片描述
我开始想找个方法(例如增加参数)使得执行时忽略语法错误,但是没有找到有效的。

后来我想到可以把语法错误的代码以字符串的形式保存,然后执行时再用eval转成Python语句,就成功了:

a='123'
try:
    print(eval("f'{a=}'"))
except:
    print(f'a={a}')

Python3.6跑的结果是:

a=123

Python3.8跑的结果是:

a=‘123’

可见try-except生效了,我们可以用Python3.6单独跑一下try里面的代码:
在这里插入图片描述
虽然还是报语法错误,但是变成异常了,会被处理。

注意,try里不能写成print(f"{eval(‘{a=}’)}“),因为转换后成了print(f”{{a=}}"),嵌套了两层{},即使用Python3.8跑也会抛出异常。

如果觉得try-except不够优雅,可以执行时判断Python版本决定执行不同版本的代码,两种方法是等效的:

import sys
a='123'
if sys.version_info > (3, 8):
    print(eval("f'{a=}'"))
else:
    print(f'a={a}')

虽然是>(3,8),但是包括3.8的,因为sys.version_info是一个有5位的元组,3.8的各个版本的前两位是3和8,第3位是细分位,例如3.8.3版本就是(3,8,3,…)。我们知道即使是(3,8,0,…)和(3,8)比较时也是更大的,所以3.8的所有细分版本都是会通过的。

同样的,可以用eval方法解决海象(warlus)运算符(只有3.8及以上支持)的兼容问题:

def test_fun(num):
    if num:
        return (num,num)
    else:
        return None
try:
    a,b=ret if eval('(ret:=test_fun(1))') else (0,0)
except:
    ret = test_fun(1)
    if ret:
        a,b=ret
    else:
        a,b=(0,0)
print(a,b)

Python3.6及以上版本运行结果均为:

1 1

要注意的是,eval部分不能写成(eval(‘ret:=test_fun(1)’))。因为eval外层的括号会被忽略,而海象运算符的优先级是最低的,会导致执行整个表达式时运算顺序混乱,执行时会报错。

当然,虽然这种方法可以兼容不同的Python版本,但是会导致代码变得复杂,因此除非很有必要用只有高版本支持的写法,否则统一用低版本的写法是最简洁的。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值