我想将描述符动态绑定到类的属性。
例如,我有这个描述符(它只是一个虚拟的例子):
class Item(object):
def __init__(self, filename):
self.filename = filename
def __get__(self, obj=None, objtype=None):
#print '__get__(%s, %s)' % (obj, objtype)
return open(self.filename).read()
def __set__(self, obj, val):
#print '__set__(%s, %s)' % (obj, val)
open(self.filename, 'w').write(str(val))
在我的主容器中,我想动态注册我的描述符。
如果我在班级实例化描述符,那么一切都很有效:
class Container(object):
foo = Item('foo')
bar = Item('bar')
不幸的是,当我尝试使用setattr
动态关联描述符时,我需要为我的类增加更多的复杂性:
class Container(object):
def __init__(self, data):
for attr in data:
super(Container, self).__setattr__(attr, Item(attr))
def __setattr__(self, name, value):
#print '__setattr__(%s, %s)' % (name, value)
attr = super(Container, self).__getattribute__(name)
if hasattr(attr, '__set__'):
attr.__set__(name, value)
else:
super(Container, self).__setattr__(name, value)
def __getattribute__(self, name):
#print '__getattribute__(%s)' % (name)
attr = super(Container, self).__getattribute__(name)
if hasattr(attr, '__get__'):
return attr.__get__(name)
return attr
预期输出为:
>>> c = Container(['foo', 'bar'])
>>> c.foo = 2
>>> c.foo
'2'
是否有一个更简单的解决方案,减少了kludges?
答案 0 :(得分:2)
所以,你的__init__
容器就在那里。你遇到的问题:
super(...).__setattr__
毫无意义,tbh。这个带有描述符的棘手部分(顺便说一下,根据我的经验,当人们开始使用它时,这是一种“默认”障碍)。当您以非动态方式使用描述符
时class Container(object):
foo = Item('foo')
bar = Item('bar')
您在班级范围内设置foo
和bar
- 字面意思是类属性。但是以你的“动态”方式,你是用实例做的。 Idk如果你试图将它设置为类,但如果这是一个意图,super
不会像这样工作。要动态设置附加描述符,您需要将其附加到实例的类(由self
内的__init__
引用)。为此,请访问self.__class__
或type(self)
。所以,您的代码可能看起来像
class Container(object):
def __init__(self, data):
for attr in data:
setattr(type(self), attr, Item(attr))