真正的区别在于变量查找在两种语言中的工作原理.
在C中,代码一次编译.当编译器读取foo的代码时,它会看到x,并且还不知道该标识符的内容.它可以是任何类型的变量,也可以是函数,也可以是印刷错误.如果它还没有看到x的定义 – 解释x是什么类型的东西,虽然不一定是它的实际值 – 然后它会立即报告错误.
当Python看到x时,它知道这是一个名称 – 即标识符 – 因为它匹配适当的令牌类型,而不是语言关键字.在Python中,一切都是对象,我们的意思是 – 包括函数.在编译时没有类型检查,因此我们不关心x是整数,还是函数,或者只是什么 – 所有这些都可以以相同的方式处理. (是的,你可以打印函数 – 但它没有显示任何有用的东西,比如原始代码;它只是为你提供了一个存根,其中包含有关类型,名称和对象ID的一些基本信息).实际上不能进行任何类型检查,因为Python的变量没有类型(甚至不是隐式类型,就像Haskell这样的类型推断语言) – Python的值有一个类型.
还没有一个有效性检查来查看x是否确实存在,因为再也没有一个 – 在Python中有一些方法可以动态创建名称(一般来说请不要).
但是,可以在编译时进行足够的分析以确定x不是局部变量,因此Python生成的代码“查找名为x的全局变量并使用它”.当foo实际运行时,以异常的形式发生任何结果错误.如果x实际上不作为全局存在,则会引发NameError;如果它存在但相应的对象是错误的类型(通常不可能打印,但可能是例如),它会引发TypeError,如果它是正确的类型但是无效的值,它通常会引发ValueError或其子类型(例如,列表中的无效数字索引将引发IndexError,这是ValueError的子类型.