使用__setattr__& __getattr__具有属性

时间:2015-06-18 10:31:14

标签: python overloading

我试图与win32com.client进行更多的pythonic交互以供我自己使用,所以我可以做以下事情:

with Presentation(close=True) as P:
        table = P[0].tables[0]
        table.cells.Shape.TextFrame.TextRange.Text= 'hello'

我设法通过重载__getattr____setattr__来实现上述工作(非常满意)。

我希望将powerpoint表作为数组而不是线性对象进行交互,因此我创建了CellRange对象

这是来自tables.py,它处理win32com.client表的数组视图。

from itertools import product
import numpy as np
from win32com.client import pywintypes

ALIGN_LABELS = 'bottom bottom_base middle top top_base mixed'.split()
ALIGN_LABELS_N = {k: i for i, k in enumerate(ALIGN_LABELS)}

class Win32Interface(object):
    def __init__(self, win32_object):
        super(Win32Interface, self).__setattr__('win32_object', win32_object)

    def __setattr__(self, k, v):
        setattr(self.win32_object, k, v)

    def __getattr__(self, v):
        return getattr(self.win32_object, v)


class Cell(Win32Interface):
    def __repr__(self):
        return self.Shape.TextFrame.TextRange.Text

    @property
    def text(self):
        return self.Shape.TextFrame.TextRange.Text

    @text.setter
    def text(self, v):
        setattr(self.Shape.TextFrame.TextRange, 'Text', v)


class CellRange(object):
    def __init__(self, cell_array):
        super(CellRange, self).__init__()
        super(CellRange, self).__setattr__('cell_array', cell_array)

    def _apply_map(self, f):
        func = np.vectorize(f)
        return func(self.cell_array)

    def __getattr__(self, k):
        try:
            arr = self._apply_map(lambda x: getattr(x, k))
            return CellRange(arr)
        except (AttributeError, pywintypes.com_error):
            return getattr(self.cell_array, k)

    def __setattr__(self, k, v):
        if hasattr(v, 'shape'):
            assert self.shape == v.shape, 'mismatched shape'
            for cell, value in zip(self.cell_array.ravel(), v.ravel()):
                cell.__setattr__(k, value)
        else:
            self._apply_map(lambda x: setattr(x, k, v))

    def __repr__(self):
        return self.cell_array.__repr__()

暂时忽略Table对象,我想知道原因

cell_range = CellRange(cell_array)
    cell_range.text = 'hello'

引发cannot be set错误。上面调用__setattr__然后调用_apply_map来设置数组的每个元素,这会调用Cell.__setattr__。为什么我可以print cell_range.text而不是cell_range.text = 'hello'

1 个答案:

答案 0 :(得分:0)

我发布后大约10分钟偶然发现了解决方案!

答案是使用Object的{​​{1}}代替__setattr__

如此明显!

Win32Interface