调用python函数就好像它是内联的一样

时间:2010-06-24 21:28:43

标签: python namespaces inline

我希望在一个不同的模块中有一个函数,在调用时,它可以访问其调用者可以访问的所有变量,并且就像它的主体被粘贴到调用者而不是拥有自己的上下文一样起作用,基本上像C宏而不是普通的功能。我知道我可以将locals()传递给函数然后它可以作为dict访问局部变量,但我希望能够正常访问它们(例如xy,而不是x [“y”]并且我希望所有的名字都是调用者不仅可以访问本地,还可以访问“导入”调用者文件但不能访问包含该函数的模块。

这有可能实现吗?

编辑2 以下是我能想到的最简单的例子:

def getObj(expression)
  ofs = expression.rfind(".")
  obj = eval(expression[:ofs])  
  print "The part of the expression Left of the period is of type ", type(obj), 

问题是'表达式'需要调用者的导入和局部变量才能无错误地进行评估。实际上,这不仅仅是一个eval,所以我试图避免只传递本地的解决方案(因为这不会解决我的一般案例问题。

。并且通过eval()

4 个答案:

答案 0 :(得分:3)

另一种,甚至是更加丑陋的方式 - 请不要这样做,即使有可能 -

import sys

def insp():
    l = sys._getframe(1).f_locals
    expression = l["expression"]
    ofs = expression.rfind(".")
    expofs = expression[:ofs]
    obj = eval(expofs, globals(), l)
    print "The part of the expression %r Left of the period (%r) is of type %r" % (expression, expofs, type(obj)), 

def foo():
    derp = 5
    expression = "derp.durr"
    insp()

foo()

输出

  

表达式'derp.durr'部分左侧('derp')的类型(类型'int')

答案 1 :(得分:2)

这是否可以实现?

是的(有点像,以一种非常迂回的方式),我会强烈反对它(稍后会详细介绍)。

考虑:

myfile.py

def func_in_caller():
    print "in caller"

import otherfile
globals()["imported_func"] = otherfile.remote_func

imported_func(123, globals())  

otherfile.py

def remote_func(x1, extra):
    for k,v in extra.iteritems(): 
        globals()[k] = v
    print x1
    func_in_caller()

这会产生(如预期的那样):

123
in caller

我们在这里做的是诡计:我们只是将每个项目复制到另一个名称空间中,以使这项工作成功。这可以(并且)非常容易地破坏和/或导致很难找到错误。

几乎可以肯定有更好的方法来解决您的问题/构建您的代码(我们需要更多关于您要实现的内容的信息)。

答案 2 :(得分:2)

我不认为这是您想要听到的答案,但尝试从调用者模块的范围访问局部变量并不是一个好主意。如果您通常使用PHP或C编程,您可能会习惯这种事情吗?

如果您仍想这样做,您可以考虑创建一个类并传递该类的实例来代替locals()

#other_module.py
def some_func(lcls):
    print(lcls.x)

然后,

>>> import other_module
>>> 
>>> 
>>> x = 'Hello World'
>>> 
>>> class MyLocals(object):
...     def __init__(self, lcls):
...             self.lcls = lcls
...     def __getattr__(self, name):
...             return self.lcls[name]
... 
>>> # Call your function with an instance of this instead.
>>> other_module.some_func(MyLocals(locals()))
'Hello World'

给它一个旋转。

答案 3 :(得分:2)

来自Zen of Python

  

2)显式优于隐式。

换句话说,传递参数并不要因为你觉得它对你更容易而变得非常花哨。编写代码不只是关于你。