import os, sys
closure:
abspath = os.path.abspath
dirname = os.path.dirname
# 15 lines of heavy usage of those functions
# Can't access abspath or dirname here
abspath = os.path.abspath
dirname = os.path.dirname
# 15 lines of heavy usage of those functions
a = abspath(somepath)
d = dirname(somepath)
...
del abspath, dirname
d = dict(abspath = os.path.abspath,
dirname = os.path.dirname)
...
a = d['abspath'](somepath)
d = d['dirname'](somepath)
最后,您可以将所有代码放在一个函数中(它有自己的本地命名空间),但这有许多缺点:
设置很尴尬(函数的非典型和神秘用法)
您需要将要执行的任何非临时任务声明为global。在
除非调用函数,否则代码不会运行
def temp(): # disadvantage 1: awkward setup
global a, d # disadvantage 2: global declarations
abspath = os.path.abspath
dirname = os.path.dirname
# 15 lines of heavy usage of those functions
a = abspath(somepath)
d = dirname(somepath)
temp() # disadvantage 3: invoking the code
简短的回答是“不”。在
Python有三个作用域。它有功能范围、全局(又名模块)范围和内置范围。不能声明其他作用域。在
一个
class
声明看起来有点像一个作用域,但它不是。它基本上是在一个对象上分配一组字段的简写。该类中的函数在不经过定义它们的对象的情况下无法访问这些字段。在这听起来有点限制。在Python中,还可以嵌套函数定义。嵌套函数定义获得对外部作用域的只读访问权。这是动态的。在定义函数之前不必提及名称。下面是一个例子:
因此,通过定义一个嵌套函数来创建所需的值、使用它们并返回结果,就可以在不牺牲太多局部性的情况下获得这种效果。在
我记得,在学习Python时,习惯于相当奇怪的作用域规则是比较困难的部分之一。在我看来,当嵌套函数被引入时,由于外部作用域的只读语义和闭包的动态作用域,它们使得作用域规则变得更加陌生。在
显然,在Python3中有一种使用
^{pr2}$nonlocal
关键字(类似于global
关键字)从封闭范围“导入”一个变量,这样您就可以在读/写上下文中使用它:否则,每当Python在
=
符号的左侧看到一个变量,它就假定您正在创建一个新的局部变量。global
和nonlocal
关键字表示您打算修改不在函数范围内的变量。在Python没有像Lisp或Scheme中的let这样的临时命名空间工具。在
Python中常用的技术是将名称放入当前名称空间,然后在处理完这些名称后将其取出。此技术在标准库中大量使用:
减少键入工作量的另一种方法是缩短重复出现的前缀:
^{pr2}$标准库中常用的另一种技术是不必担心会污染模块名称空间,而只需依赖\uu all_u列出您打算公开的名称。在docs for the import statement中讨论了的作用。在
当然,您也可以通过将名称存储在字典中来创建自己的命名空间(尽管此解决方案并不常见):
最后,您可以将所有代码放在一个函数中(它有自己的本地命名空间),但这有许多缺点:
这是你想要的,但是你必须重复名字
这避免了在以下情况下出现异常时污染命名空间
^{pr2}$相关问题 更多 >
编程相关推荐