我正在尝试使用列表来引用一系列描述符但没有成功。有一个_b
由外部库 () 定义的对象 () 列表class A
,我想通过描述符 () 访问这些对象 ( class Descriptor
)。在下面的示例中,b
分配了对描述符的引用列表,但是当列表的任何项目被分配一个值时,对描述符的引用被该值覆盖,而不是将该值传递给描述符。即使在阅读了几篇关于描述符的参考资料和文章之后,我显然还是错过了描述符的基本行为。
class Descriptor(object):
def __init__(self, varname):
self.varname = varname
pass
def __get__(self, instance, owner):
print('get', self.varname)
#return getattr(getattr(instance, self.varname),"get")()
return instance.__dict__[self.varname].get()
def __set__(self, instance, value):
print('set', self.varname)
#getattr(getattr(instance, self.varname),"set")(value)
instance.__dict__[self.varname].set(value)
class A(object):
def __init__(self, value=None):
self.value = value
def get(self):
return self.value
def set(self, value):
self.value = value
class C(object):
print "root"
a = Descriptor('_a')
b = [Descriptor('_b[x]') for x in range(5)]
def __init__(self, val):
print "init"
self._a = A()
self.a = val
self._b = [A() for x in range(5)]
self.b[0] = 1
c = C(3)
d = C(4)
print c._a.get()
print c.a
print d._a.get()
print d.a
print c.b[0]
在我的实际程序中,外部库是一个 gui 库,我想对其进行抽象,以便可以轻松地交换不同的接口。gui 中的几个视图包含与程序中的列表相对应的输入框列(每列最多 40 个)。
此外,这是访问传递给描述符的实例对象的成员函数的首选方法:getattr
或__dict__
. __dict__
看起来更干净,但我不知道使用它是否有任何框架或可用性问题。
对所提出的问题的任何帮助或满足我在程序中的需求的其他方法的建议,我们将不胜感激。谢谢。
根据millimoose 的建议,以下类似列表的课程似乎满足了我的需求。除了在类根中定义描述符而在类中定义“列表描述符”__init__
以及在初始化时必须将类作为参数提供之外,此方法是否存在任何缺陷?需要添加其他列表功能,需要添加负索引等特殊索引行为。
class DescriptorList(object):
def __init__(self, owner, varname):
self.owner = owner
self.varname = varname
def __getitem__(self, index):
print('getitem', self.varname, index)
return getattr(getattr(self.owner, self.varname)[index],"get")()
def __setitem__(self, index, value):
print('setitem', self.varname, index)
getattr(getattr(self.owner, self.varname)[index],"set")(value)
class C(object):
a = Descriptor('_a')
def __init__(self, val):
self._a = A()
self.a = val
self._b = [A() for x in range(5)]
self.b = DescriptorList(self, '_b')
for i in range(5):
self.b[i] = i
c = C(3)
print [c.b[i] for i in range(5)]
此外,通过DescriptorList
在 中实例C.__init__
化,可以简化代码,以便DescriptorList
使用对象本身而不是对象的名称。这种方法有什么优点或缺点吗?
class DescriptorList(object):
def __init__(self, var):
self.var = var
def __getitem__(self, index):
print('get', self.var, index)
return self.var[index].get()
def __setitem__(self, index, value):
print('set', self.var, index)
self.var[index].set(value)
class C(object):
a = Descriptor('_a')
def __init__(self, val):
self._a = A()
self.a = val
self._b = [A() for x in range(5)]
self.b = DescriptorList(self._b)
for i in range(5):
self.b[i] = i
为什么__get__
和的__set__
处理方式与__getitem__
和不同__setitem__
?