Python 类变量在方法结束后因未将 deepcopy 应用于列表而发生更改

Posted

技术标签:

【中文标题】Python 类变量在方法结束后因未将 deepcopy 应用于列表而发生更改【英文标题】:Python class variable getting changed after method ends for not applying deepcopy to list 【发布时间】:2020-11-12 14:56:01 【问题描述】:

试图在 python 中使用回溯解决这个 leetcode 问题 -

Given a string s, partition s such that every substring of the partition is a palindrome. 
Return all possible palindrome partitioning of s.

得到这个解决方案的奇怪输出 -

class Solution:
    
    a = list()

    def backtrack(self, start, string, palindrome, stack):

        if start == len(string):
            self.a.append(stack)
            return
        if start == len(string)-1:
            stack.append(string[start])
            self.a.append(stack)
            stack.pop()
            return

        for end in range(start, len(string)):
            if start == end:
                stack.append(string[start])
                self.backtrack(start+1, string, palindrome, stack)
                stack.pop()

            elif string[start] == string[end] and ((end == start+1) or palindrome[start+1][end-1]):
                stack.append(string[start:end+1])
                palindrome[start][end] = True
                self.backtrack(end+1, string, palindrome, stack)
                stack.pop()

    def partition(self, string):
        stack =  []
        self.a.clear()
        palindrome = [[False for __ in range(len(string))] for _ in range(len(string))]
        for i in range(len(string)):
            palindrome[i][i] = True
        self.backtrack(0, string, palindrome, stack)
        return self.a

输入:aab

输出:

[[],[]]

此代码有效,只是将list 更改为set 并进行了其他小改动

class Solution:
    
    a = set()

    def backtrack(self, start, string, palindrome, stack):

        if start == len(string):
            if ",".join(stack) not in self.a:
                self.a.add(",".join(stack))
            return
        if start == len(string)-1:
            stack.append(string[start])
            if ",".join(stack) not in self.a:
                self.a.add(",".join(stack))
            stack.pop()
            return

        for end in range(start, len(string)):
            if start == end:
                stack.append(string[start])
                self.backtrack(start+1, string, palindrome, stack)
                stack.pop()

            elif string[start] == string[end] and ((end == start+1) or palindrome[start+1][end-1]):
                stack.append(string[start:end+1])
                palindrome[start][end] = True
                self.backtrack(end+1, string, palindrome, stack)
                stack.pop()

    def partition(self, string):
        stack = answer = []
        palindrome = [[False for __ in range(len(string))] for _ in range(len(string))]
        for i in range(len(string)):
            palindrome[i][i] = True
        self.backtrack(0, string, palindrome, stack)
        ans = [item.split(",") for item in self.a]
        self.a.clear()
        return ans

输入:aab

输出:[["a","a","b"],["aa","b"]]

问题:https://leetcode.com/problems/palindrome-partitioning/

【问题讨论】:

【参考方案1】: 下面是类似的深度优先搜索解决方案,但语句较少:
class Solution:
    def partition(self, s):
        res = []
        self.depth_first_search(s, [], res)
        return res

    def depth_first_search(self, s, path, res):
        if not s:
            res.append(path)
            return
        for i in range(1, len(s) + 1):
            if self.is_palindrome(s[:i]):
                self.depth_first_search(s[i:], path + [s[:i]], res)

    def is_palindrome(self, s):
        return s == s[::-1]


print(Solution().partition("aab"))    

【讨论】:

是的,方法是在内部调用的,没有显示出来。谢谢,您的解决方案非常优雅。【参考方案2】:

想通了!我必须在第一个代码中附加stack 时应用copy.deepcopy

from copy import deepcopy

a = list()

def backtrack(self, start, string, palindrome, stack):

    if start == len(string):
        dc = deepcopy(stack)
        self.a.append(dc)
        return
    if start == len(string)-1:
        stack.append(string[start])
        dc = deepcopy(stack)
        self.a.append(dc)
        stack.pop()
        return

在 python 中,列表的副本并不总是创建一个新对象。比如——

>>> l=[1,2,3,4]
>>> x = l
>>> del l[1]
>>> l
[1, 3, 4]
>>> x
[1, 3, 4]

在上面的代码中,x and l指向同一个列表

在使用 copy.deepcopy 时,会创建一个新列表 -

>>> from copy import deepcopy
>>> l=[1,2,3,4]
>>> x = deepcopy(l)
>>> del l[1]
>>> l
[1, 3, 4]
>>> x
[1, 2, 3, 4]

【讨论】:

Python 列表的执行方式不同。因此,如果我删除 deepcopy,我将得到空列表,因为堆栈最终会完全弹出。刚学会这个。 python 新手。所以,面对一堆问题

以上是关于Python 类变量在方法结束后因未将 deepcopy 应用于列表而发生更改的主要内容,如果未能解决你的问题,请参考以下文章

Swift:应用程序因未捕获的异常“NSUnknownKeyException”而终止

@Autowired使用说明

@Autowired使用说明

OpenArgs 未将变量传递给报告

Bash:导出未将变量正确传递给父级

wpf 出现错误 System.NullReferenceException:“未将对象引用设置到对象的实例“