MySQL 内置函数名称的解析默认规则是什么?
在Python中,内置函数是指由解释器直接提供的、可以在代码中直接使用的函数,例如print()、len()等。当我们使用这些内置函数时,解释器会根据一定的规则来解析函数名称,并在当前作用域中进行查找和调用。
那么,内置函数名称的解析默认规则是什么呢?本文将从全局和局部两个角度来解析这一问题。
阅读更多:MySQL 教程
全局名称解析规则
全局名称解析规则指的是在全局作用域中解析函数名称的规则。在Python中,全局作用域是指程序的最外层作用域,即没有包裹在任何函数或类中的代码块。对于以下例子:
def foo():
print('calling foo')
foo() # 在全局作用域调用函数
在全局作用域中调用函数foo()时,解释器首先会在当前作用域中查找函数名foo,如果没有找到则会继续在全局作用域中查找。因此,即使在函数之后调用函数,也不会报错,因为函数名已经在全局作用域中被解析并绑定到了对应的函数对象。
对于内置函数名称的解析,默认会按照以下顺序进行:
- 当前作用域中(即最内层作用域)
- 内置作用域(即内置函数和模块中的名称,不需要
import就可以直接使用) - 全局作用域
- 当前模块中的其他作用域
sys.modules中的其他模块
最后一步是解释器在所有模块中查找函数名称。对于以下例子:
def len():
pass
len('hello') # 调用全局作用域中的len函数
由于在全局作用域中定义了函数len(),因此调用内置函数len()时会优先使用全局作用域中定义的函数,而不是内置函数。
局部名称解析规则
局部名称解析规则指的是在函数内部解析函数名称的规则。与全局作用域不同,函数内部会存在嵌套的作用域,可以理解为在函数内部定义的变量和函数只能在该函数内部被访问到。
对于以下例子:
def foo():
def bar():
print('calling bar')
bar()
foo() # 在全局作用域中调用foo函数
在函数foo()内部定义了函数bar(),在函数foo()中调用函数bar()时,解释器会按照以下顺序进行解析:
bar在当前作用域中(即foo()中)是否已定义bar在全局作用域中是否已定义
如果都没有找到,则会抛出NameError异常。
对于以下例子:
def foo():
print('calling foo')
def bar():
print('calling bar')
foo = bar # 覆盖全局名称
foo() # 在全局作用域中调用foo函数
在全局作用域中定义了函数foo()和函数bar(),然后将函数bar()赋值给了函数foo(),此时函数foo()已经不再是全局作用域中定义的函数了。在调用函数foo()时,解释器会根据作用域链查找函数名称,找到被覆盖的foo引用,然后调用其绑定的bar()函数。
实例说明
下面通过一个实例来说明全局和局部名称解析规则。
def print(msg):
print('Message:', msg)
def foo():
print('calling foo')
foo() # 在全局作用域中调用foo函数
在全局作用域中定义了函数print()和函数foo(),然后在函数foo()中调用print()函数。由于在函数foo()的作用域中找不到名称为print的函数,因此解释器会根据全局名称解析规则查找该函数。由于全局作用域中已经定义了print()函数,因此会使用全局作用域中的函数,而不是内置函数。此时,执行print()函数时会陷入无限递归,导致程序崩溃。
总结
内置函数名称的解析默认规则是按照全局、局部作用域及其他模块的顺序进行查找。在全局作用域中,如果同时定义了与内置函数同名的函数,则会优先使用全局作用域中的函数。而在函数内部,则会先查找局部作用域中的同名函数,再查找全局作用域中的同名函数。如果以上两个作用域都没有找到,则会抛出NameError异常。
在实际编程中,避免定义与内置函数同名的函数,以免出现上述问题。如果需要使用内置函数,可以通过import builtins导入builtins模块,然后调用builtins.前缀来使用内置函数。例如:
import builtins
def print(msg):
builtins.print('Message:', msg)
def foo():
print('calling foo')
foo() # 在全局作用域中调用foo函数
以上代码可以保证即使在函数内部定义了与内置函数同名的函数,也不会影响到内置函数的使用。
极客笔记