1

CPS コードのような高機能関数を書きたいと思います。関数コードを受け取り、それをオブジェクトにカプセル化し、このオブジェクトを結合する手段を追加する必要があります。

このようなもの:

myFunction=MyFunction(
  a = b+c
  print(c)
  return a)

しかし、無名関数の pythonic 式は 1 つだけです - lambda ステートメントです。あまり似合いません。

Python は強力な言語であり、さまざまな式があります: デコレータ、eval など... 前述の例のように無名関数を記述する良い方法はありますか?

もう 1 つの方法は、ラムダ式を、モナドの bind や return などの特別な関数や、複雑な式を 1 行で記述するためのその他の高階関数で拡張することです。

主な目的は、カスタム スロー コントロール式を作成することです。

class TimeoutExpression:
  def __init__(self,name,function,timeout):
    ...
  def eval(self):
    """ eval functions, print result and error message
      if functions failed to calculate in time """
    ...
  def andThen(self,otherExpression):
    """ create complex sequential expression"
    ...
  def __call__(self):
    ...

そして、次のように使用されます。

TimeoutExpression( time consuming calculation ).andThen(
  file object access).andThen(
    other timer consuming calcualtion )

カスタム制御フロー構造を作成するための最適な Python の慣用的な方法は何ですか?

ディスカッションを読みました: How to make an anonymous function in Python without Christening it? 同じアプローチでいくつかの決定が言及されました: 三重引用符で囲まれた文字列から関数を生成します。絶対に正しく動作する一方で、かなり面倒に思えます。それは今のところ設計された最良のアプローチですか?

更新

問題はないと言われました.pythonでは、どのコンテキストでもdefを使用できます。私のpythonの経験が私をだまし、提案されているように任意のスコープでdefを使用しようとしたと想定しました。 エラーが発生しました。どのようなコンテキストでも正確にどのように定義を配置する必要がありますか?

def compose(f):
    return lambda k: lambda x: f(k(x))

test = compose( def sqr(x) :
                print ("sqr "+str(x))
                return x*x
                return sqr) ( def x2(x):
                              print("x2 "+str(x))
                              return x*2
                              return x2 )

エラー:

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "anonFunction.py", line 4
    test = compose( def sqr(x) :
                  ^
SyntaxError: invalid syntax
4

3 に答える 3

3

ラムダの wrt Python を使用するメリットはありません。ラムダの関数と匿名関数は一般に単純な関数に使用されます。より複雑な複数行の関数が必要な場合は、名前付き関数を作成すると読みやすくなります。

関数はファーストクラスのオブジェクトであるため、関数を定義し、変数に割り当てて使用し、渡すことができます。そうでなければ、ラムダ関数を選択できる使い捨ての単純な関数が必要でない限り、名前付き関数が有利です。それにもかかわらず、Pythonic でラムダを使用することは決してありません。

あなたの例に戻ると、

myFunction=MyFunction(
  a = b+c
  print(c)
  return a)

Python では、次のように同様に記述します。

def MyFunction:
    a =b + c
    print c
    return a

そして、MyFunction非常に Pythonic であるように、コードの周りに渡します。コールバックが匿名として記述されている Javascript のコードを見たことがあります。しかし、各言語には独自の哲学があり、Python の哲学は読みやすさです。

---可読性が重要です。

于 2012-04-19T19:14:04.120 に答える
1

Python では、lambdaキーワードを使用して、単一の式を評価して結果を返す関数オブジェクトのみを作成できます。ステートメントまたは複数の行を使用して関数を作成するdefには、名前を必要とするキーワードを使用する必要があります。

制限の理由は、lambdaほとんどの場合、Python が行末を重要なものとして扱うという事実に基づいています。

Python に複数行の Lambda がない: なぜですか?

ただし、名前は重要ではありません。「匿名」関数のすべてがすべて名前anonまたは何かで定義されるという規則を作成できます。本当に気にする場合は、名前の痕跡をすべて消去できます。

y = 5
def anon(x):
    return x + y  # note "closure" over the current value of y

myFunction = anon

# if you really care, you can erase all evidence of name "anon"
anon.__name__ = ''  # wipe the record of original name "anon"
del(anon)  # unbind the name "anon"

したがって、関数型プログラミングの場合、Python はファーストクラスの関数オブジェクトを作成し、それらを渡すことができます。Python ができないことの 1 つは、名前を持たない複雑な関数オブジェクトを作成することですが、それが問題になる理由は実際にはありません。

于 2012-04-19T19:41:07.133 に答える
1

私は、複数行のラムダが提供するような機能を提供するネストされた関数を使用するハックを持っています。ここで私の GitHub リポジトリをチェックアウトできます。

基本的に、次のようなことができます。

fibonacci = f('result = t(a-1)+t(a-2) if a>2 else 1; return result')
fibonacci(6) #Output: 8

または、無名関数のポイントまで:

cube = f('result = a**3; return result')(4)
print(cube) #Output: 64

このハックには明らかに制限があります。たとえば、ifor などのより複雑なインデント構造を実装する方法はまだわかりませんwhileが、これも非常に安価なハックです。

于 2012-08-03T18:12:15.240 に答える