2012-06-22 85 views
11

我有一个方法,我已经破碎成更小的嵌套函数,打破了代码库:呼叫嵌套函数在Python

def foo(x,y): 
    def do_this(x,y): 
     pass 
    def do_that(x,y): 
     pass 
    do_this(x,y) 
    do_that(x,y) 
    return 

有没有办法通过自身运行的嵌套功能之一。例如:

foo.do_this(x,y) 

编辑:

我想设置缓存的web服务器,我已经使用pyramid_breaker

def getThis(request): 
    def invalidate_data(getData,'long_term',search_term): 
     region_invalidate(getData,'long_term',search_term) 
    @cached_region('long_term') 
    def getData(search_term): 
     return response 
    search_term = request.matchdict['searchterm'] 
    return getData(search_term) 

这是我的理解可能不准确建立在:

现在我有这个的原因是装饰器用来创建缓存键的命名空间是从函数生成的和争论。因此,您不能只将getDevice放在getThis上,因为请求变量是唯一的,并且缓存是无用的。所以我创建了具有可重复参数(search_term)的内部函数。

但是,为了使缓存无效(即刷新),无效函数需要范围知道'getData'函数,因此也需要嵌套。因此我需要调用嵌套函数。你们美好的人已经明确表明它不可能,所以有人能够解释我如何用不同的结构来做它?

+0

代码'foo.do_this'将尝试访问do_this作为成员本功能离开'foo',它会给你一个属性错误,而不是让foo作为类 – avasal

+0

“分解代码库”是模块名称空间的优点。如果你真的想封装do_函数,那么使用class作为@lazyr显示。 – msw

+0

嵌套函数不是在Python中构造代码的方式(也不是类)。看看[modules](http://docs.python.org/tutorial/modules.html)。 – georg

回答

19

我认为do_thisdo_that实际上是依赖于foo一些说法,否则你可能只是移动出来的foo并直接调用它们。

我建议将整个事情改为班级。例如:

class Foo(object): 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 

    def do_this(self): 
     pass 

    def do_that(self): 
     pass 

    def __call__(self): 
     self.do_this() 
     self.do_that() 

foo = Foo(x, y) 
foo() 
foo.do_this() 
+0

非常有用的答案,感觉像我的整个结构可能是错误的。如果我解释一个更大的图片,看看你能否帮忙(如果太困难,不要担心),可能会更有帮助。 – user1474424

+2

@ user1474424我认为你应该把这个置于一个新的问题中。 –

+0

我编辑了一个问题。是否更好地创建一个新的问题,对不起,我是一个新的堆栈溢出 – user1474424

3

不,没有。因为你可以从一个嵌套函数中访问外部范围中的变量:

def foo(x,y): 
    def do_this(z): 
     print(x,y,z) 
    # ... 

没有办法打电话do_this同时提供xy绑定。

如果您必须从其他地方拨打do_this,只需将其设置为与foo相同级别的顶级功能即可。

2

否(除了在闭合对象中戳动,这在这里完全矫枉过正)。如果你需要的话,使用一个班级。

class foo(object): 
    def do_this(self, x, y): 
     ... 
    def do_that(self, x, y): 
     ... 
    def do_other_stuff(self, x, y): 
     # or __call__, possibly 

或者只是把这些功能外范围,因为你反正都传递作为参数:

def foo(x, y): 
    do_this(x, y) 
    do_that(x, y) 

def do_this(x, y): 
    ... 

def do_that(x, y): 
    ... 
1

还有就是,你必须让他们作为函数对象的属性。但是这只会在foo的第一个电话后才起作用。

def foo(x,y): 
    def do_this(x,y): 
     pass 
    def do_that(x,y): 
     pass 
    do_this(x,y) 
    do_that(x,y) 
    foo.do_this = do_this 
    foo.do_that = do_that 
    return 

>>> foo.do_this(1, 2) 
AttributeError: 'function' object has no attribute 'do_this' 
>>> foo(1, 2) 
>>> foo.do_this(1, 2) 
>>> 
7

这些以前的答案,告诉你,你不能这样做,当然是错误的。 这是python,你可以使用一些魔术代码魔法来做几乎任何你想要的东西。

我们可以从foo的功能代码中取出第一个常量,这将是do_this函数。然后我们可以使用这段代码来创建一个新的函数。

请参阅https://docs.python.org/2/library/new.html了解更多关于新信息和https://docs.python.org/2/library/inspect.html以获取更多关于如何进入内部代码的信息。

警告:这是不是因为你能做到这一点,你应该这样做, 重新考虑你有你的功能结构的方式是要走的路,但如果你想快速和肮脏的黑客将可能打破未来,在这里你去:

import new 
myfoo = new.function(foo.func_code.co_consts[1],{}) 
myfoo(x,y) # hooray we have a new function that does what I want 

更新:在python3您可以使用类型模块foo.__code__

import types 
myfoo = types.FunctionType(foo.__code__.co_consts[1], {}) 
myfoo() # behaves like it is do_this() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: do_this() missing 2 required positional arguments: 'x' and 'y' 
+0

在Python 3中,我可以使用'types'? –

+0

@VitalyZdanevich是的,根据[文档](https://docs.python.org/2/library/new.html):'从2.6版开始弃用:新模块已经在Python 3中移除。使用类型模块的类代替。“ – Pedro

+0

这应该是被接受的答案 – noamt