我正在尝试创建一个在类中调用的装饰器,该装饰器将从该类中提取属性,并使用这些类属性来编辑函数的文档字符串。
我的问题是,我找到了装饰器的示例,它们可以编辑函数的文档字符串(将函数的__doc__
属性设置为新的字符串),并且我还可以找到装饰器的示例,这些示例可以从父类(通过将self
传递到装饰器中),但是我找不到能够同时实现两者的装饰器示例。
我尝试将这两个示例结合在一起,但不起作用:
def my_decorator(func):
def wrapper(self, *args, **kwargs):
name = func.__name__ # pull function name
cls = self.__class__.__name__ # pull class name
func.__doc__ = "{} is new for the function {} in class {}".format(
str(func.__doc__), name, cls) # set them to docstring
return func(self, *args, **kwargs)
return wrapper
class Test():
@my_decorator
def example(self, examplearg=1):
"""Docstring"""
pass
有了这个,我希望以下内容将返回“该函数的文档字符串现在是新的”:
Test().example.__doc__
相反,它返回None
。
编辑:请注意,我对如何具体访问类的名称不感兴趣,而对一般访问类属性(此处使用self.__class__.__name__
的方法不感兴趣)例如)。
答案 0 :(得分:2)
example
替换为wrapper
;装饰等同于
def example(self, examplearg=1):
"""Docstring"""
pass
example = my_decorator(example)
因此您需要设置wrapper.__doc__
,而不是func.__doc__
。
def my_decorator(func):
def wrapper(self, *args, **kwargs):
return func(self, *args, **kwargs)
wrapper.__doc__ = "{} is new for the function {}".format(
str(func.__doc__),
func.__name__)
return wrapper
请注意,在调用my_decorator
时,您没有关于修饰函数/方法属于哪个类的任何信息。您将必须明确传递其名称:
def my_decorator(cls_name):
def _decorator(func):
def wrapper(self, *args, **kwargs):
return func(self, *args, **kwargs)
wrapper.__doc__ = "{} is new for function {} in class {}".format(
func.__doc__,
func.__name__,
cls_name)
return wrapper
return _decorator
class Test():
@my_decorator("Test")
def example(self, examplearg=1):
"""Docstring"""
# or
# def example(self, examplearg=1):
# """Docstring"""
#
# example = my_decorator("Test")(example)
答案 1 :(得分:1)
您可以在调用装饰器时简单地修改__doc__
属性,并使用函数的以点分隔的__qualname__
属性的第一个标记获取类名:
def my_decorator(func):
func.__doc__ = "{} is new for the function {} in class {}".format(
str(func.__doc__), func.__name__, func.__qualname__.split('.')[0])
return func
这样:
class Test():
@my_decorator
def example(self, examplearg=1):
"""Docstring"""
pass
print(Test().example.__doc__)
将输出:
Docstring is new for the function example in class Test
答案 2 :(得分:1)
事实证明,从类内部访问类属性是不可能的,因为在调用装饰器时尚未执行该类。因此,最初的目标-在类中使用装饰器访问类属性-似乎不可能。
但是,感谢jdehesa向我指出了一种允许使用类装饰器访问类属性的变通方法,这里为Can a Python decorator of an instance method access the class?。
我能够使用类装饰器使用类属性来更改特定方法的文档字符串,如下所示:
def class_decorator(cls):
for name, method in cls.__dict__.items():
if name == 'example':
# do something with the method
method.__doc__ = "{} is new for function {} in class {}".format(method.__doc__, name, cls.__name__)
# Note that other class attributes such as cls.__base__
# can also be accessed in this way
return cls
@class_decorator
class Test():
def example(self, examplearg=1):
"""Docstring"""
print(Test().example.__doc__)
# Returns "Docstring is new for function example in class Test"