拦截python中的属性

时间:2013-10-09 00:08:36

标签: python attributes

我无法弄清楚要搜索的内容,所以如果它已经在那里,我会提前道歉,并乐意将搜索引用带到其他地方。

一些背景知识:我正在研究a python Excel library的一些额外功能,我希望能够做的一件事是在一次调用中将样式应用于一系列单元格。现在,我们的代码允许我们像ws[1][1].font.bold = True那样做粗体单元格A1。我们还有一个范围运算符,允许我们执行ws.range("A1:B2").value = 1之类的操作,将该范围内的所有值设置为1。

我现在要做的是添加ws.range("A1:B2").font.bold = True的能力,但我无法弄清楚如何做。 range("A1:B2")是一个没有明确引用单元格的对象(只是保存在空间上的两个角落),但没有显式地具有.font.value属性,而是通过一个@property装饰器可以适当地应用。

问题是,如果我添加一个@property装饰器来创建一个font属性,我可以返回一个新的字体对象,但是我无法在{{1}之后获得这个字体对象已修改属性以将其应用于范围内的所有单元格。

我原以为我可以bold字体,然后在yield之后添加应用逻辑,但这不起作用,因为yield返回一个生成器。我能想到的唯一另一个想法是创建一个显式yield对象,然后在.font类中覆盖Range来监听更改,但后来我无法弄清楚如何获取需要应用的.font.__setattr__内的原始范围,而无需创建第三个中间类。这不仅看起来很尴尬,而且看起来也非常难以形成。

这样的事情是否可能而不必导致相当深奥的方法?我希望我的解释很清楚,如果它已经在那里,请随时指出我现有的参考 - 我只是不知道要搜索什么。

1 个答案:

答案 0 :(得分:1)

要扩展我的评论,您可以执行以下操作:

class RangeFont(object):

    def __init__(self, range):
        self._range = range

    def __setattr__(self, name, value):
        if name.startswith('_'):
            super(RangeFont, self).__setattr__(name, value)
            return

        for cell in self._range: # assuming a range is iterable
            setattr(cell.font, name, value)


class Range(object):
    @property
    def font(self):
        return RangeFont(self)

上述代码的限制是它不适用于更多级别的属性,也就是说,您无法执行ws.Range(...).font.foo.bar = 123。 (也就是说你可以通过让RangeFont.__getattr__返回一个类似的包装器对象来扩展它。)