2

関数のリストを Python にクラス属性として保存した古いコードがあります。これらのリストは、一種のイベント フックとして使用されます。

mapリスト内の各関数を適切な引数で呼び出すために、式を組み合わせてワンライナーを使用しましlambdaた。このような式を使用すると不要なオーバーヘッドが発生するのではないかと心配しています。読みやすさのために、両方を削除して標準の for ループを使用するlambdaことをお勧めします。maplambda

ただし、これを行うためのより良い(より速く読む)ワンライナーはありますか?

例えば:

class Foo:
    """Dummy class demonstrating event hook usage."""
    pre  = [] # list of functions to call before entering loop.
    mid  = [] # list of functions to call inside loop, with value
    post = [] # list of functions to call after loop.
    def __init__(self, verbose=False, send=True):
        """Attach functions when initialising class."""
        self._results = []
        if verbose:
            self.mid.append( self._print )
        self.mid.append( self._store )
        if send:
            self.post.append( self._send )

    def __call__(self, values):

        # call each function in self.pre (no functions there)
        map( lambda fn: fn(), self.pre )

        for val in values:
            # call each function in self.mid, with one passed argument
            map( lambda fn: fn(val), self.mid )

        # call each fn in self.post, with no arguments
        map( lambda fn: fn(), self.post )

    def _print(self, value):
        """Print argument, when verbose=True."""
        print value

    def _store(self, value):
        """Store results"""
        self._results.append(value)

    def _send(self):
        """Send results somewhere"""

# create instance of Foo
foo = Foo(verbose=True)

# equivalent to: foo.__call__( ... )
foo( [1, 2, 3, 4] )

mapこれらのワンライナー呼び出しを記述するより良い方法はありますか?

4

3 に答える 3

2

推奨される方法は間違いなく for ループを使用することですが、どうしても を使用する場合は、map次の方法operator.methodcallerが必要な場合があります。

>>> def foo(*args):
...    print 'foo',args
... 
>>> def bar(*args):
...    print 'bar',args
... 
>>> from operator import methodcaller
>>> 
>>> map(methodcaller('__call__',1,2,3),[foo,bar])
foo (1, 2, 3)
bar (1, 2, 3)
[None, None]

これを使用する際の注意点map- コードを python 3 に移植すると、map遅延が発生して動作しなくなります。

リスト内包表記をかなり簡単に使用することもできます (これは python3 でも機能します)。

[fn() for fn in self.pre]
[fn(val) for fn in self.mid]

于 2012-11-29T18:45:05.143 に答える
1

まず第一に、「不必要なオーバーヘッドがあるのではないかと心配しています」は、コードを最適化する方法ではありません。プロファイラーを使用してホットスポットを見つけます。

第二に、あなたのコードは、読者に何が起こっているのかを知らせるためのコメントで行うことができます。

最後に、別の方法で証明されるまで、以下はタスクを実行するための優れた方法です。

for func in self.pre: func()
#apply every function in self.mid to every value in values
for func,val in itertools.product(self.mid, values):
    func(val)

値を取得したい場合は、リスト内包表記を使用できます。評価を遅らせたい場合は、ジェネレータ式を使用できます。

于 2012-11-29T18:48:50.123 に答える
0
>>> def chain(*fn):
>>>     return lambda *args, **kwargs: [_(*args, **kwargs) for _ in fn]
>>>
>>> def add(x, y):
>>>    return(x + y)
>>>
>>> def multiply(x, y):
>>>    return(x * y)
>>>
>>> chained = chain(add, multiply)
>>> chained(2, 6)

[8, 12]

于 2020-03-29T20:53:32.123 に答える