如何重写哪个类具有许多@property的python代码?

时间:2018-11-08 08:46:13

标签: python python-3.x class

我编写的类中包含许多@property,并且 Python Cookbook 提示这是错误的代码。我决定重写代码以删除这些@property,这是 Python Cookbook 中的示例,该示例显示了如何在不使用@property且仍然具有setter, getter的情况下重写类。

class Integer(object):
    def __init__(self, name):
        self.name = name

    def __get__(self, instance, owner):
        if instance is None:
            return self
        else:
            return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not isinstance(value, int):
            raise TypeError('int expected')
        instance.__dict__[self.name] = value

    def __delete__(self, instance):
        del instance.__dict__[self.name]

class Point(object):
    x = Integer('x')
    y = Integer('y')

    def __init__(self, x, y):
        self.x = x
        self.y = y

在这里,我显示代码之前
总之,我的代码将使用python-docx库在MS-Word中设置文本格式,因此您可以看到我需要通过类似{的代码来应用文本格式(粗体,斜体...)由self._run.bold = value设置self._bold时,{1}}。这意味着我只需要设置更多,就可以将属性值设置为与 Python Cookbook 示例相比。

self._bold = value

这是我的代码 后重写。您可以看到我必须编写class CellParagraph(object): def __init__(self, cell, text=None): self._cell = cell self._style = 'Default Paragraph Font' self._paragraph = self._cell.paragraphs[0] self._run = self._paragraph.add_run(text, style=self._style) self._font_name = None self._bold = False self._italic = False ...many of them... @property def bold(self): return self._bold @bold.setter def bold(self, value): self._run.bold = value self._bold = value @property def italic(self): return self._italic @italic.setter def italic(self, value): self._run.italic = value self._italic = value ...many of them... 方法才能将这些格式应用于MS-Word,每次设置某种文本格式时,我都必须使用refresh
我的问题:如何将类似案例的代码重写为 Python Cookbook 示例样式?
任何讨论将不胜感激。

refresh()

1 个答案:

答案 0 :(得分:0)

如果您需要同时设置_property_run._property

编辑:

  

我注意到一个错误,并且TextProperty的状态已共享   在不同的段落之间。因此,需要在   CellParagraph而非TextProperty

     

使用setattr(instance, f"_{self.name}", value)和变体   动态地在段落上生成_bold属性。所以拿   小心不要自己使用其中任何一个

您可以使用setattr来使用食谱中的Descriptor模式来更改CellParagraph._run上的值

class TextProperty(object):
    def __init__(self, name, property_type=None):
        self.name = name
        self.property_type = property_type

    def __get__(self, instance, owner):
        return getattr(instance, f"_{self.name}")

    def __set__(self, instance, value):
        if self.property_type is not None and not isinstance(
            value, self.property_type
        ):
            raise TypeError(f"{self.name} needs to be of type: {self.property_type}.")
        print(f"setting {self.name} to {value}")
        setattr(instance, f"_{self.name}", value)
        setattr(instance._run, self.name, value)

    def __delete__(self, instance):
        del instance.__dict__[self.name]
        delattr(instance, f"_{self.name}")
        delattr(instance._run, self.name)

    def __repr__(self):
        return "TextProperty("\
                    f"name={self.name}, "\
                    f"value={self.value}, "\
                    f"property_type={self.property_type}"\
                ")"

然后我使用了一个虚拟的Run类来充当paragraph._run属性

class Run:
    def __init__(self):
        self.bold = None
        self.italic = None

    def __repr__(self):
        return f"Run(bold={self.bold}, italic={self.italic})"

您可以在CellParagraph类(简化)中使用以下代码:

class CellParagraph(object):
    bold = TextProperty("bold", bool)
    italic = TextProperty("italic")

    def __init__(self, bold=False, italic=False):
        self._run = Run()
        self.bold = bold
        self.italic = italic

    def __repr__(self):
        return f"CellParagraph(bold={self.bold}, italic={self.italic})"

然后创建一些段落来测试此行为:

paragraph_1 = CellParagraph()
paragraph_2 = CellParagraph(italic=True)
setting bold to False
setting italic to False
setting bold to False
setting italic to True
(paragraph_1, paragraph_1._run), (paragraph_2, paragraph_2._run)
((CellParagraph(bold=False, italic=False), Run(bold=False, italic=False)),
 (CellParagraph(bold=False, italic=True), Run(bold=False, italic=True)))
paragraph_1.bold = True
paragraph_1, paragraph_1._run
setting bold to True

(CellParagraph(bold=True, italic=False), Run(bold=True, italic=False))
paragraph_1.italic = 'abc'
paragraph_1.bold = 'abc'
setting italic to abc
TypeError: bold needs to be of type: <class 'bool'>.

如果在段落和paragraph._run上都需要更改很多属性,则使用此模式可以节省一些样板,但是使用@property不太明确