BDFLがPythonラムダを1行にすることを選択した理由を具体的に説明できますか?
これはいい:
lambda x: x**x
これはエラーになります:
lambda x:
x**x
ラムダを複数行にすると、どういうわけか通常のインデントルールが「邪魔」され、さらに例外を追加する必要があることを理解していますが、それはメリットに値しませんか?
たとえば、JavaScriptを見てください。どうすればこれらの匿名関数なしで生きられますか?それらは不可欠です。 Pythonistaは、引数として渡すためだけにすべての複数行関数に名前を付ける必要をなくしたくありませんか?
グイドファンヴァンロッサムは自分で答えた。
しかし、そのようなソリューションには「Pythonicity」が欠けていることがよくあります。これは、優れたPython機能のとらえどころのない特性です。 Pythonicityをハード制約として表現することは不可能です。 Zen of Pythonでも、Pythonicityの単純なテストにはなりません...
上記の例では、提案されたソリューションのアキレス腱を見つけるのは簡単です。二重のコロンは、実際には構文的に明確であり(「パズルの制約」の1つです)、完全に任意であり、Pythonの他のものとは似ていません...
しかし、私もそれを拒否します。なぜなら、結局(そしてこれが、私がサブミッターを誤って誤解させることを認めているところである)、式の途中にインデントベースのブロックを埋め込むという容認できない解決策を見つけたからです。ステートメントのグループ化(ブレースやbegin/endキーワードなど)の代替構文も同じように受け入れられないので、これは複数行のラムダを解決できないパズルにします。
http://www.artima.com/weblogs/viewpost.jsp?thread=147358
基本的に、彼は解決策は可能であるが、Pythonがどのようであるかと一致しないと言います。
pythonで複数行のラムダを実行するのはまったく問題ありません。
>>> f = lambda x: (
... x**x)
>>> f
<function <lambda> at 0x7f95d8f85488>
>>> f(3)
27
実際のラムダ制限は、ラムダが単一の式でなければならないという事実です。キーワードを含めることはできません(python2のprint
やreturn
など)。
GvRは、通常はパラメーターとして使用されるため、ラムダのサイズを制限するためにそうすることを選択します。実際の関数が必要な場合は、def
を使用してください
これは非常に古いことを知っていますが、参照としてここに入力します。
ラムダを使用する代わりに、従来とは異なる方法でdef
を使用することもできます。目的は、def
を関数に渡すことです。これは、デコレータという1つの状況でのみ実行できます。この実装では、_def result
_は関数を作成せず、reduce()
の結果を作成し、最終的にdict
になることに注意してください。
恥知らずなプラグイン:私はこれをたくさんします ここ 。
_>>> xs = [('a', 1), ('b', 2), ('a', 3), ('b', 4)]
>>> foldl = lambda xs, initial: lambda f: reduce(f, xs, initial)
>>> @foldl(xs, {})
... def result(acc, (k, v)):
... acc.setdefault(k, 0)
... acc[k] += v
... return acc
...
>>> result
{'a': 4, 'b': 6}
_
複数ステートメントのラムダを実行できることに注意してくださいが、本当に、本当に醜いコードでのみ。ただし、興味深いのは、この実装でスコープがどのように機能するかです(name
変数の複数の使用法とmessage
変数のシャドウイングに注意してください)。
_>>> from __future__ import print_function
>>> bind = lambda x, f=(lambda x: x): f(x)
>>> main = lambda: bind(
... print('Enter your name.'), lambda _: bind(
... raw_input('> '), lambda name: bind(
... 'Hello {}!'.format(name), lambda message: bind(
... print(message), lambda _: bind(
... 'Bye {}!'.format(name), lambda message: bind(
... print(message)
... ))))))
>>> main()
_
_Enter your name.
> foo
Hello foo!
Bye foo!
_
複数ステートメントのラムダを一緒にハックすることは、pyrospadeが明らかにするほど悪いことではありません。私たちはcould Haskellのようにbindを使用して一連のモナド関数を作成しますが、不純な世界にいるためですPythonの場合、副作用を使用して同じことを達成することもできます。
私のブログ でこれを行ういくつかの方法を説明します。
たとえば、Pythonは、タプルの要素を順番に評価することを保証しているため、命令__,
_と同じように_;
_を使用できます。次のような多くのステートメントを置き換えることができます。 print
、_sys.stdout.write
_のような式。
したがって、以下は同等です。
_def print_in_tag_def(tag, text):
print "<" + tag + ">"
print text
print "</" + tag + ">"
import sys
print_ = sys.stdout.write
print_in_tag_lambda = lambda tag, text: (print_("<" + tag + ">"),
print_(text),
print_("</" + tag + ">"),
None)[-1]
_
最後にNone
を追加し、_[-1]
_を使用して抽出したことに注意してください。これにより、戻り値が明示的に設定されます。これを行う必要はありませんが、これがないと、ファンキーな_(None, None, None)
_戻り値が返されます。
したがって、IOアクションをシーケンスできます。ローカル変数はどうですか?
Pythonの_=
_はステートメントを形成するため、同等の式を見つける必要があります。 1つの方法は、引数として渡されるデータ構造の内容を変更することです。例えば:
_def stateful_def():
foo = 10
bar = foo * foo
foo = 2
return foo + bar
stateful_lambda = (lambda state: lambda *_: (state.setdefault('foo', 10),
state.setdefault('bar', state.get('foo') * state.get('foo')),
state.pop('foo'),
state.setdefault('foo', 2),
state.get('foo') + state.get('bar'))[-1])({})
_
_stateful_lambda
_で使用されているいくつかのトリックがあります:
*_
_引数により、ラムダはany引数の数を取ることができます。これはzero引数を許可するため、_stateful_def
_。の呼び出し規約を回復します。_
_の呼び出しは、「この変数を使用しない」とだけ表記されていますlambda state: lambda *_: ...
_ (lambda state: ...)({})
_ state
を値_{}
_に割り当てることができます(例:_state = {}
_)state
のキーと値を変数名とバインド値として扱いますa = b
_の代わりにstate.setdefault(a, b)
を使用し、a
の代わりにstate.get(a)
を使用します[-1]
_を使用して、return
ステートメントのように機能する最後の値を抽出しますもちろん、これはかなり面倒ですが、ヘルパー関数を使用してより良いAPIを作成できます。
_# Keeps arguments and values close together for immediately-called functions
callWith = lambda x, f: f(x)
# Returns the `get` and `setdefault` methods of a new dictionary
mkEnv = lambda *_: callWith({},
lambda d: (d.get,
lambda k, v: (d.pop(k), d.setdefault(k, v))))
# A helper for providing a function with a fresh `get` and `setdefault`
inEnv = lambda f: callWith(mkEnv(), f)
# Delays the execution of a function
delay = lambda f x: lambda *_: f(x)
# Uses `get` and `set`(default) to mutate values
stateful_lambda = delay(inEnv, lambda get, set: (set('foo', 10),
set('bar', get('foo') * get('foo')),
set('foo', 2),
get('foo') + get('bar'))[-1])
_
私は貢献できるかもしれませんが、改行を使用します:
x = lambda x,y: x-y if x<y \
else y-x if y<x \
else 0
pythonがonelinersを書くことができるという非常に素晴らしいことを、例のように忘れないでください:
a=b=0; c=b+a; d = a+b**2 #etc etc
そして、lambdaは非常に強力ですが、1つの関数全体を置き換えることを意図したものではありません。
makeTag = lambda tagName: "<{}>".format(tagName)
closeTag = lambda tagName: makeTag("/"+str(tagName))
openTag = lambda tagName: makeTag(tagName)
writeHMTLline = lambda tag,content: ""+opetTag(tag)+str(content)+closeTag(tag)
しかし、本当にこのようにしたいですか?それはしばらくするとほとんど読めなくなり、解き明かされた終わりから始まるロープの始まりに到達するようなものです。
ラムダは、(特に)関数指向プログラミングのマップ、フィルター、およびリデュース関数で、1つだけの関数として機能します。たとえば、整数で2で割り切れる値の文字値を取得する
chrDev2 = lambda INT: chr(INT) if isinstance(INT,int) and INT%2==0 else INT
someStringList = map( chrDev2, range(30) )
>>> ['\x00', 1, '\x02', 3, '\x04', 5, '\x06', 7, '\x08', 9, '\n', 11, '\x0c', 13, '\x0e', 15, '\x10', 17, '\x12', 19, '\x14', 21, '\x16', 23, '\x18', 25, '\x1a', 27, '\x1c', 29]
複雑な関数(またはそれ以上の数のラムダ)を定義し、それを別のラムダ内に配置することで、関数表現関数として使用できます。
def someAnon(*args): return sum(list(args))
defAnon = lambda list: [ x*someAnon(*list) for x in list]
しかしPythonには別の方法で関数式のサポートがあります:-レットはsuperAwesomeFunction
と呼ばれるいくつかの関数を持っていると言い、その関数はいくつかの非常に素晴らしいことを行うことができます、それを呼び出さないことで変数に割り当てることができます、このような:
SAF = superAwesomeFunction # there is no () at the end,
したがって、SAFを呼び出すときに、superAwesomeFunctionまたはメソッドを呼び出します。 Libフォルダーを検索すると、python __builtin__
モジュールのほとんどがそのように記述されていることがわかります。これは、特定のタスクを実行するいくつかの関数が必要になる場合があるためです。ユーザーが使用するのに十分ではありませんが、いくつかの関数に必要です。そのため、「superAwesomeFunction」という名前の2つの関数を持たないように選択できます。「superAwesomeFunctionDoingBasicStuf」と「realSuperAwesomeFunction」を持ち、単に「 「superAwesomeFunction」変数に「realSuperAwesomeFunction」を追加すれば完了です。
コンソールにimportedModule.__file__
(実際の例import os;os.__file__
)と入力すると、インポートされたモジュールの場所を見つけることができます。そのディレクトリをたどってimportedModule.pyというファイルに移動し、エディターで開きます。自分の「知識」を最大化する方法を見つけてください。
これがあなたやおそらく他の問題を抱えている同僚たちに役立つことを願っています。