python - 当一个python函数被修饰时,那个修饰在哪些范围内可见?
问题描述
例如...给定
- 环境 (A) [加载模块 (B) 的环境] 提供了一个功能,例如“注册”
- 模块 (C) [由 (B) 导入] 提供了一组实用程序来加载/运行其他脚本/模块/等
- 模块(D)是那些“其他脚本”之一 - 它在其主线(最外层)范围内调用“register()”,以便与 D 的主要入口点(执行/启动 D 服务的函数/工作)以及其他项目(包括,例如参数和适当的默认值) - 和
- 模块 (B) 提供了一个函数 (runScript(filename...)),当它被调用时 -
- a) 验证请求,
- b) 装饰“注册”,使得当 (D) 作为导入/加载的一部分被加载和执行时,“注册”的调用由装饰器处理,该装饰器捕获随后要调用的入口点,
- c) 调用 C 中的实用程序,该程序处理可用导入机制的细微差别,然后
- i)加载脚本(通过导入它)[它应该执行脚本,它应该执行函数调用来注册,它应该调用装饰器,它应该捕获并保存“注册”入口点],然后
- ii) 检索并调用保存的“注册”入口点
(A) 和 (D) 都不能修改 - 我们只能修改 B 和/或 C 中的代码。
似乎当 B.runScript(filename) 被调用时,除了包装器之外,一切都按预期工作。脚本确实被加载了[即,如果它有一个 Do 方法,它将被调用。*1] 但是如果没有 Do 方法,注册没有捕获入口点。
对于我的误解和/或误解/实施,我提前道歉
模块 B (runScript - runScript.py):
import os
import App
def getEntryPoint(pi_registration):
def registration(*args, **kwargs):
App.plugin_EntryPoint = args[10]
return True
return registration
def runScript(filename):
global register
try:
os.stat(filename)
register = getEntryPoint(register) # apply decorator
App.Do("RunScript", { 'FileName' : filename })
except:
print "script inaccessible ("+filename+")"
模块 C(应用程序(控制/仿真...)App.py):
import sys
import os
import path
import gimp
# etc...
plugin_EntryPoint = None
def Do(procedureName, options)
# ...
if procedureName == 'RunScript':
filename = options['FileName'}
# determine import mechanisms available --
isimport = False
isimportSFL = False
isimportUtil = False
isimportable = False
try:
import imp
isimport = True
except:
pass
if not isimport:
# try alternative version's loader mechanism versions...
try:
from importlib.machinery import SourceFileLoader
isimportSFL = True
except:
pass
if not isimportSFL:
try:
import importlib.util
isimportUtil = True
except:
pass
plugin_EntryPoint = None
if isimport:
moduleD = imp.load_source("module_D", filename)
elif isimportSFL:
moduleD = SourceFileLoader("module_D", filename)
elif isimportUtil:
modspec = importlib.util.spec_from_file_location("module_D", filename)
moduleD = importlib.util.module_from_spec(spec)
spec.loader.exec_module(moduleD)
if hasattr(moduleD, 'Do')
moduleD.Do() # try conventional entry point...
elif plugin_EntryPoint is None: # try 'registered' entry point...
raise AppTerminate, "no entry point registered"
else
pluginEntryPoint(App.plugin_Args)
# ...
模块 D(服务插件“moduleD.py”):
def myEntrypoint():
print "entered"
register("myName", "", "", "", "", "", "", "", [], [], myEntrypoint)
if __name__ == '__main__":
main()
环境(A):坦率地说,因为我不能确切地看到环境(gimpfu)是如何设置它的,所以我只能推测手头问题的可能等价物:
#!/usr/bin/python
def register(name, a, b, c, d, e, f, g, h, i, entrypoint):
print "Plugin "+name+ " Entrypoint "+str(entrypoint)
import RunScript
RunScript._runScript("moduleD")
import _RunScript
解决方案
这最终会转移到 Python 的静态与动态范围问题——因此,函数的范围是静态的,并且仅在模块中可见,而不是它本身可能导入的任何模块。
评语:唉,废话。我猜在做了很多系统编程工作之后,我们将一层“滑入”功能堆栈中,(拦截较低层的服务请求而不影响堆栈中它上面的层(发出服务请求),我希望有将是一种方式,某种方式,来完成同样的事情。[c'est la guerre]
推荐阅读
- rust - rust-lld 丢失,如何安装?
- jasper-reports - 如何通过排除特定格式的某些波段来排除空格?
- c# - ASP.NET Web API 不接收从 Angular 发布的数据
- jquery - 如何使用 3.1.1. 使用 Jquery 更改输入文本?
- javascript - 限制用户关闭浏览器的选项卡或窗口
- java - 如何在 Spring REST Docs 中记录树
- ruby-on-rails - 如何在 ruby on rails 中使用 Ajax 正确运行分页
- spring - 外部化 application.properties
- cmake - 如何为cmake设置包含顺序
- json - 由于数据类型,解析 Json 返回错误