python - mixins 是跨不同实体类型存储多个属性的正确选择吗?
问题描述
我目前正在构建一个系统,该系统将跨多个来源聚合帖子。这些来源几乎没有共同的属性——例如,所有来源的唯一共同点是帖子包含文本:
class Post:
def __init__(self, text=None):
self.text = text
def persist(self):
row_id = FoobarDB.insert('post', text=self.text).row_id
id = row_id
for superclass in type(self).mro():
try:
super(superclass, self).persist(id)
except AttributeError: pass
return id
@classmethod
def load(cls, id):
post_text = FoobarDB.select('post', row_id=id).text
post = cls(post_text)
for superclass in cls.mro():
try:
super(superclass, post).load(id)
except AttributeError: pass
return post
不同的来源有不同的特征:一些有标签,一些有标题,一些有赞成票和反对票,等等。我正在考虑使用 mixins 来表示所有这些,所以Post
专门用于不同来源的子类将继承Post
自所有适用于该来源的 mixin:
class TwitterPost(Post, HasAuthor, HasScore): ...
class StackExchangePost(Post, HasAuthor, HasScore, HasTitle, HasTags, HasComments): ...
class XkcdPost(Post, HasTitle, HasImage): ...
class RedditPost(Post, HasTitle, HasScore, HasImage, HasComments): ...
这种方法的问题在于,我最终会得到许多重复的 mixin 声明,据我所知,如果没有技巧,这些声明是无法优化的eval
:
class HasAuthor:
@property
def author(self):
try: return self._author
except AttributeError: return None
@author.setter
def set_author(self, value): self._author = value
def persist(self, id):
FoobarDB.insert('author', post_id=id, author=self.author)
def load(self, id):
self.author = FoobarDB.select('author', post_id=id).author
class HasImage:
@property
def image_url(self):
try: return self._image_url
except AttributeError: return None
@image_url.setter
def set_image(self, value): self._image_url = value
def persist(self, id):
FoobarDB.insert('image', post_id=id, image_url=self.image_url)
def load(self, id):
self.image_url = FoobarDB.select('image', post_id=id).image_url
这段代码重复向我表明,mixin 在这里不是正确的选择,或者至少不应该以这种方式使用它们。有没有更好的方法来表示具有一些共同属性但许多属性不同的多个类?
另一个限制是我不知道不同的帖子有什么属性。我需要能够添加新的属性类型以适应新的帖子类型,而不必在基Post
类中更改太多代码。(事实上,我认为这种方法可行的原因之一是,Post
如果数据后端是关系数据库,它会自动将实体拆分为跨不同表的许多行。)
解决方案
推荐阅读
- ios - 根据选择将 UITableView 滚动到某个 indexPath
- node.js - Material-UI Migration Helper: codemod-script?
- reactjs - react-select background color issues
- javascript - 使用会话变量更改文件名
- javascript - Bing map pushpin click event handler applies only last one
- spring - Return type of JPA Repository 'getOne(id)' Method
- angular - checkbox change issue with model value in edge browser
- jasperserver - 如何在每分钟内重复重新加载 jasper 报告
- python-3.x - 安装张量流问题
- angular - Angular 6 - 使用 ngFor 在 div 上使用 onmouseover 更改类