一个诡异的Python小问题

Posted 老吴的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个诡异的Python小问题相关的知识,希望对你有一定的参考价值。

一个诡异的Python小问题

问题

  • 来自一个基础偏弱的学员,但不知道如何去解释

    >>> \'\' is not None
    <stdin>:1: SyntaxWarning: "is not" with a literal. Did you mean "!="?
    True  # 注意结果是会出现的,其实不影响你的比较
    
  • 在我想来,这没啥毛病啊,可提示了语法警告

  • 于是我去搜了下为何,捅了个马蜂窝

搜索

  • 搜到的众多结果中,多有这样一段描述

    从 python 3.8 开始,使用 is 和 is not 运算符时,会抛出 SyntaxWarning 语句警告信息
    
  • 首先这肯定是不准确的描述,要真是,那还了得,所有的is / is not 都有问题?

  • 比如

    >>> [] is not None
    True
    
  • 但既然这么说应该也多少有点依据

Python3.8 CHANGELOG

  • 英文描述

    The compiler now produces a SyntaxWarning when identity checks (is and is not) are used with certain types of literals (e.g. strings, numbers). These can often work by accident in CPython, but are not guaranteed by the language spec. The warning advises users to use equality tests (== and !=) instead. (Contributed by Serhiy Storchaka in bpo-34850.)
    
  • 中文描述

    当标识号检测 (is 和 is not) 与特定类型的字面值 (例如字符串和数字) 一同使用时编译器现在会产生 SyntaxWarning。 这在 CPython 中通常是可行的,但并不被语言定义所保证。 该警告会建议用户改用相等性检测 (== and !=)。 (由 Serhiy Storchaka 在 bpo-34850 中贡献。)
    

测试

  • 根据上面的描述做几个测试

  • Python3.7环境的确没毛病

    D:\\Python37>python
    Python 3.7.5 (tags/v3.7.5:5c02a39a0b, Oct 15 2019, 00:11:34) [MSC v.1916 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> \'\' is not None
    True
    

  • 关键:标识号检测 (is 和 is not) 与特定类型的字面值 (例如字符串和数字)

    >>> 1 is None  # 的确数字也有问题 is None和is not None类似
    <stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
    False
    
    # 非数字或字符串是OK
    >>> [] is None
    False
    >>>  is None
    False
    

  • 来看另外一个情况

    >>> a = 1
    >>> b = \'\'
    >>> a is None
    False
    >>> b is not None
    True
    
  • 赋值后都是没毛病的

  • 谁又会单单用一个字面量去跟None比较呢?所以一般大家的代码都不会受此影响


  • 另外一点,Did you mean "=="? 或者!=

    >>> \'\' == None
    False
    >>> 1 != None
    True
    
  • 但其实我们并不推荐跟None去比较的时候用==或者!=

    参考码农高天的 《为什么判断一个值是否为None的时候,一定要用is呢?》
    https://www.bilibili.com/video/BV1xL411N7iS
    

花边

The compiler now produces a SyntaxWarning when identity checks (is and is not) are used with certain types of literals (e.g. strings, numbers). These can often work by accident in CPython, but are not guaranteed by the language spec. The warning advises users to use equality tests (== and !=) instead. (Contributed by Serhiy Storchaka in bpo-34850.)

BPO

  • BPO的意思是... bug.python.org,也就是python提交bug的地方

  • bpo-34850原文

    https://github.com/python/cpython/issues/79031
    
    Gregory have noticed that the "is" and "is not" operator sometimes is used with string and numerical literals. This code "works" on CPython by accident, because of caching on different levels (small integers and strings caches, interned strings, deduplicating constants at compile time). But it shouldn\'t work on other implementations, and can not work even on early or future CPython versions.
    
    https://discuss.python.org/t/demoting-the-is-operator-to-avoid-an-identity-crisis/86
    
    I think that the adequate solution of this issue is not demoting the "is" operator, but emitting a syntax warning. In general, this is a work for third-party checkers. But many people don\'t use checkers for their one-time scripts, using "is" with a literal is always a mistake, and it is easy to add a check for this in the compiler.
    
    Currently the compiler emits SyntaxWarning only for parenthesis in assert: assert(x, "msg"). But in earlier versions there were more warnings (they are errors). In 3.8 yet one SyntaxWarning will be added instead of DeprecationWarning for unknown escape sequences in string literals.
    
    The proposed PR makes the compiler emitting a SyntaxWarning when the "is" or "is not" operators are used with a constant (except singletons None, False, True and ...). A warning will be replaced with a SyntaxError if the warnings system is configured to raise errors. This is because SyntaxError contains more information and provides better traceback. The same change was made for "assert(...)". Added tests, including tests for "assert(...)".
    
    Barry have noted that using the "==" operator with None can be also classified as an error. But I think that in this case there may be legal uses of this, and the compiler should not complain. It is a work for third-party checkers, which can provide configuration options for enabling and disabling particular kinds of checks.
    

literals,字面量

https://docs.python.org/zh-cn/3.9/reference/lexical_analysis.html#literals

  • 字面值是内置类型常量值的表示法。

  • 特别琐碎的概念

  • 但不光是数字(你以为的整数),还有很多字面值

    >>> 3.14 is not None  # 浮点数
    <stdin>:1: SyntaxWarning: "is not" with a literal. Did you mean "!="?
    True
    
    >>> 3.14j is not None # 虚数
    <stdin>:1: SyntaxWarning: "is not" with a literal. Did you mean "!="?
    True
    
    
    

以上是关于一个诡异的Python小问题的主要内容,如果未能解决你的问题,请参考以下文章

微信小程序诡异错误this.setData报错

记录一个ssl证书引发的诡异问题

找出诡异的Bug:数据怎么存不进去

win10+python3.5,使用requests抓取信息遇到chunked乱码的诡异问题。python2.7则不乱码

史上最诡异的数学题

在执行save操作时候出现的诡异!