【问题标题】:Why does assigning to True/False not work as I expect?为什么分配给 True/False 不能按我的预期工作?
【发布时间】:2011-01-04 12:44:16
【问题描述】:

作为回答另一个问题的一部分,我编写了以下代码,乍一看其行为似乎很奇怪:

print True                    # outputs true
True = False;    print True   # outputs false
True = True;     print True   # outputs false
True = not True; print True   # outputs true

谁能解释这种奇怪的行为?我认为这与 Python 的对象模型有关,但我不确定。

是Cygwin下的2.5.2版本。

【问题讨论】:

  • 这不是很好的老笑话#define true false吗?
  • 在第 3 版中,分配 True = False 会引发一个 sintax 错误,所以我想您的问题是指第 2 版
  • 这有什么奇怪的?需要详细说明吗?
  • @Paul,你对 BCPL 了解多少?还是RCA1802组装?还是面向对象的 COBOL?还是 F#、Haskell 或 Forth? SO 的高代表并不能说明某人在特定领域的知识渊博。我的 Python 知识远不及其他领域那么全面,而且无关紧要,因为 SO 是针对所有技能水平的。最重要的是,我不完全确定“=”和“==”之间的区别在哪里。或许你可以解释一下?
  • @SLott,问题或多或少是这样的:为什么甚至可以分配给常量?但是@Balpha 和@Ignacio 为我澄清了这一点,因为 True 和 False 不是关键字(至少在 Python 2 中),而只是指向底层对象的名称(并且指针可以更改)。

标签: python python-2.x


【解决方案1】:

在 2.x 中,True 和 False 不是关键字,因此可以以这种方式隐藏内置函数。

【讨论】:

    【解决方案2】:

    想象一下:

    A = True
    B = False
    
    print A           # true
    A = B;  print A   # false
    A = A;  print A   # false, because A is still false from before
    A = not A; print A # true, because A was false, so not A is true
    

    完全相同的事情正在发生,但在你的版本中它令人困惑,因为你不期望你可以重新定义 True 和 False。

    【讨论】:

      【解决方案3】:

      您可以检查 True/False 是否为关键字:

      >>> import keyword
      >>> keyword.iskeyword('True')
      False
      

      由于不是(在我的版本中),分配 True=False 仅意味着“True”是另一个“变量”名称。

      【讨论】:

      • 请注意,您可能应该使用keyword.iskeyword('True') 作为示例,因为如果在那里使用大多数实际关键字会给出一个 SyntaxError。
      • 注意:这是在python 3中修复的,True是keyword
      • 确实很有趣,虽然有点离题:)
      【解决方案4】:

      Python 有这两个(以及其他)内置对象。它们只是对象;一开始,它们还没有名字,但要知道我们指的是什么,我们称它们为0x600D0xBAD

      在开始执行 Python (2.x) 脚本之前,名称 True 绑定到对象 0x600D,名称 False 绑定到对象 0xBAD,所以当程序引用到True,它看着0x600D

      因为0x600D0xBAD 知道它们通常被名称TrueFalse 使用,所以这就是它们打印时的输出,即0x600D__str__ 方法返回@987654335 @等等。

      True = False
      

      现在将名称 True 绑定到不同的对象。从现在开始,TrueFalse 两个名称都引用同一个对象 0xBAD,在打印时输出 False

      True = True
      

      实际上并没有做任何事情:它采用名称True 引用的对象,并将新(和旧)名称True 绑定到该对象。由于(由于上一步)True 在此之前引用了0xBAD,因此在此之后仍然引用了0xBAD。因此,打印仍然输出False

      True = not True
      

      首先获取名称True绑定到的对象,即0xBAD。它将此对象提供给not 运算符。 not 不关心(或知道)这里使用什么名称来指代0xBAD,它只知道当给定0xBAD 时它应该返回0x600D。然后将此返回值提供给赋值运算符=,将名称True 绑定到此对象。

      由于名称True 现在再次引用对象0x600D,调用print True 输出True,世界再次美好。

      【讨论】:

        【解决方案5】:

        您可以使用简单的布尔比较轻松恢复原始值:

        True = 1==1
        False = 1==0
        

        或者通过将整数文字转换为布尔值:

        True = bool(1)  # actually every number except 0 works
        False = bool(0)
        

        【讨论】:

          猜你喜欢
          • 2015-07-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-07
          • 2020-01-10
          • 1970-01-01
          • 2021-05-30
          相关资源
          最近更新 更多