19

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

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 上,因为请求变量是唯一的并且缓存是无用的。所以我创建了具有可重复参数(search_term)的内部函数。

然而,为了使缓存失效(即刷新),失效函数需要知道“getData”函数的范围,因此也需要嵌套。因此我需要调用嵌套函数。你们这些了不起的人已经明确表示这是不可能的,所以有人能够解释我如何用不同的结构来做到这一点吗?

4

7 回答 7

29

我假设do_this并且do_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()
于 2012-06-22T10:44:23.983 回答
17

这些之前的答案,告诉你不能这样做,当然是错误的。这是 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'
于 2015-10-15T15:09:36.197 回答
4

有,您必须将它们作为函数对象的属性。但这只有在第一次调用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)
>>>
于 2012-06-22T10:52:45.993 回答
3

不(除了在闭包对象中四处寻找,这在这里完全是矫枉过正)。如果需要,请使用类。

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):
    ...
于 2012-06-22T10:44:34.890 回答
2

不,那里没有。由于您可以从嵌套函数中访问外部范围内的变量:

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

在为anddo_this提供绑定时无法调用。xy

如果您必须do_this从其他地方调用,只需将其设置为与foo.

于 2012-06-22T10:44:01.593 回答
1

你可以这样试试:

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)
于 2018-08-10T08:14:09.263 回答
1

我就是这样做的。

代码

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:  !
于 2021-01-28T16:44:02.573 回答