近来在网上冲浪时看到了一个奇怪的 Python 语句:
1 | 0xfor x in (15, 10, 5)] [ |
有那么一瞬间,对自己多年的 Python 语法产生了怀疑, 0xfor
是一个什么新的循环关键字?
经过一番探究,发现一个奇怪的 Python 语法世界。
上面这一句,实际上是 [0xf or x in (15, 10, 5)]
首先, 0xf
代表了 十六进制整型 15
,同理还可以用二进制、八进制
1 | 0b010or x in (15, 10, 5)] [ |
还有一个特殊数字表示—— j
,代表 complex(复数)类型, j
在这里表示虚数 i
(不用 i
的原因),也可以有很奇怪的写法:
1 | 0jor.0j |
其次,在 Python 中操作符(Operator)左右的空格并不全是必须的
“ Whitespace is needed between two tokens only if their concatenation could otherwise be interpreted as a different token”
所以理论上你可以写出类似这样的代码
1 | 0xfin[15] |
最后,由于 or
操作符遵循最短求值原则,只要左侧表达式为真,右侧表达式是不会执行的,所以任何奇怪的表达都可以正常运行:
1 | 0xdeadbeefor whysoserious |
所以综上,我们来一个终极“乱码”:
1 | 0b010&0o0&0b0is(0j)in[0xdeadbeefor["是不是很奇怪这样也能运行"]] |
现在再看一眼开头, [0xfor x in (15, 10, 5)]
是不是一眼就能能把 [15]
给看出来了呢?🥴
参考:
- https://stackoverflow.com/questions/67083039/why-does-python-return-15-for-0xfor-x-in-1-2-3
- https://twitter.com/nedbat/status/1382027078816653319
- https://stackoverflow.com/questions/24812444/why-are-complex-numbers-in-python-denoted-with-j-instead-of-i
- https://stackoverflow.com/questions/8370637/complex-numbers-in-python
- https://docs.python.org/3/reference/expressions.html#operator-precedence
- https://docs.python.org/3/reference/lexical_analysis.html#whitespace-between-tokens