簡體   English   中英

在Python中重載運算符__add__時避免循環依賴

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM