没有什么可发现的:就 Python 语言而言,这不是一个“错误”。你有一个完全有效的 Python 程序。 Python 是一种动态语言,您使用的标识符会在运行时解析。
用 C#、Java 或 C++ 编写的等效程序将是无效的,因此编译会失败,因为在所有这些语言中,都需要使用未定义的标识符来为用户生成诊断(即编译时错误)。在 Python 中,根本不知道该标识符在编译时是否已知。所以代码是有效的。可以这样想:在 Python 中,拥有一个建筑工地的地址(一个名字)并不要求建筑已经开始。重要的是,当您使用地址(名称)时,就好像那里有建筑物一样,最好有建筑物,否则会引发异常:)
在 Python 中,会发生以下情况:
a = "WelcomeToTheMachine" 查找属性a 的封闭上下文(这里:模块上下文),并将属性'a' 设置为存储在常量池中的给定字符串对象。它还会缓存属性引用,以便后续访问a 会更快。
if a == "DarkSideOfTheMoon": 在缓存中找到a,并对对象a 执行二进制比较运算符。这最终以builtins.str.__eq__ 结束。该运算符的返回值用于控制程序流程。
awersdfvsdvdcvd 是一个表达式,其值是查找名称 'awersdfvsdvdcvd' 的结果。这个表达式被评估。在您的情况下,在封闭的上下文中找不到该名称,并且查找引发了 NameError 异常。
此异常传播到匹配的异常处理程序。由于处理程序位于当前模块中的所有嵌套代码块之外,print 函数永远不会有机会被调用。 Python 的内置异常处理程序向用户发出错误信号。解释器(用词不当!)实例无事可做。由于 Python 进程在解释器实例完成后不会尝试做任何其他事情,因此它会终止。
绝对没有说程序会导致运行时错误。例如,awersdfvsdvdcvd 可以在模块执行之前设置在封闭范围内,这样就不会引发运行时错误。 Python 允许对模块的生命周期进行精细控制,并且您的代码可以在模块编译后但在执行之前注入 awersdfvsdvdcvd 的值。只需几行相当简单的代码即可。
事实上,这是 Python 程序中使用的众多动态编程技术之一。它们的明智使用使 C++ 在几十年或永远不会原生获得的功能成为可能,而这在 C# 和 Java 中都非常麻烦。当然,Python 有性能成本——没有什么是免费的。
如果您希望在编译时突出显示此类问题,您可以轻松地将一些工具集成到 IDE 中来发现此问题。例如。 PyCharm 有一个内置的静态检查器,这个错误会像预期的那样用红色波浪线突出显示。