【问题标题】:Call python function as if it were inline像内联一样调用python函数
【发布时间】:2010-06-24 21:28:42
【问题描述】:

我想在不同的模块中有一个函数,当被调用时,它可以访问它的调用者可以访问的所有变量,并且就像它的主体被粘贴到调用者而不是拥有自己的上下文一样,基本上就像一个 C 宏而不是一个普通的函数。我知道我可以将 locals() 传递给函数,然后它可以将局部变量作为 dict 访问,但我希望能够正常访问它们(例如 x.y,而不是 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() ,因为这不能解决我的一般情况问题。

【问题讨论】:

  • 是的,您可以这样做,但您可能不应该出于同情下一个阅读您的代码的人而添加神秘的语言功能。最好不要使用 C 预处理器宏是有原因的:它们以神秘的方式改变语言。
  • 您应该询问问题,而不是(很好地说)不寻常解决方案。
  • @THC4k- 5000 英尺视图是我几周前发布的这个问题,但没有引起任何关注:stackoverflow.com/questions/3027307/… 我正在尝试为该问题提供一般案例解决方案

标签: python namespaces inline


【解决方案1】:

还有另一种更丑陋的方法——请不要这样做,即使有可能——

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')

【讨论】:

  • 我没有完全按照 OP 做的那样做,但 sys._getframe(n).f_locals 正是我一直在寻找的几个小时
【解决方案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】:

这有可能实现吗?

是的(有点,以一种非常迂回的方式),我强烈建议一般不要这样做(稍后会详细介绍)。

考虑:

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

我们在这里做的是诡计:我们只是将每个项目复制到另一个命名空间中以使其工作。这可能(并且)很容易破坏和/或导致难以发现的错误。

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

【讨论】:

  • 或者甚至在remote_func,只是locals().update(extra)。少一点混乱。
  • 谢谢,我将根据我正在尝试做的事情的更大背景来编辑我的问题
【解决方案4】:

来自Zen of Python

2) 显式优于隐式。

换句话说,传入参数,不要仅仅因为你认为这对你来说更容易而试图变得非常花哨。编写代码不只是关于你。

【讨论】:

  • 不确定我是否遵循,一旦我传递了实际变量,我的函数只会获取当前值并且无法执行需要知道实际路径字符串的 wsdl 反射。
猜你喜欢
  • 2013-04-02
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-12
  • 2010-11-06
相关资源
最近更新 更多