在python中,为什么0xbin()返回False?

Mat*_*ttS 191 python

输入命令0xbin()返回False:

>>> 0xbin()
False
Run Code Online (Sandbox Code Playgroud)

为什么会这样?这种语法应该没有任何意义.函数不能以0开头,十六进制中没有"i"和"n",bin函数必须有一些参数.

YSe*_*elf 230

Python似乎解释0xbin()0xb in (),在一个空元组中意味着十一.答案是否定的False.

  • 显然是的.[Python参考](https://docs.python.org/3.6/reference/lexical_analysis.html#whitespace-between-tokens)表示只有"如果它们的串联可以被解释为不同的标记",则只需要令牌之间的空格.但我在[Code Golf](https://codegolf.stackexchange.com/)中只见过这样的代码. (46认同)
  • 所以显然"在","是"等不需要空格?我第一次遇到这个,但它是有道理的,因为"<"和"=="也不需要它们. (19认同)
  • @Aaron:`[_ [:alpha:]] [_ [:alnum:]]*`在正则表达式语言中允许(Unicode)字符类,即不是Python的.; - ] (8认同)
  • 哇,我以为这种解析只在Fortran和BASIC中完成.我简直不敢相信现代语言. (8认同)
  • @MattS这就是为什么有效的python标识符(和许多其他语言)只接受标识符的第一个字母的alpha或下划线,然后允许数字.由于完全支持Unicode,实际的实现相当复杂,但标识符的纯ASCII正则表达式为:`r'[_ a-zA-Z] [_ a-zA-Z0-9]*'` (7认同)
  • @Barmar python很老了. (4认同)
  • @RonJohn我已经编程了40年,Python还不到30年.就我而言,它是一个年轻的鞭子 - 鲷鱼. (2认同)
  • @Barmar:Python [想保留](https://www.python.org/dev/peps/pep-3099)和[LL(1)语言](https://en.wikipedia.org/wiki/LL_grammar )。这实际上与该示例并没有任何关系,但是它说明了他们对“哑”解析器的持续需求(并且还提供了一些解释方式。TL; DR:他们不希望Python这么做)。最终像Perl。)。 (2认同)

Chr*_*nds 139

如果您反汇编代码,您将看到Yself的答案,其中提到0xbin()被解释为0xb in (),已得到确认:

>>> import dis
>>> dis.dis('0xbin()')
  1           0 LOAD_CONST               0 (11)
              2 BUILD_TUPLE              0
              4 COMPARE_OP               6 (in)
              6 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)

  • `list(tokenize.tokenize(io.BytesIO(b"0xbin()").readline))`可能更合适 (16认同)

Dra*_*nis 61

你可以使用Python自己的tokenizer来检查!

import tokenize
import io
line = b'0xbin()'
print(' '.join(token.string for token in tokenize.tokenize(io.BytesIO(line).readline) if token.type!=59))
Run Code Online (Sandbox Code Playgroud)

这将打印字符串中的标记,以空格分隔.在这种情况下,结果将是:

0xb in ( ) 
Run Code Online (Sandbox Code Playgroud)

换句话说,它返回False,因为数字11(0xb)不在空元组(())中.

(感谢Roman Odaisky建议tokenize在评论中使用!)

编辑:更彻底地解释代码:tokenize函数需要输入一些奇怪的格式,因此io.BytesIO(line).readline是一个将字节序列转换为tokenize可读取的字符的函数.tokenize然后将其标记并返回一系列namedtuples; 我们取代表每一个的字符串并将它们与空格连接在一起.该type != 59部分用于忽略否则将在开头显示的编码说明符.

  • 这是最好的答案,"dis"和"ast"的答案掩盖了不常见的符号背后的情况,这在普通的python中清楚地表明了这一点. (7认同)

Pål*_* GD 53

您可以使用AST模块获取表达式的抽象语法树:

>>> import ast
>>> m = ast.parse('0xbin()')
>>> ast.dump(m)
'Module(
    body=[Expr(
               value=Compare(left=Num(n=11),
                             ops=[In()],
                             comparators=[Tuple(elts=[],
                                                ctx=Load())
                                         ]
                            ))])'
Run Code Online (Sandbox Code Playgroud)

请参阅抽象语法以了解如何解释表达式,但tl; dr:Num(n=11)0xb部分,并Tuple(elts=[], ...)提示空元组而不是函数调用.