Python装饰器是一个非常" pythonic ";解决了很多问题。因此,我想在我的c扩展中包含一个预定义的装饰器,它可以装饰在包含我的扩展的Python文件中调用的函数。
我似乎在CPython api文档中找不到任何描述如何编写装饰器的内容。如有任何帮助/指导,我将不胜感激。
具体来说,我希望Python代码看起来像下面这样:
import my_c_extension as m
@m.my_decorator(1)
def func():
pass
func()
my_decorator将使用参数'1'在调用func之前执行一些功能(在my_c_extension中用c编写),并在调用func之后执行更多功能。
提前感谢!
对于这样的问题,首先用Python模拟通常是有帮助的。对于您的情况,我希望有两个好处:
-
如果你最终完全在扩展模块中实现装饰器,这将帮助你理解它应该如何工作,以及你将要创建的对象将保持什么状态。
-
通常,您可以通过在Python中完成大部分工作来简化问题。
为了便于讨论,假设您真正尝试做的是使用C扩展来帮助采样低级CPU计数器以进行性能调优。这里有一种方法可以实现Python和C的混合。所有复杂的装饰器魔法都留在Python中,而只有真正需要在C中使用的功能才在C中。
def print_cpu_counter_info(counter_id):
def wrapper(func):
def wrapped(*args, **kwargs):
before = my_c_extension.get_counter_value(counter_id)
ret = func(*args, **kwargs)
after = my_c_extension.get_counter_value(counter_id)
print(f'counter {counter_id}: {before} -> {after}')
return ret
return wrapped
return wrapper
@print_cpu_counter_info(L3_CACHE_LINE_MISS_COUNTER_ID)
def my_slow_func(...):
...
如果这是不可行的(太慢,比这更复杂,等等),那么您将需要在C中创建扩展对象来复制wrapper
和wrapped
函数的行为。这绝对是可行的,但它需要一些工作,而且维护起来会更困难。期望编写数百到数千行C代码来复制上面示例中只需要几行Python代码的内容。