【问题标题】:variable is not None works but not variable doesn't workvariable is not None 有效,但 not variable 无效
【发布时间】:2022-01-15 04:07:21
【问题描述】:

我试图解决 Pyhon 3.x 中的动态编程问题。我想创建一个备忘录字典对象。在将None 的默认值分配给memo 参数后,Nonenot object 的检查似乎不起作用,但如果我将其更改为object is None,它工作正常。 不起作用,我的意思是在not object 的情况下,此条件不会评估为True,并且不会执行以下缩进代码。 这会导致 LeetCode 上的 TLE。但是使用is None check 确实有效,它为备忘录分配了一个字典,因此缓存按预期工作,并且解决方案通过了。

为什么会这样?

        def lcs(i, j, memo = None):
            if not memo:
                memo = {}

        def lcs(i, j, memo = None):
            if memo is None:
                memo = {}

我用return lcs(0, 0)调用了这个函数。

编辑:在我的系统 Python IDLE 上,两个表达式的计算结果都为 True。所以我认为,LeetCode 平台对代码的处理方式不同。

编辑 2:在@buran 指出之后的某个时候,这些部分 sn-ps 也在 LeetCode 上产生了预期的结果,我也尝试了部分 sn-ps,它们确实给出了预期的结果。但是当我尝试整个代码(从过去的提交中使用)时,令人惊讶的是它也给出了预期的结果(实际上创建了新的备忘录)。直到今天,我才能真正重现我早些时候遇到的问题。 对于不同的问题,代码再次显示相同的行为,现在我想我在这里遗漏了一些东西。这就是我这次发布整个代码的原因。有人可以发现并解释为什么这两个代码给出不同的结果。

class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        
        def lps(l, r, memo = None):
            if memo is None:
                memo = {}
            if (l, r) not in memo:
                if l > r:
                    memo[(l, r)] = 0
                elif l == r:
                    memo[(l, r)] = 1
                elif s[l] == s[r]:
                    memo[(l, r)] = lps(l+1, r-1, memo) + 2
                else:
                    memo[(l, r)] = max(lps(l+1, r, memo), lps(l, r-1, memo))
            return memo[(l, r)]
        
        return lps(0, len(s)-1)

class Solution:
    def longestPalindromeSubseq(self, s: str) -> int:
        
        def lps(l, r, memo = None):
            if not memo:
                memo = {}
            if (l, r) not in memo:
                if l > r:
                    memo[(l, r)] = 0
                elif l == r:
                    memo[(l, r)] = 1
                elif s[l] == s[r]:
                    memo[(l, r)] = lps(l+1, r-1, memo) + 2
                else:
                    memo[(l, r)] = max(lps(l+1, r, memo), lps(l, r-1, memo))
            return memo[(l, r)]
        
        return lps(0, len(s)-1)

还有人可以告诉我是否应该从我过去的编辑或原始帖子中删除以及应该删除什么。这正在成为一个非常长的帖子。 (我是新来的)

【问题讨论】:

  • 你能澄清什么“不起作用”吗?是否抛出错误?结果不是你预期的吗?如果可能,请提供代码以便他人可以复制和粘贴来说明问题。
  • 这不是你要问的,而是def lcs(i, j, memo = {}):
  • @danh - 默认值可能很棘手。在您的示例中,当缺少参数时,始终使用一个默认的 dict 对象。每个调用都会得到相同的字典,它将保存来自其他调用的任何数据。
  • @danh 使用可变默认参数被认为是一种不好的做法,并且可能导致棘手的错误。见docs.python-guide.org/writing/gotchas/…docs.quantifiedcode.com/python-anti-patterns/correctness/…
  • 请发帖minimal reproducible example。目前,当您调用 lcs(0, 0) 时,两个 sn-ps memo 将是空字典。鉴于 lcs() 不返回任何内容(因此返回 None)并且您将其称为 return 语句的一部分 return lcs() 可能还有其他事情发生 - 范围问题或 if/else 块或其他问题

标签: python-3.x function nonetype


【解决方案1】:

not 是一个关键字,相当于!=。所以它的含义完全不同。

您可以使用not 关键字如下(例如)

def lcs(i, j, memo = None):
            if memo is not None:
                memo = {}

上面的代码等价于

def lcs(i, j, memo = None):
            if memo != None:
                memo = {}

如果你想那么糟糕地使用not 关键字,请使用此代码。

def lcs(i, j, memo = None):
            if not memo == None:
                memo = {}

如果您有任何疑问,请告诉我。

【讨论】:

  • 您的第一个示例if memo is not None: memo = {} 是倒退的。如果用户传入一个,它只会分配字典。not!= 不同(它们由不同的魔术方法实现,不必解析为相同的真值)。 None 是 python 中为数不多的有保证的单例之一。 memo is Nonememo is not None 是首选的测试方式。
【解决方案2】:

来自Truth Value Testing

默认情况下,一个对象被认为是真,除非它的类定义了一个返回 False 的 bool() 方法或一个返回零的 len() 方法.

空的dict 的长度为零,False 也是如此。如果您使用备忘录字典调用lcs,但该字典恰好没有任何内容,它将测试Falseif not memo: memo = {} 将为您创建一个新的备忘录对象。该代码无法区分空备忘录和无。

if memo is None 是分配备忘录的正确方法,仅当调用者没有传入备忘录时。

【讨论】:

    【解决方案3】:

    我已经有一段时间没有使用 Python 了,所以请耐心等待,但我想我可以解释一下一般的编程概念。

    在第一个中,您正在检查备忘录是否不存在。

    if not memo
    

    如果备忘录不存在则继续的意思。

    在第二个中,您正在检查备忘录确实存在并且它被设置为无。

    if memo is None
    

    如果 memo 存在则继续(进入检查的先决条件)并且它被设置为 None

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-12
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 2015-10-13
      • 1970-01-01
      • 2021-10-12
      相关资源
      最近更新 更多