[英]Avoiding circular dependency when overloading operator __add__ in Python
我有一個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:
我最終刪除了依賴項,並在不使__add__
重載的情況下離開了Message類。
但是。。。我一直在考慮這個問題,對我來說,使用語法collection_of_objects = object1 + object2是很有意義的。 它表達了“我有一個蘋果,然后又買了一個蘋果,所以現在我有了兩個蘋果的集合”的概念。 也許我們應該認為對象是對象數量為1的集合的特例? 在這種情況下,對象應該繼承“可列出”類(或由其修飾)...
無論如何,謝謝大家的回答! 我將開放這個問題,看看是否會引起進一步的辯論;)
我會避免使用MessageCollection並嘗試使用常規的python列表。 它們非常強大,在我看來,有99%的時間比嘗試構建新的集合類型要好。
集合是通用的,對內容不承擔任何責任,而對容器不承擔任何責任,這是一個非常強大的抽象概念。 恕我直言,除非有非常有說服力的理由,否則您應該真正避免搞混。
如果確實需要,則需要一個MessageCollection類。 然后在__add__
運算符。 這意味着您將MessageCollection構建為空,並可以使用+將其添加(擴展)。 這類似於列表語法。
停止寫課。 真的 。 這是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
進行的所有切片,迭代,操作和更改都已經可用,因為messages
是一個 list。 MessageCollection可能是。 而且,如果必須使用messages.append(m3)
確實讓您感到困惑,那么您仍然可以
messages += m3
內置的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.