代码之家  ›  专栏  ›  技术社区  ›  bdk

像内联一样调用python函数

  •  2
  • bdk  · 技术社区  · 14 年前

    我想在一个不同的模块中有一个函数,当被调用时,它可以访问调用者可以访问的所有变量,函数的作用就像它的主体被粘贴到调用者中而不是有它自己的上下文一样,基本上就像一个C宏而不是一个普通的函数。我知道我可以将local s()传递到函数中,然后它可以以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), 
    

    问题是“expression”需要调用方的导入和局部变量才能无误地进行eval。实际上,这不仅仅是eval,因此我试图避免只将locals()传入eval()并传递给eval()的解决方案,因为这不会解决我的一般情况问题。

    4 回复  |  直到 14 年前
        1
  •  2
  •   orokusaki    14 年前

    我不认为这是您想要听到的答案,但是尝试从调用者模块的作用域访问局部变量不是一个好主意。如果您通常使用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'
    

    试一试。

        2
  •  3
  •   AKX Bryan Oakley    14 年前

    还有一个更糟糕的方法——请不要这样做,即使可能。--

    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”)左侧表达式“derp.durr”的部分属于类型(类型“int”)。

        3
  •  2
  •   ChristopheD    14 年前

    这可以起飞吗?

    是的(某种程度上,以一种非常迂回的方式),我强烈建议一般情况下不要这样做(稍后再详细讨论)。

    考虑:

    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
    

    我们在这里所做的是欺骗:我们只是将每个项复制到另一个名称空间中,以使其正常工作。这个罐头(和) )很容易打破和/或导致难以发现的错误。

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

        4
  •  2
  •   unholysampler    14 年前

    Zen of Python :

    2)显式优于隐式。

    换言之,传递参数,不要仅仅因为你认为它对你来说会更容易,就试图获得真正的幻想。编写代码不仅仅是为了你。