我编写的类中包含许多@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()
答案 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
不太明确