首页 > 解决方案 > 向运行 Python 装饰器的模块添加属性

问题描述

我想编写一个 Python 装饰器,它向正在运行装饰器的模块添加一个属性,即

@procedure
def whatever(arg1, arg2):
    # do things
    return

attr应该向找到的模块添加一个属性whatever。我尝试编写装饰器procedure(在另一个文件中定义)如下

def procedure(fn):
    global attr
    attr = SomeClass()
    return fn

attr被添加到procedure定义的模块,而不是procedure运行的模块。还有其他方法可以做到这一点吗?

标签: pythonmoduleattributesdecorator

解决方案


假设您要标记一个函数,以便定义它的模块的某些用户能够知道它属于某个函数类别。你可以像这样写一个简单的装饰器:

def special(fn):
    globals().setdefault("__specials__", set()).add(fn)
    return fn

然后你可以编写一个使用这个装饰器的模块,像这样:

"""Module 'has_specials'"""
def regular():
    return "meh"

@special
def important():
    return "wow!"

@special
def bigshot():
    return "HA"

然后可以由另一个模块使用,如下所示:

import has_specials

if hasattr(has_specials, "__specials__"):
    for fn in has_specials.__specials__:
        print("%-20s: %s" % (fn.__name__, fn))

上面的代码将导入模块,并列出special函数:

important           : <function important at 0x000002435FD51488>
bigshot             : <function bigshot at 0x000002435FD51510>

推荐阅读