gpt4 book ai didi

Python - 使用 decorator.py 来保存方法文档字符串

转载 作者:太空宇宙 更新时间:2023-11-03 11:06:46 24 4
gpt4 key购买 nike

我有兴趣将实例方法作为类方法和实例方法来调用。这可以通过使用 class_or_instance 装饰器来完成,如下所示:

class class_or_instance(object):
def __init__(self, fn):
self.fn = fn

def __get__(self, obj, cls):
if obj is not None:
return lambda *args, **kwds: self.fn(obj, *args, **kwds)
else:
return lambda *args, **kwds: self.fn(cls, *args, **kwds)

class A(object):
@class_or_instance
def func1(self,*args):
# method body

现在我可以将 func1 调用为 A.func1(*args)A().func1(*args)。然而,这样做时 func1 的文档字符串消失了。解决这个问题的一种方法是使用来自 decorator.py 的装饰器但是我无法让它与作为类而不是函数的装饰器一起使用。关于如何解决这个问题有什么建议吗?

编辑:functools.wraps() 在这种情况下将无法正常工作。参见 related question在计算器上

最佳答案

基本描述符/装饰符

您只需要记住您应该装饰哪个函数。您的函数是在 __get__ 中创建的,因此将包装器用作装饰器无济于事,相反,您需要在 __get__ 方法中应用它。顺便说一句,您可以为此使用 functools.update_wrapperdecorators.decorator。它们的工作方式非常相似,只是您必须保留 decorators.decorator 的结果,而 functools.update_wrapper 返回 None。两者都有签名 f(wrapper, wrapped)

from functools import update_wrapper
class class_or_instance(object):
def __init__(self, fn):
self.fn = fn

def __get__(self, obj, cls):
if obj is not None:
f = lambda *args, **kwds: self.fn(obj, *args, **kwds)
else:
f = lambda *args, **kwds: self.fn(cls, *args, **kwds)
# update the function to have the correct metadata
update_wrapper(f, self.fn)
return f

class A(object):
@class_or_instance
def func1(self,*args):
"""some docstring"""
pass

现在如果你这样做:

print A.func1.__doc__

你会看到“一些文档字符串”。耶!


缓存属性装饰器

这里的关键是您只能影响返回的内容。由于 class_or_instance 实际上并不充当函数,因此使用它做什么并不重要。请记住,此方法会导致函数每次都被反弹。我建议您改为添加一点魔术,并在第一次调用后绑定(bind)/缓存函数,这实际上只涉及添加一个 setattr 调用。

from functools import update_wrapper
import types

class class_or_instance(object):
# having optional func in case is passed something that doesn't have a correct __name__
# (like a lambda function)
def __init__(self, name_or_func):
self.fn = fn
self.name = fn.__name__

def __get__(self, obj, cls):
print "GET!!!"
if obj is not None:
f = lambda *args, **kwds: self.fn(obj, *args, **kwds)
update_wrapper(f, self.fn)
setattr(obj, self.name, types.MethodType(f, obj, obj.__class__))
else:
f = lambda *args, **kwds: self.fn(cls, *args, **kwds)
update_wrapper(f, self.fn)
return f

然后我们可以测试它......neato:

A.func1 #GET!!!
obj = A()
obj.func1 #GET!!!
obj.func1 is obj.func1 # True
A.func1 # GET!!!
obj2 = A()
obj2.func1 is not obj.fun1 # True + GET!!!

关于Python - 使用 decorator.py 来保存方法文档字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17160117/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com