在使用嵌套函数的Video 类的上下文中:
class Video(object):
def __init__(self, ...):
self.__cbFileRefDone = []
def open(self, filename):
@WINFUNCTYPE(None, DWORD, DWORD)
def cbFileRefDone(port, user_data):
print "File indexed.", filename
self.__cbFileRefDone.append(cbFileRefDone) # save reference
if not self.hsdk.PlayM4_SetFileRefCallBack(
c_long(self.port), cbFileRefDone, DWORD(0)):
logging.error("Unable to set callback for indexing")
return False
它有点难看,但更自然的变体在回调期间因 TypeError 而失败:
#XXX this won't work
@WINFUNCTYPE(None, DWORD, DWORD)
def cbFileRefDone(self, port, user_data):
print "File indexed."
为了解决这个问题,可以创建一个特殊的函数描述符:
def method(prototype):
class MethodDescriptor(object):
def __init__(self, func):
self.func = func
self.bound_funcs = {} # hold on to references to prevent gc
def __get__(self, obj, type=None):
assert obj is not None # always require an instance
try: return self.bound_funcs[obj,type]
except KeyError:
ret = self.bound_funcs[obj,type] = prototype(
self.func.__get__(obj, type))
return ret
return MethodDescriptor
用法:
class Video(object):
@method(WINFUNCTYPE(None, DWORD, DWORD))
def cbFileRefDone(self, port, user_data):
print "File indexed."
def open(self, filename):
# ...
self.hsdk.PlayM4_SetFileRefCallBack(
c_long(self.port), self.cbFileRefDone, DWORD(0))
此外 MethodDescriptor 保存对 C 函数的引用以防止它们被垃圾收集。