如何避免Python中的对象别名?

8 投票
7 回答
11387 浏览
提问于 2025-04-16 09:31

我正在尝试写一个函数,用来检查一个列表是否是排好序的(返回 TrueFalse)。我该怎么做才能避免多个变量指向同一个东西呢?

def is_sorted(t):
    a = t
    a.sort()

当我这样做的时候,它会把 at 都排序了。我该怎么避免这种情况呢?

7 个回答

3

你可以通过创建一个列表的副本来做到这一点,像这样:

def is_sorted(t):  
    a = t[:]  # create a copy
    a.sort()
6

编辑: 请查看 这个回答,了解正确的做法。我会把我的回答留在这里以供后人参考(处理这种情况的正确方法是什么?),但这不应该被视为问题的最佳答案,即使它是一个正确的答案。


针对你的具体问题,你可以使用 copy.copy(或者用切片语法 [:])来创建原始列表的一个副本:

import copy

def is_sorted(t):
    a = copy.copy(t) # could also do: a = t[:]
    a.sort()
    return a == t

不过,更好的方法是使用 sorted 函数来返回一个排序后的列表副本:

def is_sorted(t):
    return sorted(t) == t

或者: is_sorted = lambda t: sorted(t) == t

9

这里有一种O(n)的做法

>>> from itertools import islice, izip
>>> def is_sorted(L):
...     return all(i<=j for i,j in izip(L, islice(L,1,None)))
... 
>>> is_sorted(range(50))
True
>>> is_sorted(range(50)+[20])
False

它会短路,所以如果列表在一开始就没有排序的话,速度会非常快

下面是一个简单的程序,用来比较一些其他的选择

import random
import time
from itertools import islice, izip

def is_sorted1(L):  # 0.0006s
    return all(i<=j for i,j in izip(L, islice(L,1,None)))

def is_sorted2(L):  # 0.117s
    return all(L[i] < L[i+1] for i in range(len(L)-1) )

def is_sorted3(L):  # 2.344s
    return L == sorted(L)

def is_sorted4(L):  # 0.0002s
    return all(L[i] < L[i+1] for i in xrange(len(L)-1) )

A = [range(random.randrange(100000)) for i in range(100)]
for a in A:
    random.shuffle(a)

for f in is_sorted1, is_sorted2, is_sorted3, is_sorted4:
    s=time.time()
    for a in A:
        f(a)
    print time.time() - s

撰写回答