【发布时间】:2016-05-10 16:42:32
【问题描述】:
我有一个类有很多非常相似的属性:
class myClass(object):
def compute_foo(self):
return 3
def compute_bar(self):
return 4
@property
def foo(self):
try:
return self._foo
except AttributeError:
self._foo = self.compute_foo()
return self._foo
@property
def bar(self):
try:
return self._bar
except AttributeError:
self._bar = self.compute_bar()
return self._bar
...
所以我想我会写一个装饰器来完成属性定义工作。
class myDecorator(property):
def __init__(self, func, prop_name):
self.func = func
self.prop_name = prop_name
self.internal_prop_name = '_' + prop_name
def fget(self, obj):
try:
return obj.__getattribute__(self.internal_prop_name)
except AttributeError:
obj.__setattr__(self.internal_prop_name, self.func(obj))
return obj.__getattribute__(self.internal_prop_name)
def __get__(self, obj, objtype=None):
if obj is None:
return self
if self.func is None:
raise AttributeError("unreadable attribute")
return self.fget(obj)
class myClass(object):
def compute_foo(self):
return 3
foo = myDecorator(compute_foo, 'foo')
def compute_bar(self):
return 4
bar = myDecorator(compute_bar, 'bar')
这很好用,但是当我想使用 @myDecorator('foo') 语法时,它变得更加复杂,无法确定 __call__ 方法应该返回什么以及如何将属性附加到它的类。
目前我有:
class myDecorator(object):
def __init__(self, prop_name):
self.prop_name = prop_name
self.internal_prop_name = '_' + prop_name
def __call__(self, func):
self.func = func
return #???
def fget(self, obj):
try:
return obj.__getattribute__(self.internal_prop_name)
except AttributeError:
obj.__setattr__(self.internal_prop_name, self.func(obj))
return obj.__getattribute__(self.internal_prop_name)
def __get__(self, obj, objtype=None):
if obj is None:
return self
if self.func is None:
raise AttributeError("unreadable attribute")
return self.fget(obj)
class myClass(object):
@myDecorator('foo')
def compute_foo(self):
return 3
c = myClass()
print(c.foo)
它返回:AttributeError: 'myClass' object has no attribute 'foo'
【问题讨论】:
-
我看的越多,我就越相信我想要达到的目标是疯狂的......
myDecorator可以知道myClass是为它添加属性吗? -
直到
__get__()等被调用。 -
谢谢。如果我理解正确,那么在这种情况下使用
@myDecorator('foo')语法毫无意义。类属性foo应在类定义中定义,myDecorator应称为myCustomProperty? -
您不必将装饰函数作为参数传递给装饰器。这可以通过使用包装器来解决。
标签: python python-3.x decorator