Python 3.x 为什么数组中的元素被过度写入?
我用Python编写了一个简单的函数,其目的是发现,如果从两个元素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]
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数组实际上指的是Pythonlist
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