Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 为什么数组中的元素被过度写入?_Python 3.x - Fatal编程技术网

Python 3.x 为什么数组中的元素被过度写入?

Python 3.x 为什么数组中的元素被过度写入?,python-3.x,Python 3.x,我用Python编写了一个简单的函数,其目的是发现,如果从两个元素a和b中,可以通过交换其中一个数组中最多一对元素从另一个元素中获得一个元素 这是我的职责: def areSimilar(a, b): test = 0 for i in range(len(b)): for j in range(len(b)): b2 = b b2[i] = b[j] b2[j] = b[i]

我用Python编写了一个简单的函数,其目的是发现,如果从两个元素
a
b
中,可以通过交换其中一个数组中最多一对元素从另一个元素中获得一个元素

这是我的职责:

def areSimilar(a, b):
    test = 0
    for i in range(len(b)):
        for j in range(len(b)):
            b2 = b
            b2[i] = b[j]
            b2[j] = b[i]
            if a == b2:
                test = 1
    return(test==1)
问题是,在检查
b
时,即使我没有对
b
执行任何计算,它也发生了变化-发生了什么事

我会使用的代码,但如果要复制,请使用:

import copy
def areSimilar(a, b):
    test = 0
    for i in range(len(b)):
        for j in range(len(b)):
            b2 = copy.deepcopy(b)
            b2[i] = copy.deepcopy(b[j])
            b2[j] = copy.deepcopy(b[i])
            if a == b2:
                test = 1
    if test == 1:
        return True
    else:
        return False
已编辑:更好地解决第二点)

您的代码有两个问题:

  • 当您执行
    b2=b
    操作时,这只会创建对底层对象的另一个引用。如果
    b
    是可变的,则对
    b2
    所做的任何更改也将反映在
    b
  • 当一次交换足够时,无需进一步测试,但如果继续循环,测试将在交换
    i
    j
    的情况下再次成功,因此
    test
    条件要么从未达到,要么(至少——取决于重复的数量)达到两次。虽然这不会导致错误的结果,但通常会被视为逻辑错误
要修复代码,只需创建
b
的副本即可。假设Python数组实际上指的是Python
list
s这样做的一种方法是每次用
b2=list(b)
替换
b2=b
,创建一个新的
list
。更有效的方法是在
b
本身上执行交换(并回交换):


相比之下,您可以看到基于复制的方法是多么低效(尽管正确):

def are_similar2(a, b):
    for i in range(len(b)):
        for j in range(len(b)):
            b2 = list(b)
            b2[i] = b[j]
            b2[j] = b[i]
            if a == b2:
                return True
    return False


print(are_similar2([1, 1, 2, 3], [1, 2, 1, 3]))
# True
print(are_similar2([1, 1, 2, 3], [3, 2, 1, 1]))
# False
即使在输入相对较小的情况下,计时也要差得多:

a = [1, 1, 2, 3] + list(range(100))
b = [1, 2, 1, 3] + list(range(100))
%timeit are_similar(a, b)
# 10000 loops, best of 3: 22.9 µs per loop
%timeit are_similar2(a, b)
# 10000 loops, best of 3: 73.9 µs per loop

为什么要在这里执行deepcopy()?从避免嵌套对象的副作用的意义上讲,这当然是“更安全的”,但实际上并不需要这样做,特别是在实现交换时,在交换时,您可以只使用
b2
,但这将对性能产生相当大的影响。此外,无需进一步测试,一旦测试值为1,您就可以返回。
a = [1, 1, 2, 3] + list(range(100))
b = [1, 2, 1, 3] + list(range(100))
%timeit are_similar(a, b)
# 10000 loops, best of 3: 22.9 µs per loop
%timeit are_similar2(a, b)
# 10000 loops, best of 3: 73.9 µs per loop