我是一位经验丰富的程序员但不熟悉Python,所以我不知道我在这里看到的是我特有的Python行为,而我并不知道。我通常使用C ++和C#编程,因此我在两种语言中都包含了代码示例以演示不同的结果。
我正在做的是运行递归搜索功能,使用状态结构来记录结果。在C#中它的行为与预期的一样,但在Python中它似乎(据我所知),不区分当前/最后一次递归调用中存在的状态。我知道Python通过引用管理对象(如在C#中) - 我在对对象进行深入复制之前将其进一步传递给搜索函数。
首先提供C#版本和结果:
class SimState
{
public List<string> stateDescriptions = new List<string>();
public SimState Clone()
{
return new SimState() {
stateDescriptions = new List<string>(this.stateDescriptions)
};
}
}
class Program
{
public void search_recursive(SimState state,int move,int recurseDepth)
{
if (recurseDepth > 2)
return;
state.stateDescriptions.Add(move.ToString());
Console.WriteLine(String.Format("{0}: {1}",
recurseDepth,
String.Join(",", state.stateDescriptions)));
for(int n = 0;n < 2;n++)
{
var newState = state.Clone();
this.search_recursive(newState, n + 1, recurseDepth + 1);
}
}
static void Main(string[] args)
{
var initialState = new SimState();
new Program().search_recursive(initialState, 0, 0);
Console.ReadKey();
}
}
结果:这就是我期望发生的事情。它将所有组合搜索到最大值。深度为2:
0: 0
1: 0,1
2: 0,1,1
2: 0,1,2
1: 0,2
2: 0,2,1
2: 0,2,2
到目前为止一切顺利。现在,我认为是一个等效的Python程序:
import copy
class SimState:
stateDescriptions = []
def search_recursive(state: SimState, move, recurseDepth):
if(recurseDepth > 2):
return
state.stateDescriptions.append('{0}'.format(move))
print('{0}: '.format(recurseDepth) + ','.join(state.stateDescriptions))
for n in range(2):
newState = copy.deepcopy(state)
search_recursive(newState,n + 1,recurseDepth + 1)
initialState = SimState()
search_recursive(initialState,0,0)
结果:
0: 0
1: 0,1
2: 0,1,1
2: 0,1,1,2
1: 0,1,1,2,2
2: 0,1,1,2,2,1
2: 0,1,1,2,2,1,2
似乎Python没有意识到我传入一个全新的状态(通过新的深度复制&#39; newState&#39;),而是更新现有的&# 39;状态&#39;来自之前的递归调用。我很清楚SO&#34; "Least Astonishment" and the Mutable Default Argument&#34;)上的帖子,但这似乎是指默认参数,这里没有使用。
我在Visual Studio 2017中使用Python 3.6。
我错过了一些明显的东西吗?感谢
答案 0 :(得分:3)
问题是你的班级定义。您在Python中编写的内容创建了一个类变量,可能来自C#背景,可以说它会创建一个&#34;静态属性&#34;。无论如何,您需要一个实例属性,如下所示:
In [2]: import copy
...:
...: class SimState:
...: def __init__(self):
...: self.stateDescriptions = []
...:
...: def search_recursive(state: SimState, move, recurseDepth):
...: if(recurseDepth > 2):
...: return
...: state.stateDescriptions.append('{0}'.format(move))
...: print('{0}: '.format(recurseDepth) + ','.join(state.stateDescriptions))
...: for n in range(2):
...: newState = copy.deepcopy(state)
...: search_recursive(newState,n + 1,recurseDepth + 1)
...:
...: initialState = SimState()
...: search_recursive(initialState,0,0)
...:
0: 0
1: 0,1
2: 0,1,1
2: 0,1,2
1: 0,2
2: 0,2,1
2: 0,2,2
另外,我不确定你的意思&#34; python通过引用管理对象&#34;,但Python 不支持call-by-reference 语义。它的语义类似于Java - 除了Python是一种纯OOP语言,没有原始类型,一切都是一个对象(所以,它就像Java,除了一切是一个引用类型) 。此策略在技术上称为call by object sharing