【发布时间】:2012-09-20 03:05:33
【问题描述】:
在 python 中,我可以通过直接分配给属性或通过调用改变属性状态的方法来改变实例的状态:
foo.thing = 'baz'
或:
foo.thing('baz')
有没有一种很好的方法来创建一个可以接受上述两种形式的类,这些形式可以扩展到大量具有这种行为的属性? (简短地说,我将展示一个我不太喜欢的实现示例。)如果您认为这是一个愚蠢的 API,请告诉我,但也许需要一个更具体的示例。假设我有一个Document 课程。 Document 可以有一个属性 title。然而,title 可能也希望有一些状态(字体、字体大小、对齐方式...),但普通用户可能会很高兴只需将标题设置为字符串并完成它...
实现此目的的一种方法是:
class Title(object):
def __init__(self,text,font='times',size=12):
self.text = text
self.font = font
self.size = size
def __call__(self,*text,**kwargs):
if(text):
self.text = text[0]
for k,v in kwargs.items():
setattr(self,k,v)
def __str__(self):
return '<title font={font}, size={size}>{text}</title>'.format(text=self.text,size=self.size,font=self.font)
class Document(object):
_special_attr = set(['title'])
def __setattr__(self,k,v):
if k in self._special_attr and hasattr(self,k):
getattr(self,k)(v)
else:
object.__setattr__(self,k,v)
def __init__(self,text="",title=""):
self.title = Title(title)
self.text = text
def __str__(self):
return str(self.title)+'<body>'+self.text+'</body>'
现在我可以按如下方式使用它:
doc = Document()
doc.title = "Hello World"
print (str(doc))
doc.title("Goodbye World",font="Helvetica")
print (str(doc))
虽然这个实现看起来有点乱(__special_attr)。也许那是因为这是一个混乱的 API。我不知道。 有没有更好的方法来做到这一点? 还是我在这条路上走得太远了?
我意识到我也可以为此使用 @property,但如果我有多个属性以这种方式运行,那将根本无法很好地扩展——我需要编写每个都有一个 getter 和 setter,哎呀。
【问题讨论】:
-
另外请注意,我的实际用例不涉及标记语言,我只是将其用作更多受众熟悉的示例。 (请不要建议我使用
elementtree或xml.favorite.parser...)
标签: python properties