一个诡异的Python小问题

一个,诡异,python,问题 · 浏览次数 : 47

小编点评

这段代码使用 `is` 和 `is not` 运算符进行字符串比较,但由于 `is` 和 `is not` 运算符在字符串 literal 中使用时存在语法警告,导致代码无法运行。 **问题:** 如何在使用 `is` 和 `is not` 运算符比较字符串 literal 的情况下避免语法警告呢? **解决方案:** * 使用 `==` 和 `!=` 运算符进行字符串比较。 * 使用 `try` 和 `except` 语句捕获语法警告并将其转换为 `SyntaxError`。 * 在 `assert` 语句中使用 `==` 和 `!=` 运算符进行字符串比较。 * 在 `try` 和 `except` 语句中使用 `is` 和 `is not` 运算符进行字符串比较。

正文

一个诡异的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 !=)。 
    
    
    
    

测试

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

  • 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小问题相似的内容:

一个诡异的Python小问题

一个诡异的Python小问题 问题 来自一个基础偏弱的学员,但不知道如何去解释 >>> '' is not None :1: SyntaxWarning: "is not" with a literal. Did you mean "!="? True # 注意结果是会出现的,其实不影

一个诡异的 Pulsar InterruptedException 异常

背景 今天收到业务团队反馈线上有个应用往 Pulsar 中发送消息失败了,经过日志查看得知是发送消息时候抛出了 java.lang.InterruptedException 异常。 和业务沟通后得知是在一个 gRPC 接口中触发的消息发送,大约持续了半个小时的异常后便恢复正常了,这是整个问题的背景。

一个难忘的json反序列化问题

前言 最近我在做知识星球中的商品秒杀系统,昨天遇到了一个诡异的json反序列化问题,感觉挺有意思的,现在拿出来跟大家一起分享一下,希望对你会有所帮助。 案发现场 我最近在做知识星球中的商品秒杀系统,写了一个filter,获取用户请求的header中获取JWT的token信息。 然后根据token信息

记一次难忘的json反序列化问题排查经历

前言 最近我在做知识星球中的商品秒杀系统,昨天遇到了一个诡异的json反序列化问题,感觉挺有意思的,现在拿出来跟大家一起分享一下,希望对你会有所帮助。 案发现场 我最近在做知识星球中的商品秒杀系统,写了一个filter,获取用户请求的header中获取JWT的token信息。 然后根据token信息

Harbor镜像仓库的导出与整理之二

Harbor镜像仓库的导出与整理之二 背景 前几天参照大神的blog进行了一下harbor的镜像列表的获取与下载. 当时发现一个很诡异的问题. 实际上镜像仓库里面的镜像很多. 但是导出和列表里面的却很少. 经过查询发现harbor的v2.0的API里面存在一些限制. 每次api的返回结果最多是 10

[转帖]NUMA导致的Oracle性能问题

https://www.cnblogs.com/realcp1018/p/6903721.html 背景简介: Oracle版本:11.2.0.4 OS 版本:OEL5.8 在一次Oracle的Dataguard正常switchover过程中,遇到了一个极其诡异的问题,一条主业务的SQL语句在新主库

记录荒废了三年的四年.net开发的第一次面试

对象 身在成都小微企业,前两天面试深圳老牌金蝶公司。对我这个荒废了三年光影的人来说,怎一个跨度之大了得?作为人我生第一次面试的,整个面试过程,只能用诡异来形容这次感受。而结尾也是迷迷糊糊中草草收场。 不是很好的开局 我我毕业就进了国企。毕业前,在我想象中,他是一个伟光正的形象。所以我抱着人生值得,未

[转帖]JVM内存非典型术语介绍(shallow/retained/rss/reserved/committed)

https://www.jianshu.com/p/871d6bb3a32d 背景 ​ 在服务器性能优化内存这一项时,有一些现象很诡异。如top显示的RES很大,但是实际jvm堆内存占用很小,同时使用nmt发现committed更大。所以决定写这篇wiki大概介绍一下 JVM中如何计算一个对象的实际

Maven依赖冲突解决总结

转载请注明出处: 1.Jar包冲突的通常表现 Jar包冲突往往是很诡异的事情,也很难排查,但也会有一些共性的表现。 抛出java.lang.ClassNotFoundException:典型异常,主要是依赖中没有该类。导致原因有两方面:第一,的确没有引入该类;第二,由于Jar包冲突,Maven仲裁机

服务器神秘挂起:一场惊心动魄的内核探案

2024年6月17日,我们的运维团队突然收到了一连串的告警。监控大屏上,代表着不同 Sealos 可用区的绿点中,零星地闪烁起了一两个红点。 “奇怪,怎么有几台服务器突然 hang 住了?” 值班的小辉皱起了眉头。 这次故障的诡异之处在于它的随机性。并非所有节点都受到影响,而是在不同可用区中,时不时