简体   繁体   English

在 Python 中调用嵌套函数

[英]Call Nested Function in Python

I have a method that i have broken into smaller nested functions to break up the code base:我有一个方法,我已经分解成更小的嵌套函数来分解代码库:

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

Is there a way to run one of the nested functions by itself.有没有办法自行运行其中一个嵌套函数。 eg:例如:

foo.do_this(x,y)

EDIT:编辑:

I am trying to setup caching on a web server i have built using pyramid_breaker我正在尝试在使用 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)

This is my understanding may not be accurate:这是我的理解可能不准确:

Now the reason i have this is that the namespace used by the decorator to create the cache key is genereated from the function and the arguements.现在我有这个的原因是装饰器用来创建缓存键的命名空间是从函数和参数中生成的。 You can't therefore just put the decorator on getThis as the request variable is unique-ish and the cache is useless.因此,您不能将装饰器放在 getThis 上,因为请求变量是唯一的,而缓存是无用的。 So i created the inner function which has repeatable args (search_term).所以我创建了具有可重复参数(search_term)的内部函数。

However to invalidate the cache (ie refresh), the invalidation function requires scope to know of the 'getData' function so also needs to be nested.然而,为了使缓存失效(即刷新),失效函数需要知道“getData”函数的范围,因此也需要嵌套。 Therefore i need to call the nested function.因此我需要调用嵌套函数。 You wonderful people have made it clear its not possible so is someone able to explain how i might do it with a different structure?你们很棒的人已经明确表示这是不可能的,所以有人能够解释我如何用不同的结构来做到这一点?

I assume do_this and do_that are actually dependent on some argument of foo , since otherwise you could just move them out of foo and call them directly.我假设do_thisdo_that实际上依赖于foo一些参数,否则你可以将它们移出foo并直接调用它们。

I suggest reworking the whole thing as a class.我建议将整个事情作为一个班级进行重新处理。 Something like this:像这样的东西:

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()

These previous answers, telling you that you can not do this, are of course wrong.之前的这些回答,告诉你你不能这样做,当然是错误的。 This is python, you can do almost anything you want using some magic code magic.这是python,您几乎可以使用一些魔术代码魔术做任何您想做的事情。

We can take the first constant out of foo's function code, this will be the do_this function.我们可以从 foo 的函数代码中取出第一个常量,这就是do_this函数。 We can then use this code to create a new function with it.然后我们可以使用此代码创建一个新函数。

see https://docs.python.org/2/library/new.html for more info on new and https://docs.python.org/2/library/inspect.html for more info on how to get to internal code.看到https://docs.python.org/2/library/new.html的新方式等详细信息https://docs.python.org/2/library/inspect.html关于如何让内部的详细信息代码。

Warning: it's not because you CAN do this that you SHOULD do this , rethinking the way you have your functions structured is the way to go, but if you want a quick and dirty hack that will probably break in the future, here you go:警告:并不是因为你可以这样做,所以你应该这样做,重新思考你的函数结构的方式是要走的路,但如果你想要一个快速而肮脏的 hack 可能会在未来崩溃,你去吧:

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

UPDATE: in python3 you can use the types module with foo.__code__ :更新:在 python3 中,您可以使用带有foo.__code__的 types 模块:

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'

There is, you have to make them as an attribute of the function object.有,您必须将它们作为函数对象的属性。 But this will work only after the first call of foo .但这只有在第一次调用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)
>>>

No (apart from poking around in closure objects, which is complete overkill here).不(除了在闭包对象中闲逛,这在这里完全矫枉过正)。 If you need that, use a class.如果需要,请使用类。

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

Or just put those functions in the outer scope, since you're passing everything as arguments anyway:或者只是将这些函数放在外部作用域中,因为无论如何您都将所有内容作为参数传递:

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

def do_this(x, y):
    ...

def do_that(x, y):
    ...

No, there is not.不,那里没有。 Since you may access variables in an outer scope from within a nested function:由于您可以从嵌套函数中访问外部作用域中的变量:

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

there is no way to call do_this while providing a binding for x and y .在为xy提供绑定时无法调用do_this

If you must call do_this from elsewhere, simply make it a top level function at the same level as foo .如果您必须从其他地方调用do_this ,只需将其设为与foo相同级别的顶级函数即可。

You can try this way:你可以试试这个方法:

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)

This is how I did it.我就是这样做的。

CODE代码

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"])

OUTPUT输出

Error Message with/without params: hello World
Success Message with/without params:   World!
Warning Message with/without params:  hello!
Warning Message with/without params:  !

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM