我想实现与第三版CLRS的问题2-4相关的python代码。问题是“在列表中找到反转的数量”,并且我写了这个代码:
mainCounter = 0
def merg(array,counter):
if len(array)==1:
return array
left = array[:len(array)/2]
right = array[len(array)/2:]
return combine(merg(left, counter), merg(right, counter), counter)
def combine(array1, array2, counter):
global mainCounter
result = []
pointer1 = 0
pointer2 = 0
while(pointer1 != len(array1) and pointer2 != len(array2)):
if array1[pointer1] < array2[pointer2]:
result.append(array1[pointer1])
pointer1 += 1
elif array1[pointer1] == array2[pointer2]:
result.append(array1[pointer1])
pointer1 += 1
else:
result.append(array2[pointer2])
counter += (len(array1)-pointer1)
pointer2 += 1
if pointer1 == len(array1):
for i in array2[pointer2:]:
result.append(i)
else:
for i in array1[pointer1:]:
result.append(i)
mainCounter+=counter
return result
问题是当我在python控制台中导入此模块时,mainCounter没有改变,但必须更改!!:
Python 2.7.3 (default, Aug 1 2012, 05:16:07)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from mergSort import *
>>> merg([1,4,2,3],0)
0
0
2
[1, 2, 3, 4]
>>> merg([1,4,2,3],0)
2
2
4
[1, 2, 3, 4]
>>> mainCounter
0
>>> merg([1,4,2,3],0)
4
4
6
[1, 2, 3, 4]
>>> merg([1,4,2,3],0)
6
6
8
[1, 2, 3, 4]
>>> merg([1,4,2,3],0)
8
8
10
[1, 2, 3, 4]
>>> mainCounter
0
每次调用merg
函数时,我得到的结果都不同,但mainCounter没有改变!哪里错了?
答案 0 :(得分:4)
tldr:不要使用from module import *
import *
没有您想象的那么特别 - 当您使用from mergSort import *
导入内容时,请将其视为
import mergSort
mainCounter = mergSort.mainCounter
merg = mergSort.merg
del mergSort
所以你真的只引用了导入时mergSort.mainCounter
引用的int对象。 mergSort
使用mergSort.mainCounter
个;
>>> a = 1
>>> b = a
>>> a += 1 # or a = a + 1 or a = a.__add__(1)
>>> a
2
>>> b
1
我们对整数对象有两个单独的引用,并且递增一个(将引用更改为指向由旧对象上的方法调用生成的新对象)将不会影响另一个。要确认这一点,请尝试
merg.__globals__['mainCounter']
或
import sys; sys.modules[merg.__module__].mainCounter
这些应该具有merg正在使用的mainCounter值。
(sys.modules['mergSort'] is merg.__globals__
是真的,它们是相同的字典)
当一个名称在函数中声明为全局时,它将在函数模块的命名空间中查找。
import *
经常受到诽谤,因为它很难追踪名称的来源,但这里也很糟糕,因为它破坏了我们对模块的概念 - 只是因为你从模块导入*并不意味着你实际上在它的命名空间中,你刚刚完成了from module import a, b, c, d, e, ...
。这更糟糕,因为许多名称在Python中没有重新绑定,但有些名称一直都是,就像通过引用整数作为计数器的名称一样。
答案 1 :(得分:1)
完全不使用import *
是一种很好的做法。
您导入的对象对彼此一无所知,并且使用global mainCounter
无法提供帮助。
试试这个:
import mergSort
mergSort.merg([1, 4, 2, 3], 0)
print mergSort.mainCounter