2012-06-22 86 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