如何在函数内定义函数?

86 阅读2分钟

在某些情况下,我们需要在一个函数内定义另一个函数,并且内部函数需要访问外部函数的局部变量。例如,以下代码尝试在 DNPClass 类的 handleResponseEvent() 方法中执行额外的 C1 类方法。但是,如果 handleResponseEvent() 方法定义在 main() 函数内,它才能正常工作。问题是,我们希望了解在函数内定义函数的其他方法,以及在 main() 函数内定义事件处理函数是否为最佳方法。

huake_00152_.jpg

def main():
    C1 = DNPClass()
    C1.method1(arg1, arg2, arg3, arg4, arg5)

    # subscribing to event
    C1.method2.RequestEvent += handleResponseEvent
    ...

def handleResponseEvent( request, response):
    #code to execute when event handler is called
    #code references additional method from C1 instance
    ....

2. 解决方案

  1. 将事件处理函数定义在外部函数内

第一种方法是将 handleResponseEvent() 方法定义在 DNPClass 类中,而不是在 main() 函数内。这样,内部函数就可以访问 DNPClass 类的实例变量。以下代码展示了这种方法:

class DNPClass:
    def __init__(self):
        self.method2 = Method2()

    def method1(self, arg1, arg2, arg3, arg4, arg5):
        # code

    def handleResponseEvent(self, request, response):
        # code to execute when event handler is called
        # code references additional method from self instance
        ...

class Method2:
    def __init__(self):
        self.RequestEvent = Event()


def main():
    C1 = DNPClass()
    C1.method1(arg1, arg2, arg3, arg4, arg5)

    # subscribing to event
    C1.method2.RequestEvent += C1.handleResponseEvent  # will call C1.method3
    ...

  1. 使用闭包来访问外部函数的局部变量

第二种方法是使用闭包来访问外部函数的局部变量。闭包是指一个可以访问另一个函数作用域变量的函数。在以下代码中,我们使用闭包将 C1 对象传递给 handleResponseEvent() 函数:

def main():
    C1 = DNPClass()
    C1.method1(arg1, arg2, arg3, arg4, arg5)

    # subscribing to event
    C1.method2.RequestEvent += lambda request, response: handleResponseEvent(request, response, C1)
    ...

def handleResponseEvent(request, response, dnp):
    # code to execute when event handler is called
    # code references additional method from dnp instance
    dnp.method3()
    ...

  1. 使用 functools.partial() 函数来创建闭包

第三种方法是使用 functools.partial() 函数来创建闭包。partial() 函数可以创建一个新的函数,该函数可以将参数部分预先绑定到另一个函数。在以下代码中,我们使用 partial() 函数将 C1 对象作为参数绑定到 handleResponseEvent() 函数:

from functools import partial

def main():
    C1 = DNPClass()
    C1.method1(arg1, arg2, arg3, arg4, arg5)

    # subscribing to event
    C1.method2.RequestEvent += partial(handleResponseEvent, C1)
    ...

def handleResponseEvent(dnp, request, response):
    # code to execute when event handler is called
    # code references additional method from dnp instance
    dnp.method3()
    ...

三种方法各有优缺点,可以根据具体情况选择使用哪种方法。