我可以在Python中的任何位置定义范围吗?

Hub*_*bro 11 python scope

有时候,我发现我不得不使用功能名称很长,如os.path.abspathos.path.dirname一个很多在短短的几行代码.我不认为使用这些函数乱丢全局命名空间是值得的,但是能够在我需要这些函数的行周围定义范围将是非常有帮助的.举个例子,这将是完美的:

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
Run Code Online (Sandbox Code Playgroud)

我想知道这是否可行

Ray*_*ger 19

Python没有一个临时命名空间的工具,像我们在Lisp或计划.

Python中常用的技术是将名称放在当前名称空间中,然后在完成它们时将其取出.这种技术在标准库中大量使用:

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
Run Code Online (Sandbox Code Playgroud)

减少键入工作量的另一种方法是缩短重复前缀:

>>> import math as m
>>> m.sin(x / 2.0) + m.sin(x * m.pi)

>>> p = os.path
...
>>> a = p.abspath(somepath)
>>> d = p.dirname(somepath)
Run Code Online (Sandbox Code Playgroud)

标准库中常用的另一种技术是不要担心污染模块名称空间,只需依靠__all__列出您打算公开的名称.__all__的效果在import语句文档中讨论.

当然,您也可以通过将名称存储在字典中来创建自己的命名空间(尽管此解决方案并不常见):

d = dict(abspath = os.path.abspath,
         dirname = os.path.dirname)
...
a = d['abspath'](somepath)
d = d['dirname'](somepath)
Run Code Online (Sandbox Code Playgroud)

最后,您可以将所有代码放在一个函数中(它有自己的本地命名空间),但这有许多缺点:

  • 设置很尴尬(非典型和神秘的功能使用)
  • 需要声明的全球要做到这一点,不是暂时的任何任务.
  • 在调用函数之前,代码不会运行
 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
Run Code Online (Sandbox Code Playgroud)


Joh*_*ooy 5

这种做你想要的,但你必须重复这些名称

try:
    abspath = os.path.abspath
    dirname = os.path.dirname
    # fifteen lines of code
finally:
    del abspath
    del dirname
Run Code Online (Sandbox Code Playgroud)

如果在下面的情况下存在异常,这可以避免污染命名空间

try:
    ...
    try:
        abspath = os.path.abspath
        dirname = os.path.dirname
        # fifteen lines of code
    finally:
        del abspath
        del dirname

    ... # don't want abspath or dirname in scope here even if there was
    ... # an exception in the above block

except:
    ...
Run Code Online (Sandbox Code Playgroud)