在不编辑原始类的情况下包装get和set属性方法

时间:2017-02-25 20:14:14

标签: python oop wrapper

我正在尝试在获取或/和设置属性之前或之后进行一些操作。 这段代码的棘手部分是我无法修改原始类。

类的方法没问题,它按预期工作。但我找不到处理财产的方法。我有一个错误:

TypeError: readonly attribute

如果有人可以帮我找到正确的方向......

这是我无法修改的课程:

class Test(object):
    def __init__(self):
        super(Test, self).__init__()
        self._param = None
        self._controler = None
        self._message = None
    @property
    def param(self):
        return self._param
    @param.setter
    def param(self, param):
        self._param = param

    @property
    def controler(self):
        return self._controler

    def message(self):
        print('message')

这是我为编写工作而编写的包装器,这将是我的模块的一部分

def add_things_before_and_after(function_to_enhance):
    def new_wrapper(self):
        print("Before function execution") 
        function_to_enhance(self)
        print("After function execution")
    return new_wrapper

这是要编写以使用包装器并实现类

的代码
# this one works as expected
Test.message = add_things_before_and_after(Test.message)
# these two lines does not work
Test.param.fget = add_things_before_and_after(Test.param.fget)
Test.controler.fget = add_things_before_and_after(Test.controler.fget)

test = Test()
test.message()
test.param = 1
print(test.param)
print(test.controler)

1 个答案:

答案 0 :(得分:2)

可以通过使用新属性覆盖整个param属性来实现。但是,必须修复装饰器函数以返回包装函数的值。

functools.wraps是保存包装函数的属性(名称,doc等)的好方法。

from functools import wraps

def add_things_before_and_after(function_to_enhance):
    @wraps(function_to_enhance)
    def new_wrapper(self):
        print("Before function execution")
        r = function_to_enhance(self)
        print("After function execution")
        return r
    return new_wrapper

# this one works as expected
Test.message = add_things_before_and_after(Test.message)

# these two lines should work
Test.param = property(add_things_before_and_after(Test.param.fget), Test.param.fset)
Test.controler = property(add_things_before_and_after(Test.controler.fget), Test.controler.fset)

test = Test()
test.message()
test.param = 1
print(test.param)
print(test.controler)

# ==Output==
#
# Before function execution
# message
# After function execution
# Before function execution
# After function execution
# 1
# Before function execution
# After function execution
# None