一个类如何生成一个根据类属性更改的回调函数?

时间:2018-04-29 23:19:58

标签: python class import wrapper python-module

我遇到这种情况:

module1.py

class AudioEngine:
    def __init__(self):
        self.liverecording = False

    def getaudiocallback(self):

        def audiocallback(in_data, frame_count, time_info, status):  # these 4 parameters are requested by pyaudio
            data = None      # normally here we process the audio data
            if self.liverecording:
                print("Recording...")
            return data

        return audiocallback

main.py

import module1

a = module1.AudioEngine()
f = a.getaudiocallback()

f(0, 0, 0, 0)

a.liverecording = True

f(0, 0, 0, 0)  # prints "Recording...", which is the expected behaviour, but why does it work?

问题:如何使回调函数audiocallback(...)相应地更改为a.liverecording的新值?如果它开箱即用,为什么呢?

更具体地说,f一旦使用f = a.getaudiocallback()创建,请保留其代码指向a.liverecording 的指针(因此,如果后者被修改,则为({1}}创建时 a.liverecording(或False)的副本

1 个答案:

答案 0 :(得分:2)

如果您了解闭包,那么唯一的技巧是您在闭包中捕获的局部变量是self内的getaudiocallback参数。

在该方法中,self当然是AudioEngine实例a。因此,您捕获的变量的值是同一个实例。

事实上,Python允许您在运行时反映几乎所有内容,因此您可以直接看到:

>>> f = a.getaudiocallback()
>>> f
<function __main__.AudioEngine.getaudiocallback.<locals>.audiocallback(in_data, frame_count, time_info, status)>
>>> f.__closure__[0].cell_contents
<__main__.AudioEngine at 0x11772b3c8>
>>> f.__closure__[0].cell_contents is a
True

如果getaudiocallback仍然有效,并且self反弹到某个其他值,那么f.__closure__[0]会更新为指向self的新值。由于它已经退出,这种情况永远不会发生;在调用方法时,单元格将始终指向a中的实例。

但如果该实例后来发生变异,就像你写a.liverecording = True时一样,当然你可以看到它。