8

Googleでこの件について何も見つけられなかったので、ここで質問する必要があると思います:

jQueryのように、Pythonで関数を連鎖させることは可能ですか?

['my', 'list'].foo1(arg1, arg2).foo2(arg1, arg2).foo3(arg1, arg2) #etc...

このコードを書くと、多くのスペースと可読性が失われます。

foo3(foo2(foo1(['my', 'list'], arg1, arg2), arg1, arg2), arg1, arg2) #etc...

そのような関数を作成するための幻想的なライブラリがいくつか存在するようですが、なぜこれがそれほど複雑に見える必要があるのか​​ わかりません...

ありがとう!

4

5 に答える 5

10

関数が値を返す限り、チェーンできます。jQuery では、通常、セレクター メソッドはセレクター自体を返します。これにより、チェーンを実行できます。Python で連鎖を実装したい場合は、次のようにすることができます。

class RoboPuppy:

  def bark(self):
    print "Yip!"
    return self

  def growl(self):
    print "Grr!"
    return self

pup = RoboPuppy()
pup.bark().growl().bark()  # Yip! Grr! Yip!

ただし、問題は、関数の引数が狭すぎることです。連鎖はこれに対する解決策ではありません。関数の引数を要約したい場合は、次のように、引数を変数に代入してから関数に渡します。

spam = foo(arg1, arg2)
eggs = bar(spam, arg1, arg2)
ham = foobar(eggs, args)
于 2010-12-03T06:42:15.193 に答える
9

これがSimonのListMutator提案の拡張です:

class ListMutator(object):

    def __init__(self, seq):
        self.data = seq

    def foo1(self, arg1, arg2):
        self.data = [x + arg1 for x in self.data]
        # This allows chaining:
        return self

    def foo2(self, arg1, arg2):
        self.data = [x*arg1 for x in self.data]
        return self

if __name__ == "__main__":
    lm = ListMutator([1,2,3,4])
    lm.foo1(2, 0).foo2(10, 0)
    print lm.data

    # Or, if you really must:
    print ListMutator([1,2,3,4]).foo1(2, 0).foo2(10, 0).data

コレクションの抽象基本クラスを使用することで、1つ上手く行き、ListMutator完全にリストのように動作させることができます。実際、自分自身をサブクラス化することはできますが、実行する必要のある特定のことを実行できなくなる可能性があります...そして、のような組み込み型のサブクラス化に関する一般的な意見はわかりません。listlist

于 2010-12-03T08:02:48.590 に答える
3

オブジェクト メソッドについて話している場合は、return selfすべてのメソッドから見ても簡単です。一方、バインドされていない関数を連鎖させたい場合、それらを好きなように連鎖させることは私にはあまり意味がありません。確かに見栄えはしますが、「。」が含まれているため、意味的に一貫性がありません。「チェーン」ではなく、オブジェクト属性アクセスを表します。

于 2010-12-03T06:24:56.663 に答える
1

今後の参考のために、最小限の関数型プログラミング ライブラリであるMokaをご覧ください。彼らの例から:

(List()                    # Create a new instance of moka.List
   .extend(range(1,20))    # Insert the numbers from 1 to 20
   .keep(lambda x: x > 5)  # Keep only the numbers bigger than 5
   .rem(operator.gt, 7)    # Remove the numbers bigger than 7 using partial application
   .rem(eq=6)              # Remove the number 6 using the 'operator shortcut'
   .map(str)               # Call str on each numbers (Creating a list of string)
   .invoke('zfill', 3)     # Call zfill(x, 3) on each string (Filling some 0 on the left)
   .insert(0, 'I am')      # Insert the string 'I am' at the head of the list
   .join(' '))             # Joining every string of the list and separate them with a space.

>>> 'I am 007'
于 2012-05-08T12:47:22.527 に答える
0

これを見てください。連鎖用の単純なラッパー クラスです。そして、underscore.js lib の機能の一部を実装しました。リスト、タプル、または辞書をアンダースコアでラップし、それを操作してから、別のアンダースコアを追加して値を取得します。

print (_([1,2,3])
       .map(lambda x: x+1)
       .reverse()
       .dict_keys(["a", "b", "c"])
       .invert()
       .items()
       .append(("this is what you got", "chaining"))
       .dict()._)

出力:

{2: 'c', 3: 'b', 4: 'a', 'this is what you got': 'chaining'}
于 2013-07-18T06:38:07.620 に答える