python函数的原地修改or返回值

python中有一坨神奇的函数,他们名字类似,但是有的是原地修改,有的是返回值。
比如sort,sorted

>>> a
[3, 7, 5, 1]
>>> sorted(a)
[1, 3, 5, 7]
>>> a
[3, 7, 5, 1]
>>> a.sort()
>>> a
[1, 3, 5, 7]

注意的是a.sort()是没有返回值的,但是修改了a。sorted(a)返回的是排序后的a,但是a却没变。
这个东西太简单了以至于我觉得我没这么二会犯错…
直到我在写寻找最大k个数的程序时:

#coding: utf-8
# import heapq
import random

def kbig(s, k):
    if k <= 0:
        return []
    if len(s) <= k:
        return s
    sa, sb = partition(s)
    # print sa, sb, k
    left  = kbig(sa, k)
    print left
    right = kbig(sb, k - len(sa))
    print left, right
    left.extend(right)
    return left
    # return kbig(sa, k).extend(kbig(sb, k - len(sa))) # wrong!
    # return kbig(sa, k) + kbig(sb, k - len(sa))  #right!

def partition(s):
    sa, sb = [], []
    choice = random.randint(0, len(s) - 1)
    s[0], s[choice] = s[choice], s[0]
    p = s[0]
    for i in range(1, len(s)):
        sa.append(s[i]) if s[i] > p else sb.append(s[i])
    sa.append(p) if len(sa) < len(sb) else sb.append(p)
    return (sa, sb)

def main():
    a = [4, 5, 3, 7, 9, 10, 2]
    k = 3
    print kbig(a, k)
    # print heapq.nlargest(k, a)

if __name__ == '__main__':
    main()

上面代码没改,包括了我的各种调试。
我一开始递归返回值用的extend,一直悲剧我还反应不过来…
好方法就是用列表的’+’运算,当然返回extend后的前一个列表也可。

另外注释的headq那一行是python中的优先级堆库,一个函数nlargest输出结果很爽!

sa.append(s[i]) if s[i] > p else sb.append(s[i]) 中的A if B else C是python版本的三元运算符,mark一记(其实我还是习惯A? B: C这样…不过python一直追求的是代码的可读性和直白,直接if else也是广大人民的诉求=。=)。

s[0], s[choice] = s[choice], s[0] 注意到没有,这就是python交换两个数的最佳solution,那些要多设置一个临时变量的C神马的真心弱爆了!

Tags :

2 thoughts on “python函数的原地修改or返回值”

  1. 上学期重修数据结构的时候发现用自己写的heap做sort和headq库相比速度差了20多倍百思不得其解…看了源码觉得算法应该都是一样的啊…有空可以试试
    另A if B else C 和 A and B or C是一样的吗?

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Click the right image To submit your comment: