2016-11-16 7 views
1

私は、メソッドチェインのように(例えば、Fluent interface)、ユーザーの観点から扱いやすいオブジェクト指向のデータ構造を設計しています。ただし、各変更はオブジェクト上で一時的にのみ実行する必要があります。そのチェーン内で、そのチェーンを超えないでください。 .add()numberから永久変更を行い、この場合メソッドチェーン中にオブジェクトを一時的に変更する

class C: 
    def __init__(self, num): 
     self.sum = num 

    def add(self, num=0): 
     self.sum += num 
     return self 

number = C(23) 
number.add(7).add(12).sum 
# 42 
number.sum 
# 42 (but I expect: 23) 


ここで意図したとおりない作業を行う簡略化した例です。ただし、恒久的な変更は、次のように可能なはずです:一時的範囲で

# This is the only way how a user should make permanent changes: 
number = number.add(4).add(12) 

は、私はチェーンが終了した後、バックnumberの古いバージョンを取得する方法を探しています。でも、

class C2: 
    def __init__(self, num): 
     self.sum = num 

    def add(self, num=0): 
     self2 = C2(self.sum) # or equivalently: self2 = copy.deepcopy(self) 
     self2.sum += num 
     return self2 

number = C2(23) 
number.add(7).add(12).sum 
# 42 
number.sum 
# 23 

は、しかし、私が働いているとactuallクラスとオブジェクトは、データの膨大な量を含む、属性メソッド、および:絶望の端に、私は、「インスタンスの複製」のような醜いソリューションを考えることができますサブクラス。したがって、醜いコードが含まれているという事実の他に、すべてのメソッドでインスタンスをコピーしないようにする必要があります。

この問題を解決する方法はありますか?チェーンの最初の要素で1回だけコピーを作成する(サイレントに)?またはチェーンの最後に加えられた変更を破棄することによって、

:Anはソリューションは、ユーザーインターフェイスを悩ませずに、必要な操作 内部、すなわちを実行する必要が受け入れ (現実世界「変化」は数字だけを追加する以外の多くの異なる、通勤方法を含むことに注意してください)

# These are NOT accepted solutions: 
number.copy().add(4).add(12) 
number.add(4).add(12).undo() 

自己複製以外の直接的な解決策がない場合は、次のような質問があります。コードを読みやすくし、メモリ使用量を低く抑える最も洗練された方法は何ですか?たとえば、自己複製機能によってすべてのクラスメソッドをデコレートしますか?

+0

私は、オブジェクトが "一時的な範囲"の終わりを自動的に検出する可能性があるとは思わない - おそらくあなた自身のPythonベースの言語を書くことを除いては... FWIW、すべての "流暢なインターフェイス私が今までに見た実装は、オブジェクトを所定の場所に変更したり、コピーを返すことができます。 –

答えて

1

の代わりにあなたがメソッドを呼び出したオブジェクトをmodyfing、修正されたコピーを返す:この記事のコメントを参照してください、この溶液中での取り扱いメモリの詳細については

class C: 
    def __init__(self, num): 
     self.sum = num 

    def add(self, num=0): 
     return C(self.sum + num) 

number = C(23) 
assert number.add(7).add(12).sum == 42 
assert number.sum == 23 

を。このソリューションは、問題を解決するための標準的な方法です。

+0

申し訳ありませんが、この解決策は既に質問に記載されています。 – Martin

+0

それから、これは標準的な習慣であり、汚れたハックではないことを伝えています。 –

+0

私はそれが多くのappliationsのための標準であることを知っています。しかし、それはまた、大規模なインスタンスのために推奨される(または唯一の)戦略ですか?私はそれが劇的にメモリ使用量を増加させるのではないかと思います:Sまたはチェーンが終了すると、Pythonは自動的にすべてのインスタンスを削除しますか? – Martin

関連する問題