你的后一个例子对我的作品,但你的主要问题在于,你没有在
@catch_assertionerror
@name.setter
def name(self, value):
assert isinstance(value, str), "This value should be a string"
self._name = name
但descriptor
包装与catch_assertionerror
功能。更糟糕的是,你会返回一个函数,而不是包装原始文件的新描述符。现在,当您分配给name
属性时,只需使用指定的值替换包装函数即可。
一步一步,使用原来的类定义:
class X(object):
@property
def name(self):
return self._name
@catch_assertionerror
@name.setter
def name(self, value):
assert isinstance(value, str), "This value should be a string"
self._name = value
>>> x = X()
>>> x.name
<unbound method X.handle_problems>
>>> x.__dict__
{}
>>> x.name = 2
>>> x.name
2
>>> x.__dict__
{'name': 2}
你必须做什么是包裹方法函数来代替,然后把它传递给描述符处理装饰:
class X(object):
@property
def name(self):
return self._name
@name.setter
@catch_assertionerror
def name(self, value):
assert isinstance(value, str), "This value should be a string"
self._name = value
等:
>>> x = X()
>>> x.name
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in name
AttributeError: 'X' object has no attribute '_name'
>>> x.name = 2
error caught
>>> x.name = "asdf"
>>> x.name
'asdf'
将来考虑使用functools.wraps
和functools.update_wrapper
。没有他们你的类和函数更难检查,因为你的包装将隐藏原始:
>>> @catch_assertionerror
... def this_name_should_show(): pass
...
>>> this_name_should_show
<function handle_problems at 0x7fd3d69e22a8>
定义你的装饰是这样的:
def catch_assertionerror(function):
@wraps(function)
def handle_problems(*args, **kwargs):
...
return handle_problems
将保留原有功能的信息:
>>> @catch_assertionerror
... def this_name_should_show(): pass
...
>>> this_name_should_show
<function this_name_should_show at 0x7fd3d69e21b8>
它也会向您表明您的情况存在问题:
# When trying to define the class
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in X
File "<stdin>", line 2, in catch_assertionerror
File "/usr/lib/python2.7/functools.py", line 33, in update_wrapper
setattr(wrapper, attr, getattr(wrapped, attr))
AttributeError: 'property' object has no attribute '__module__'
您没有在代码中显示调用函数的位置 – hspandher
我刚刚在交互式Python会话中尝试了“更简单的示例”,并且它按预期工作。你如何运行这些代码? – SpoonMeiser