【发布时间】:2015-11-02 00:46:10
【问题描述】:
背景
我需要一个类似于namedtuple 的类型,但具有可更改 字段。 namedlist 的行为如下:
Something = namedlist('Something', ['a', 'b'])
st = Something(123, 456)
print st # Something(a=123, b=456)
a, b = st
print a, b, st.a, st.b # 123 456 123 456
st.a = 777
print st # Something(a=777, b=456)
st.b = 888
print st # Something(a=777, b=888)
在了解了描述符 here 和 there 之后,我得到了以下代码,如上所述:
class IndexAccessor(object):
def __init__(self, index):
self.index = index
def __get__(self, instance, owner):
return list.__getitem__(instance, self.index)
def __set__(self, instance, value):
list.__setitem__(instance, self.index, value)
def namedlist(classname, fields):
def init(self, *args):
list.__init__(self, args)
def repr(self):
return '%s(%s)' % (self.__class__.__name__, ', '.join(['%s=%s' % (k,list.__getitem__(self, i)) for i, k in enumerate(self._fields)]))
attrs = {'_fields': tuple(fields),
'__init__': init,
'__repr__': repr
}
for index, field in enumerate(fields):
attrs[field] = IndexAccessor(index)
return type(classname, (list,), attrs)
问题
IndexAccessor 类对我来说有点像样板,所以我想知道是否可以改进代码以避免它。
我试图用这个替换 for index, field in enumerate(fields) 循环
for index, field in enumerate(fields):
def get(self):
return list.__getitem__(self, index)
def set(self, v):
list.__setitem__(self, index, v)
attrs[field] = property(get, set, None, 'Property "%s" mapped to item %d' % (field, index))
...但这导致print a, b, st.a, st.b 语句生成123 456 456 456 而不是123 456 123 456,我怀疑这与index 没有按要求工作有关。
奖励积分对于答案也可以提供简洁的代码以允许在构造函数中进行基于名称的分配,如
Something = namedlist('Something', ['a', 'b'])
st = Something(a=123, b=456)
【问题讨论】:
-
采用
namedtuple本身所做的方法,您在namedlist中创建一个类模板字符串,将给定字段应用于模板,然后exec生成的字符串生成实际的类。 -
如果这是您认为可以改进的工作代码,请参阅Code Review。如果不是,请澄清问题。
-
@jonrsharpe 我不同意,因为如果
namedlist的工作版本被删除,这个问题仍然有意义。 -
@jonrsharpe:后台的代码确实可以工作,除了构造中基于名称的分配。我还可以删除
IndexAccessor类并替换问题中描述的for循环,这会破坏代码。这比将问题移至代码审查更可取吗?
标签: python python-2.7 properties namedtuple python-descriptors