1、引言
这个运算符为什么跟海象联系在一起呢?因为看起来像是躺着的海象,其中眼睛和牙齿的形象表示就是海象运算符了,如下图:
海象运算符,也叫做海象选择器,在Go语言中很常见,Python3.8也开始引入,我们在前面的ROS键盘遥控机器人,通过参数服务器指定速度 中有介绍,使用参数指定速度的时候,使用的就是海象运算符
./keys_to_twist_ramps.py _linear_scale:=0.5 _angular_scale:=1.0 _linear_accel:=1.0 _angular_accel:=1.0
在启动launch文件的时候,有时候也比较常用到这个海象运算符,比如加载模型描述文件:
roslaunch pkg_name xxx.launch model:='$(find urdf_pkg)/urdf/x.urdf'
其用法跟赋值运算符=,看起来是特别类似,不过还是区别很大的。
既然在新的版本引入它,我想应该是存在一些优势,所以借鉴进来,GoGoGo我们一起来了解下。
2、示例
使用海象运算符可以将代码变得更加的简洁,而且在某些情况下,使用海象运算符可以提高代码的性能。比如将表达式的部分值赋值给变量,可以避免在循环中重复计算相同的表达式,从而提高代码的效率。
2.1、赋值
赋值运算是最常见的,这种情况是可以使用海象运算符,让代码变得更简洁高效
x = 11
if x > 10:print("x大于10")
#转换成海象运算符
if (y := 11) > 10:print("y大于10")
x="hello world"
n=len(x)
if (n > 10):print(f"x长度{n},大于10")
#x长度11,大于10
#转换成海象运算符
y="hello chyichin"
if (n := len(y)) > 10:print(f"y长度{n},大于10")
#y长度14,大于10
通过海象运算符,这里的n就不需要要再次计算字符串的长度了。
2.2、循环
n=3
while n:
print(n)
n-=1
/*
2
1
0
*/
转成海象运算符:
n=3
while (n := n-1)+1:
print(n)
/*
2
1
0
*/
同样的,在下面这个获得输入的情况下,也是可以直接获取并赋值的
while True:
txt=input("输入hello:")
if(txt=='hello'):break
#转成海象运算符:
while (txt := input("输入hello:"))!='hello':continue
2.3、读取文件
读取文件时,使用while来不断读取,其用法也是同上:
f = open('test.txt','r',encoding='utf-8')
while True:
content=f.read()
if not content:break
print(content)
f.close()
换成海象运算符:
f = open('test.txt','r',encoding='utf-8')
while content := f.read():
print(content)
2.4、列表推导
使用列表推导的时候,海象运算符可以提高性能,我们来看个示例,常规的一个写法:
l=[1,3,5,7,9]
n=0
def f(x):
global n
n+=1
print(f"执行次数:{n}")
return x**2
print([f(i) for i in l if f(i)>1])
/*
执行次数:1
执行次数:2
执行次数:3
执行次数:4
执行次数:5
执行次数:6
执行次数:7
执行次数:8
执行次数:9
[9, 25, 49, 81]
*/
我们来看下其执行的一个过程:5个数的平方,执行5次,另外从列表[1, 9, 25, 49, 81]获取大于1的值,满足条件的值有4个,所以需再次执行4次,所以总计执行9次。
而我们换成海象运算符的情况,只需要执行5次即可,如下:
l=[1,3,5,7,9]
n=0
def f(x):
global n
n+=1
print(f"执行次数:{n}")
return x**2
print([x for i in l if (x := f(i))>1])
/*
执行次数:1
执行次数:2
执行次数:3
执行次数:4
执行次数:5
[9, 25, 49, 81]
*/
3、区别
这里的区别主要是针对赋值运算符=,因为看起来很像,所以需要注意一些常见的场景是不能使用海象运算符的
3.1、赋值运算
a=1这个没有问题,如果使用海象运算符a:=1
File "<stdin>", line 1
a:=1
^
SyntaxError: invalid syntax
就会报语法错误。所以这样直接进行赋值操作是不可以的,也没有必要。
3.2、符合赋值运算
同样的,a+=3这样的复合赋值运算符,也不能使用海象运算符a:+=3
File "<stdin>", line 1
a:+=3
^
SyntaxError: invalid syntax
3.3、匿名函数
另外注意lambda表示的用法
f1=lambda x:x**3
f1(3)
#27
这样常规写是没有问题,如果换成海象运算符也是不行的
f2:=lambda x:x**3
File "<stdin>", line 1
f2:=lambda x:x**3
^
SyntaxError: invalid syntax
需要小括号括起来,这样就可以了
(f2:=lambda x:x**3)
f2(4)
#64
我们用海象运算符本身的目的是,使代码更加简洁优雅和提高性能,如果过度或者不当的使用,反而会使代码的可读性和性能都下降。所以还是看场景来运用,一切都是为了代码的可读性和计算的性能,不能舍本逐末!