27

(itertools.chain と混同しないでください)

私は以下を読んでいました: http://en.wikipedia.org/wiki/Method_chaining

私の質問は: Python でメソッドチェーンを実装する最良の方法は何ですか?

これが私の試みです:

class chain():
    def __init__(self, my_object):
        self.o = my_object

    def __getattr__(self, attr):
        x = getattr(self.o, attr)
        if hasattr(x, '__call__'):
            method = x
            return lambda *args: self if method(*args) is None else method(*args)
        else:
            prop = x
            return prop

list_ = chain([1, 2, 3, 0])
print list_.extend([9, 5]).sort().reverse()

"""
C:\Python27\python.exe C:/Users/Robert/PycharmProjects/contests/sof.py
[9, 5, 3, 2, 1, 0]
"""

1 つの問題は、呼び出しがmethod(*args)変更さself.oれても返されない場合Noneです。(その後、返すselfか、返すものをmethod(*args)返す必要があります)。

チェーンを実装するより良い方法はありますか? おそらく多くの方法があります。

メソッドが常に返されると仮定するだけNoneでよいので、常に返される可能性がありself.oますか?

4

5 に答える 5

22

Pipeあなたの質問への答えになるかもしれない非常に便利なライブラリがあります。例えば::

seq = fib() | take_while(lambda x: x < 1000000) \
            | where(lambda x: x % 2) \
            | select(lambda x: x * x) \
            | sum()
于 2012-08-29T07:49:53.893 に答える
16

メソッドが直接変更せずに、変更されたバージョンを返すように、純粋な関数のみを使用する場合に可能です。インスタンスself.dataを返す必要もあります。Chainable

リストでコレクションのパイプライン処理を使用する例を次に示します。

import itertools

try:
    import builtins
except ImportError:
    import __builtin__ as builtins


class Chainable(object):
    def __init__(self, data, method=None):
        self.data = data
        self.method = method

    def __getattr__(self, name):
        try:
            method = getattr(self.data, name)
        except AttributeError:
            try:
                method = getattr(builtins, name)
            except AttributeError:
                method = getattr(itertools, name)

        return Chainable(self.data, method)

    def __call__(self, *args, **kwargs):
        try:
            return Chainable(list(self.method(self.data, *args, **kwargs)))
        except TypeError:
            return Chainable(list(self.method(args[0], self.data, **kwargs)))

次のように使用します。

chainable_list = Chainable([3, 1, 2, 0])
(chainable_list
    .chain([11,8,6,7,9,4,5])
    .sorted()
    .reversed()
    .ifilter(lambda x: x%2)
    .islice(3)
    .data)
>> [11, 9, 7]

OP ではなく、を.chain参照することに注意してください。itertools.chainchain

于 2015-01-30T09:13:10.127 に答える
4

特定のメソッドがどのように機能するかを知らなければ、メソッドが返す値の種類とその理由を知ることができないため、任意のオブジェクトの任意のメソッドをチェーンできるようにする一般的な方法はありません。メソッドはNone何らかの理由で戻る可能性があります。メソッドがオブジェクトを変更したことを常に意味するわけではありません。同様に、値を返すメソッドは、連鎖可能な値を返さない可能性があります。のようなメソッドをチェーンする方法はありませんlist.index:fakeList.index(1).sort()動作する可能性はあまりありません。なぜなら、indexそれは数値を返すことであり、その数値は何かを意味し、元のオブジェクトをチェーンするためだけに無視することはできないからです。

特定の特定のメソッド (sort や remove など) をチェーンするために Python の組み込み型をいじっているだけの場合は、それらの特定のメソッドを (ラッパー クラスでオーバーライドすることによって) 明示的にラップすることをお勧めします。一般的な機構付き__getattr__

于 2012-08-29T07:40:11.563 に答える