gpt4 book ai didi

python - 从属性包装方法返回修改后的文档字符串

转载 作者:行者123 更新时间:2023-11-28 17:36:15 26 4
gpt4 key购买 nike

我有一个属性包装器类:

import functools

class wrapper(object):

def __init__(self, function):
self.function = function
functools.update_wrapper(self, function)

def __call__(self, *args, **kwargs):
# Do some stuff here first
return self.function(self.obj, *args, **kwargs)

def __get__(self, instance, owner):
self.cls = owner
self.obj = instance
return self.__call__

然后我可以包装一些方法 Bar.foo:

class Bar:
@wrapper
def foo(self):
""" This is the docstring I want to see """
pass

现在,如果我创建一些 Bar 实例,然后查看 Bar.foo,它显然是一个包装器,并且没有文档字符串。我想以某种方式修补一些东西,以便显示包装函数中的原始文档字符串(更好的是,我想稍微修改它以包括它被包装的事实)。可以这样做吗?

最佳答案

事实证明,类形式的装饰器与“普通”装饰器(函数形式)的工作方式不同。 update_wrapper 更新装饰器实例的属性,但是当您将该装饰器应用于类的方法时,__doc__ 和其他属性实际上将从 __call__ 装饰器类的方法(因为你从 __get__ 返回了 __call__)。示例:

import functools

class wrapper1(object):
"""This is the wrapper1 class"""
def __init__(self, wrapped):
"""This is the wrapper1.__init__"""
self.wrapped = wrapped
functools.update_wrapper(self, wrapped)

def __call__(self, *args, **kwargs):
"""This is the wrapper1.__call__"""
print "__call__ of wrapper1.__call__"
if hasattr(self, 'obj'):
return self.wrapped(self.obj, *args, **kwargs)
return self.wrapped(*args, **kwargs)

def __get__(self, instance, owner):
self.cls = owner
self.obj = instance
return self.__call__


def wrapper2(wrapped):
@functools.wraps(wrapped)
def _wrapper(*args, **kwargs):
print "_wrapper of wrapper2 decorator"
return wrapped(*args, **kwargs)
return _wrapper


@wrapper1
def f1():
"""The f1 function"""
print "f1 call"


@wrapper2
def f2():
"""The f2 function"""
print "f2 call"

print "call of f1: '{}'".format(f1.__doc__)
f1()

print "call of f2: '{}'".format(f2.__doc__)
f2()

class A(object):
def __init__(self, desc):
self.desc = desc

@wrapper1
def m1(self):
"""The A.m1 method"""
print "A.m1 call: {}".format(self.desc)

@wrapper2
def m2(self):
"""The A.m2 method"""
print "A.m2 call: {}".format(self.desc)

a = A('Hello!')

print "Call of A.m2: {}: {}".format(a.m2.__doc__, A.m2.__doc__)
a.m2()

print "Call of A.m1: {}: {}".format(a.m1.__doc__, A.m1.__doc__)
a.m1()

最后两行打印出来:

Call of A.m1: This is the wrapper1.__call__: This is the wrapper1.__call__
__call__ of wrapper1.__call__
A.m1 call: Hello!

如果装饰器的形式并不重要,那么使用装饰器作为def wrapper(wrapped):。它更简单明了。但是如果出于某些原因你仍然想使用类形式的装饰器,那么将 __get__ 方法更改为返回 self,它将修复不希望的行为:

def __get__(self, instance, owner):
self.cls = owner
self.obj = instance
return self

关于python - 从属性包装方法返回修改后的文档字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30340115/

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