注:Python 版本为 2.7
问题
我希望将{描述符类的层次结构}集成到{小部件类的层次结构}中,并且重写描述符行为必须像定义嵌套派生类一样简单。例子:
class A(object):
class width(Attribute):
def changed(self, obj, value, old):
print 'A.width changed:', value
class B(A):
class width(A.width):
def changed(self, obj, value, old):
super(B.width, self).changed(obj, value, old)
print 'B.width changed:', value
B().width = 10
# must print:
# A.width.changed: 10
# B.width.changed: 10
这是我的自定义描述符类:
class Attribute(object):
def __init__(self):
if not hasattr(self, '_name'):
self._name = self.__class__.__name__
def __get__(self, obj, cls):
if obj is None:
print 'Attribute getter (class):', cls
return self
print 'Attribute getter (class, inst):', (cls, obj)
print 'Attribute getter returning:', self.get(obj)
return self.get(obj)
def __set__(self, obj, value):
print 'Attribute setter (inst, value):', (obj, value)
self.set(obj, value)
def get(self, obj):
try:
return obj.__dict__[self._name]
except KeyError:
raise AttributeError("attribute '%s' referenced before assigment" % (self._name))
def set(self, obj, value):
try:
old = obj.__dict__[self._name]
except KeyError:
obj.__dict__[self._name] = value
self.changed(obj, value, None)
else:
obj.__dict__[self._name] = value
if old != value:
self.changed(obj, value, old)
def changed(self, obj, value, old):
pass
问题是Python 不想使用__get__
and __set__
,而它们是类的属性。从这个测试中可以看出:
# `A` and `B` were defined above
A.width_ = A.width()
B.width_ = B.width()
to_test = (
# good:
'Aw_ = A.width_',
'Bw_ = B.width_',
'B().width_ = 10',
# silent:
'Aw = A.width',
'Bw = B.width',
'B().width = 10',
)
for expr in to_test:
print "Testing:", expr
exec expr
所以,我的Attribute
作品只有在实例化时才起作用。
我已经尝试过的
装饰
__get__
并__set__
使用staticmethod
或classmethod
。静音部分没有变化。好的部分失败了:方法不可调用。笏。从外部添加
__get__
和__set__
到类,作为绑定到的方法。没有改变。Attribute
Attribute
代码:
# `__get__` was renamed to `_unbound__get__`
Attribute.__get__ = Attribute._unbound__get__.__get__(Attribute, Attribute.__class__)
# `__set__` was renamed to `_unbound__set__`
Attribute.__set__ = Attribute._unbound__set__.__get__(Attribute, Attribute.__class__)
- 使用实例化的描述符。这种方法需要 2 个符号:一个用于描述符(子)类,一个用于描述符。它还需要在子类化之后实例化描述符。
代码:
class B(A):
class Width(A.width):
def changed(self, obj, value, old):
super(B.width, self).changed(obj, value, old)
print 'B.width.changed:', value
B.width = B.Width()
更多背景。
我有越来越多的小部件层次结构,其中必须跟踪某些属性以进行更改,并且可以在子类中扩展对更改的响应。所以我正在尝试使用模块化机器创建自动化方法。因为在实际小部件中保留每个属性的相关变量和方法只是令人讨厌的混乱。
问题
是否有解决方法来满足我的需求?还是我做错了什么?