在Lua中,有一个名为setfenv()
的内置函数,它允许您提供变量表作为函数的环境。这是一个使用它的例子:
foo = 1
function f()
print(blech) --Note that no variable named blech has been defined.
end
variableTable = {blech = foo}
setfenv(f, variableTable)
f() -- This will work and print 1, because blech has been defined as foo's value in the variableTable
我这样做的动机是它允许我建立一个平台,以便用户可以在Lua中编写易于理解的脚本(他们可以编写无效函数,并且可以简单地相信变量将存在于他们身上)。它还提供了一种优雅的方法来排除我不希望它们出于安全原因使用的模块和函数(例如,如果你定义一个没有定义os模块的变量表,那么一个知识渊博的用户就无法使用它恶意地)。
我希望能够在Python中实现同样的功能。是否有类似的东西可以在Python中完成?
答案 0 :(得分:6)
有exec
:
def foo():
print bar
exec foo.func_code in {"bar": "baz"}
这不是特别好的风格(我甚至会说它特别糟糕)。它使foo
的实现难以理解,因为它依赖于了解它的特殊方式。相反,将参数传递给函数。
此不提供任何安全措施。作为第一个近似值,Python不包含任何受限执行功能。没有什么能阻止用户提供foo的这个定义:
def foo():
import os
os.system("rm -rf /")
仅仅因为你没有在映射中提供os
并不意味着他们不能自己去获取它。如果你真的需要限制执行,那么你可能想要坚持使用Lua,或至少调查PyPy sandboxed mode。
答案 1 :(得分:2)
你为什么要这样做?您的代码是否太可读了?
只需将带有'env'的字典或结构传递给函数。
编辑:阅读你的动机。第一部分我无法理解(在python中编写lua脚本?这是什么意思?),第二部分是完全错误的。这无法限制环境。例如,你仍然可以import os
限制执行有点复杂。我知道的一些东西:
答案 2 :(得分:1)
我不确定你为什么要这样做,但这是一种愚蠢的方式:
def foo():
print bar
foo.func_globals['bar'] = 1
foo()
警告:我不建议这样做。
答案 3 :(得分:0)
我不知道有任何理智的方式来做到这一点。只需使用函数参数。
def f(blech):
print(blech)
如果您希望它包含许多变量,请将它们粘贴在dict
中并传递它。
def f(vars):
print(vars['blech'])
print(vars['fizz'])
答案 4 :(得分:0)
您可以让您的函数采用额外的值,这是一个关键字参数:
def printKeyValuePairs(preface, **kwargs):
print preface + "\n"
for k,v in kwargs.iteritems():
print k + ": " + v + "\n"
# usage
printKeyValuePairs("Here are my key-value pairs:", One=1, Two=2, Three=3)
# prints:
# Here are my key-value pairs:
# One: 1
# Two: 2
# Three: 3
# (note that the above lines could be ordered any which way... might want to
# sort first if it matters)