__getattr__ 定义属性的文档

6 投票
2 回答
829 浏览
提问于 2025-04-17 12:16

我需要自定义 __getattr__ 这个方法,让它去调用另一个函数来读取数据。

这样做效果不错,但有一个问题,就是使用 help(object.attr) 时无法正常工作。因为这段代码是在一个交互式环境中使用的,所以 help() 对我们来说非常重要。

有没有更好的设计方法,能实现相同的功能,同时让 help() 也能正常工作呢?

2 个回答

1

你可以把一个属性变成一个属性方法。这样,这个属性方法会自动使用获取方法的说明文档作为它自己的说明。或者,你也可以给 property() 提供一个 doc 参数。

1

用来显示“帮助”的文本其实是对象的一个属性,叫做 "__doc__"。不过,根据你手里的对象类型,有时候你不能直接给这个 __doc__ 属性赋值。

如果你想让 "help(object.attr)" 正常工作(而不是让 help(object) 显示所有可能的属性),那就简单一些——你只需要确保 __getattr__ 返回的内容有正确设置的文档字符串。

既然“它不工作”,我猜测你可能是在返回某个函数调用的内部结果,就像下面这个代码片段:

def __getattr__(self, attr):
    if attr == "foo":
        #function "foo" returns an integer
        return foo()
    ...

如果你直接返回函数 "foo" 本身,而不是调用它,那么它的文档字符串就会正常显示。

你可以把返回值包裹在 __getattr__ 中,作为一个动态创建的类的对象,这个类包含一个合适的文档字符串——所以,试试用下面的方式:

def __getattr__(self, attr):
    if attr == "foo":
        #function "foo" returns an (whatever object)
        result = foo()
        res_type = type(result)
        wrapper_dict = res_type.__dict__.copy()
        wrapper_dict["__doc__"] = foo.__doc__ #(or "<desired documentation for this attribute>")
        new_type = type(res_type.__name__, (res_type,), wrapper_dict)
        # I will leave it as an "exercise for the reader" if the 
        # constructor of the returned object can't take an object
        # of the same instance (python native data types, like int, float, list, can)
        new_result = new_type(result)
    elif ...: 
        ...
    return new_result

这样应该可以工作——除非我误解了你为什么帮助功能一开始就不工作。如果是这样,请给我一些你从 __getattr__ 返回的内容的例子。

撰写回答