【问题标题】:How come these strings are not equal?为什么这些字符串不相等?
【发布时间】:2016-08-12 08:19:27
【问题描述】:

我一直在尝试(供我个人使用)一些人对定时键盘输入的解决方案,唯一有效的是 Alex Martelli/martineau here. 的一个我使用了他们的第二个代码块(从import msvcrt),它对几乎所有东西都很有用,除了比较。如果没有及时输入输入,我将 None 的返回替换为空字符串,并且我使用了一些测试行,如下所示:

import msvcrt
import time 

def raw_input_with_timeout(prompt, timeout):
    print prompt,    
    finishat = time.time() + timeout
    result = []
    while True:
        if msvcrt.kbhit():
            result.append(msvcrt.getche())
            if result[-1] == '\r':   # or \n, whatever Win returns;-)
                return ''.join(result)
            time.sleep(0.1)          # just to yield to other processes/threads
        else:
            if time.time() > finishat:
                return ""

textVar = raw_input_with_timeout("Enter here: \n", 5)
print str(textVar)    # to make sure the string is being stored
print type(str(textVar))   # to make sure it is of type string and can be compared
print str(str(textVar) == "test")
time.sleep(10)   # so I can see the output

在我用 pyinstaller 编译后,运行它,然后在窗口中输入 test,我得到这个输出:

Enter here:
test
test
<type 'str'>
False

我最初认为比较返回 False,因为该函数将字符附加到数组中,这可能与它没有与字符串进行正确比较有关,但在进一步研究 Python 的工作方式之后(即, SilentGhost 的回复here),我真的不知道为什么比较不会返回 True。任何回应表示赞赏。谢谢!

【问题讨论】:

  • 使用print repr(textVar),我相信会出现差异。 print str("some string with unprintable bytes like \x00") 在功能上等同于 print "some string with unprintable bytes like \x00";两者都不会使该空字节可见(在大多数终端或控制台上)。 repr() 生成一个调试表示,它使用 Python 字符串文字语法为任何不可打印的内容使用转义序列创建一个 ASCII 安全的可复制值。
  • input 转换为str 不是多余的吗? input 总是被解释为字符串。
  • 请注意,print 已经在您尝试打印的任何内容上调用了str,这使得您所有的str() 调用都是多余的,即使对于布尔和str 类型的对象结果也是如此。
  • 也许你有一些隐藏的空白或换行符,尝试用textVar.strip()去掉它

标签: python python-2.7 input


【解决方案1】:

您将无法仅通过打印来了解字符串为何不同。字符串值可以包含打印时在控制台上不(容易)可见的字节。

使用repr() function 来生成调试友好的表示。这种表示会将字符串格式化为 Python 字符串文字,仅使用可打印的 ASCII 字符和转义序列:

>>> foo = 'test\t\n'
>>> print foo
test

>>> foo == 'test'
False
>>> print repr(foo)
'test\t\n'

在您的情况下,您在返回值中包含 \r 回车符:

if result[-1] == '\r':
    return ''.join(result)

最后一个\r 仍然存在,所以你至少会得到'test\r' 的值,但是\r 在打印时不会出现:

>>> print 'test\r'
test
>>> print repr('test\r')
'test\r'

您可以在加入时排除最后一个字符,方法是对字符串进行切片:

return ''.join(result[:-1])

或者您可以使用str.strip() 删除字符串开头和结尾的所有空白字符(包括\r 字符):

return ''.join(result).strip()

请注意,在这里使用str() 调用是没有意义的。你返回一个str 对象,所以str(textVar) 是多余的。此外,print 将调用 str() 对任何不是字符串对象的对象。

【讨论】:

    【解决方案2】:

    如果你考虑一下这段代码:

    result = []
    while True:
        if msvcrt.kbhit():
            result.append(msvcrt.getche())
            if result[-1] == '\r':   # or \n, whatever Win returns;-)
                return ''.join(result)
    

    可以看到,在构建输入字符串的时候,用户输入的最后一个字符一定是\r,也就是对应回车的不可打印字符。因此,返回的输入字符串如下所示:

    test\r
    

    我认为您需要重新编写代码以从输入中丢弃最终的不可打印字符。

    【讨论】:

      【解决方案3】:

      字符串后面可能有一些看不见的字节。尝试print([c for c in textVar]),如果它显示字符谎言'\r'\n 尝试str(textVar).strip() == "test" 或手动删除这些字符。

      【讨论】:

      • bytes 是 Python 2 中 str 的别名。
      • 打印一个容器会显示用repr()函数转换的内容。您在这里创建了一个非常冗长的repr(textVar)没有意义再次将字符串对象传递给str();在这里,textVar 已经始终是一个字符串。
      最近更新 更多