在Python中调用嵌套函数

时间:2012-06-22 10:41:01

标签: python nested

我有一个方法,我已经分解成较小的嵌套函数来分解代码库:

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)

修改

我正在尝试在使用pyramid_breaker构建的Web服务器上设置缓存

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)

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

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

然而,为了使缓存无效(即刷新),失效函数需要知道'getData'函数的范围,因此也需要嵌套。因此我需要调用嵌套函数。你们精彩的人已经说清楚它是不可能的,那么有人能够解释我如何用不同的结构来做这件事吗?

7 个答案:

答案 0 :(得分:23)

我认为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()

答案 1 :(得分:11)

这些以前的答案,告诉你不能这样做,当然是错的。 这是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中,您可以将types模块与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'

答案 2 :(得分:3)

不,没有。因为您可以从嵌套函数中访问外部作用域中的变量:

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

在为do_thisx提供绑定时,无法致电y

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

答案 3 :(得分:3)

有,你必须将它们作为功能对象的属性。但这只有在第一次调用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)
>>>

答案 4 :(得分: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):
    ...

答案 5 :(得分:0)

您可以尝试这种方式:

def a(x, y):
    name = 'Michael'
    a.name = name

    a.z = z = x * y
    #a.z = z

def b():
    def give_me_price(f,g):
        price = f * g
        return price

    def two(j,k):
        surname = 'Jordan' # without return surname give None

    # two = two('arg1', 'arg2')
    # b.blabla = two

    one = give_me_price(5, 10)
    b.halabala = one

    print(a.name) # ;)

x = 20
y = 30

a(x,y) # IMPORTANT! first you must run function
print(a.z)
print(a.name * 5)

print('-'*12)
b() # IMPORTANT! first you must run function
print('price is: ' + str(b.give_me_price(5, 25)))
# print(b.blabla)

答案 6 :(得分:0)

我就是这样做的。

代码

def getMessage(a="", b="", c=""):
    def getErrorMessage(aa, bb):
        return "Error Message with/without params: {}{}".format(aa, bb)

    def getSuccessMessage(bb, cc):
        return "Success Message with/without params:  {}{}".format(bb, cc)

    def getWarningMessage(aa, cc):
        return "Warning Message with/without params:  {}{}".format(aa, cc)

    return {
        "getErrorMessage": getErrorMessage(a, b),
        "getSuccessMessage": getSuccessMessage(b, c),
        "getWarningMessage": getWarningMessage(a, c),
    }


a = "hello"
b = " World"
c = "!"
print(getMessage(a, b)["getErrorMessage"])
print(getMessage(b=b, c=c)["getSuccessMessage"])
print(getMessage(a=a, c=c)["getWarningMessage"])
print(getMessage(c=c)["getWarningMessage"])

输出

Error Message with/without params: hello World
Success Message with/without params:   World!
Warning Message with/without params:  hello!
Warning Message with/without params:  !
相关问题