首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >海象运算符不给变量赋值?

海象运算符不给变量赋值?
EN

Stack Overflow用户
提问于 2021-11-15 16:23:51
回答 2查看 269关注 0票数 2

在玩walrus操作符时,我有一个合并排序的实现:

代码语言:javascript
复制
def mergesort(array):
    if len(array) == 1:
        output = array
    else:
        pivot = len(array) // 2
        left = mergesort(array[pivot:])
        right = mergesort(array[:pivot])
        output = []
        while (l := len(left)) or (r := len(right)):
            if l and r and left[0] < right[0]:
                output.append(left.pop(0))
            elif r:
                output.append(right.pop(0))
            else:
                output.append(left.pop(0))
        
    return output

mergesort([66, 93, 85, 46, 56, 88, 56, 75, 55, 99, 87])

但这将返回错误UnboundLocalError: local variable 'r' referenced before assignment

代码语言:javascript
复制
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
/tmp/ipykernel_134/1678992391.py in <module>
----> 1 mergesort(array)

/tmp/ipykernel_134/4030760045.py in mergesort(array)
      5     else:
      6         pivot = len(array) // 2
----> 7         left = mergesort(array[pivot:])
      8         right = mergesort(array[:pivot])
      9         

...

/tmp/ipykernel_134/4030760045.py in mergesort(array)
     10         output = []
     11         while (l := len(left)) or (r := len(right)):
---> 12             if l and r and left[0] < right[0]:
     13                 output.append(left.pop(0))
     14             elif r:

UnboundLocalError: local variable 'r' referenced before assignment

为什么在我的for循环中没有包括r,而l是吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-15 16:38:47

布尔或 or很懒,所以当l被证明是真的时,(r := len(right))甚至不会被执行。

在这种情况下,您可以使用非懒惰的按位或 |,尽管这是一种滥用。

或者只使用列表的真值而不是它们的长度:

代码语言:javascript
复制
while left or right:
    if left and right and left[0] < right[0]:
        output.append(left.pop(0))
    elif right:
        output.append(right.pop(0))
    else:
        output.append(left.pop(0))

顺便说一句,最好使用<=而不是<,这样就像mergesort应该是一个稳定的类型。

增编:玩乐与懒惰:

代码语言:javascript
复制
while left or right:
    which = (left or right)[0] <= (right or left)[0] and left or right
    output.append(which.pop(0))

另外,请注意,我切换到了while ... and ...,并在循环之后追加了剩下的非空的:

代码语言:javascript
复制
while left and right:
    which = left if left[0] <= right[0] else right
    output.append(which.pop(0))
output += left or right

或者回到你的风格:

代码语言:javascript
复制
while left and right:
    if left[0] <= right[0]:
        output.append(left.pop(0))
    else:
        output.append(right.pop(0))
output.extend(left or right)
票数 5
EN

Stack Overflow用户

发布于 2021-11-15 16:23:51

  1. Python获取len(left)表达式并将其计算为True
  2. 这意味着它可以立即进入while循环,而不必检查第二个语句len(right),因为懒惰懒惰
  3. 但是,这意味着r没有实例化,因为它没有被计算

不幸的是,在表达式周围加上额外的括号没有任何作用。

while ( (l:=len(left)) or (r:=len(right)) ):不起作用。

解决这个问题的一个选择是使用+而不是or,因为它们具有相同的逻辑意义,但是+需要计算表达式的右侧。

例如。

代码语言:javascript
复制
def mergesort(array):
    if len(array) == 1:
        output = array
    else:
        pivot = len(array) // 2
        left = mergesort(array[pivot:])
        right = mergesort(array[:pivot])
        output = []
        while (l:=len(left)) + (r:=len(right)):
            if l and r and left[0] < right[0]:
                output.append(left.pop(0))
            elif r:
                output.append(right.pop(0))
            else:
                output.append(left.pop(0))
        
    return output

顺便说一句,如果您对while X and Y ( X=0 )也有同样的问题,那么您可以使用类似的技巧,但是从0 * n == 0开始,您可以用*代替or,而不是用+代替and。即while X * Y

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69977641

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档