一个诡异的Python小问题

问题

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

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

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

搜索

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

    从 python 3.8 开始,使用 isis 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.)
    
    
  • 中文描述

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

测试

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

  • 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
    
    
    
  • 17
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wuxianfeng023

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值