首页 > 编程知识 正文

解包赋值是什么意思,解包赋值能够使得赋值过程变得更简洁

时间:2023-05-06 14:41:48 阅读:242005 作者:2982

解包赋值是一个方便代码编写的语法特性,在一个赋值语句中可将右边表达式的值自动解开赋值给左边,如:
a, b = t简单看上去相当于:
a = t[0]b = t[1]不过若t的位置是一个表达式,则下面这样做就必须用一个临时变量来防止重复求值,事实上这个代码和解包并不等价,解包赋值的具体步骤更复杂一点:
首先,计算右边的表达式,以及左边的各左值元素中的需计算部分(如果有的话,比如a[i + 1], b = t),而这两者的计算顺序则根据语言定义
其次,根据左边的元素数量,将右边表达式转换为对应大小的数组,转换过程是直接迭代,换句话说,右边的表达式不一定需要是一个tuple/list/dict/set等,只要可迭代就行;转换完后,需要检查数量和数组大小的一致性,即上例中,假如t的元素不为2个,无论多余或少于,都会报异常
最后,将对应位置的左值和数组元素做赋值操作,需要注意的是,这个赋值不仅可以是简单赋值,也可以有解包操作,例如:
a, (b, c) = tt中有两个元素,第一个赋给a,第二个对b,c再做一次解包


这个语法的好处在于可以让代码简单明了,尤其是在循环语句中:
for a, b in l: ... //循环体而不用写成:
for t in l: a = t[0] b = t[1] //假设l的元素是一个二元组,假如是一个迭代器,则这里更麻烦 ... //循环体<span style="font-family: Arial, Helvetica, sans-serif;"></span>

在larva中也实现了python的这个语法,不过做了一点小小的限制,全局变量初始化不能使用,全局变量必须采用“变量名=表达式”这种方式初始化,另外,函数参数也不能写成解包的形式,比如:

func f(a, (b, c)):这个形式在python中是可以的

有些语言变相实现了类似的语法,比如go语言函数的多值返回,不过它这个实现相当于C语言中多值返回的一种变形,C代码:
void f(int in, int *out_1, int *out_2, int *out_3)go也有指针,所以就是个语法糖的事情了


不过,python和larva的解包赋值按照上面说的实现,有一个小问题,比如这个例子(python代码):
l = [1,2,3,4]it = iter(l)try: a, b = itexcept ValueError: passfor i in it: print i最后这个for循环会打印出4,原因也很简单,在执行解包赋值的时候,对it进行迭代,发现有超过2个元素(也就是next()执行了三次),异常被捕获忽略后,it的状态是l的第四个元素,可以继续迭代。这个似乎有些设计上的不合理,不过考虑到正常代码几乎不会碰到这种情况,所以也在可接受范围了


具体到larva目前的转java代码实现,在LarUtil类中有一个函数unpack_seq,输入一个LarObj和大小n,它会对输入的LarObj进行迭代,转换成一个大小为n的LarObj[],如果这个过程中检查到大小不一致,则异常,具体的实现可以看git上的代码

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。