2013-02-22 52 views
1

这可能看起来像一个相当奇怪的事情,但我很好奇,如果有可能隐式通过一个变量在Python中调用链而不传递它作为参数。为了更好地说明这里有一个例子:Python中的每个激活“全局”变量?

这里是 “正常” 的方式:

def three(something): 
    print(something) 

def two(something): 
    # ... 
    three(something) 

def one(something): 
    # ... 
    two(something) 

这里就是我希望能够做到:

def three(): 
    # something is defined implicitly 
    print(something) 

def two(): 
    # ... 
    three() 

def one(something): 
    # somehow define something inside a context 
    # for this activation 
    two() 

为此,one,twothree不在同一个类或甚至相同的模块。

+0

如果它们不在同一个类或模块中,那么当'three'被调用时定义的'something'有什么保证? – StoryTeller 2013-02-22 20:45:58

+0

什么都没有。这是非常可怕的黑客攻击,但我仍然希望它能够工作。 – 2013-02-22 20:47:38

+0

不,你不知道。你可能会对好奇心或某事感兴趣,但是你不想真的写这样的代码;-) FWIW我认为如果不深入改变语言是不可能的(特别是静态确定哪些名字被查找的范围规则在哪个范围内)。 – delnan 2013-02-22 20:50:34

回答

2
  1. 你不想这样做。

  2. 如果您确信自己想折磨自己,那么您可以创建一个单独的线程并在该线程中运行one()的调用。然后只需使用threading.local作为共享状态。

  3. 你真的不想这样做。

这里是你如何使用线程本地存储:

import threading 
state = threading.local() 

def three(): 
    # something is defined implicitly 
    print(state.something) 

def two(): 
    # ... 
    three() 

def one(something): 
    # somehow define something inside a context 
    # for this activation 
    def inner(): 
     state.something = something 
     two() 
    t = threading.Thread(target=inner) 
    t.start() 
    t.join() 

if __name__=='__main__': 
    one(42) 
    one(24) 
+0

TLS具有创建另一个线程的开销,并且在由于某种原因(例如事件处理程序)而无法创建另一个线程的情况下并不总是可以接受的。 – 2013-02-22 21:06:19

+0

虽然erm,它会使用'join'。尽管如此,仍然在OS级创建线程的开销。 – 2013-02-22 21:12:28

0

如果您必须,您可以将值分配给函数对象本身。理想情况下,如果“某些”设置不正确,那么three()和two()都会执行检查,这会比AttributeError引发更好的异常。

def three(): 
    print(three.something) 

def two(): 
    three.something = two.something 
    three() 

def one(something): 
    two.something = something 
    two() 
+0

但是在这种情况下,两个人必须明确地做些事情,把事情传递给三个人,这不是我想要的。它必须传递给呼叫链,而没有任何功能需要做任何事情。此外,在这种情况下,变量最终成为全局性的,而不是在每个激活的基础上完成。 – 2013-02-22 20:57:00

+0

这不会是可重入的 – 2013-02-22 20:57:01

0

你可以利用词法闭包 - 一个的定义中定义两个()和三个()()。

+0

“*就此而言,一,二和三不在同一个班级,甚至不在同一个班级。*” – 2013-02-22 21:09:21

0

您可以使用__builtins__来保存您的“全局变量”。

>>> __builtins__.something = "Hello world!" 
>>> def foo(): 
    print something 


>>> foo() 
Hello world! 

这可以帮助您避免显式传递变量。
这是一个可怕的黑客。恕我直言,你真的不需要那样做。

+0

这不会使这些变量不依赖于它们被调用的激活吗? – 2013-02-22 21:38:05