我有一个Message类和一个MessageCollection类,它显然取决于Message。 我想这样做:
m1 = Message()
m2 = Message()
collection = m1 + m2
isinstance(collection, MessageCollection) # True
问题是我必须在Message类中重载__add__
运算符并在那里创建一个新的MessageCollection实例:
class Message:
def __add__(self, msg_or_collection):
if isinstance(msg_or_collection, Message):
return MessageCollection([self, msg_or_collection])
elif isinstance(msg_or_collection, MessageCollection)
return msg_or_collection.append(self)
raise TypeError("can't add %s to Message" % type(msg_or_collection))
因而产生了丑陋的循环依赖。有什么办法可以避免吗?也许我的设计是错误的,还有其他方法吗?
编辑:
我确实已经超载了MessageCollection' __add__
运算符,所以我可以做
collection1 = MessageCollection()
collection2 = collection1 + m1 + m2.
我只想让它更好......
编辑2:
我最终删除了依赖项并离开了Message类而没有__add__
重载。
然而......我一直在考虑它,对我而言,拥有语法collection_of_objects = object1 + object2是完全合理的。它表达了"我有一个苹果的概念,然后我买了另一个,所以现在我有两个苹果的集合"。也许我们应该想到一个对象是一个集合的特殊情况,其中对象的数量是1?在这种情况下,对象应该从一个" listable"继承(或被装饰)。类...
无论如何,谢谢你们的回答!我将问题保持开放,看是否会产生进一步的争论;)
答案 0 :(得分:2)
我会避免使用MessageCollection并尝试使用常规的python列表。它们非常强大,在我看来99%的时间比尝试构建新的集合类型更好。
集合是通用的,并且在内容不假设其容器的任何内容时不会假设其内容,这是一个非常强大的抽象概念。恕我直言,除非有非常令人信服的理由,否则你应该真的避免搞乱。
如果你真的需要一个MessageCollection类。然后将__add__
运算符放在其上。这意味着您将MessageCollection构建为空,并可以使用+添加(扩展它)。这类似于列表语法。
答案 1 :(得分:0)
停止写课程。 Really。这是Python中常见的反模式,它使许多在Java中学到很多的人和C ++的学习程度较低。部分原因是Java在包含类之外发生了什么。当你有一个没有状态和的课程时,你不会被Java困住,那就忘了上课。
在Java和C ++中,创建集合类更为重要,因为这两种语言都没有列表,集合,序列,字典等。在Java / C ++中,您必须为任何聚类类型编写类,加载库或实例化模板。这增加了想要写一个类的频率:如果我想要一个Message *
的向量,那么我将不得不像你一样做一个:
collection1 = MessageCollection()
m1 = Message()
m2 = Message()
collection2 = collection1 + m1 + m2
class Message:
def __add__(self, msg_or_collection):
if isinstance(msg_or_collection, Message):
return MessageCollection([self, msg_or_collection])
elif isinstance(msg_or_collection, MessageCollection)
return msg_or_collection.append(self)
raise TypeError("can't add %s to Message" % type(msg_or_collection))
但有一些事情可能会好得多。您没有编写的代码没有任何缺陷,更糟糕的是每次使用isinstance
时,您都会增加代码耦合,以便MessageCollection和Message变得缠绕在一起并且不可分割。因此,我们会放弃Message.add
这将删除您非常热衷的+
。但是,除了用于链接消息之外,我们可以指出没有消息收集的行为,我们可以轻松地做到这一点
m1 = Message()
m2 = Message()
messages = [m1, m2]
我们丢失了一个基于多态输入类型的多态返回类型的类方法。我们现在知道messages.append(m3)
的时间复杂度,因为我们对列表非常熟悉,并且我们想要在messages
上进行的所有切片,迭代,操作和更改都已可用,因为{{1} } 是-a 列表; MessageCollection可能是。如果必须使用messages
真的让你筋疲力尽,那么你仍然有
messages.append(m3)
内置。