パイソン:「with」を使用してその場で新しい関数を定義する
-
18-09-2019 - |
質問
次のコードを変換したいと思います。
...
urls = [many urls]
links = []
funcs = []
for url in urls:
func = getFunc(url, links)
funcs.append(func)
...
def getFunc(url, links):
def func():
page = open(url)
link = searchForLink(page)
links.append(link)
return func
はるかに便利なコードに変換します。
urls = [many urls]
links = []
funcs = []
for url in urls:
<STATEMENT>(funcs):
page = open(url)
link = searchForLink(page)
links.append(link)
これを使ってやろうと思っていたのですが、 with
声明。以下でコメントしたように、私は次のことを達成したいと思っていました。
def __enter__():
def func():
..code in the for loop..
def __exit__():
funcs.append(func)
もちろん、これは機能しません。
リスト内包表記は、アクションが発生した場合には適していません。 searchForLink
単なる 1 つの機能ではなく、多くの機能があります。非常に読みにくいコードになってしまいます。たとえば、これでもリスト内包表記では問題が発生します。
for url in urls:
page = open(url)
link1 = searchForLink(page)
link2 = searchForLink(page)
actionOnLink(link1)
actionOnLink(link2)
.... many more of these actions...
links.append(link1)
解決
ビット型にはまらない、しかし、あなたは、FUNCを登録し、デフォルト引数として任意のループ変数をバインドデコレータを持つことができます:
urls = [many urls]
links = []
funcs = []
for url in urls:
@funcs.append
def func(url=url):
page = open(url)
link = searchForLink(page)
links.append(link)
他のヒント
ここはwith
を使用しても意味がありません。代わりに、リストの内包表記を使用します:
funcs = [getFunc(url, links) for url in urls]
def
とlambda
:関数を作成するための唯一の二つの方法があります。ラムダは小さな機能のために意図されているので、彼らはあなたのケースのために非常に適切ではないかもしれません。あなたが本当にしたい場合は、それぞれ別の内の2つのラムダを囲むことができます:
urls = [many urls]
links = []
funcs = [(lambda x:
lambda:
links.append(searchForLink(open(x))))(u)
for u in urls]
私の好みのために少しもLISPishます。
ライン<STATEMENT>(funcs):
を失う。
編集ます:
私は意味:なぜあなたはこれを行うだろうか?なぜ、ページごとに新しい関数を定義しますか?理由だけでこれをしない?
urls = [many urls]
links = []
for url in urls:
page = open(url)
link = searchForLink(page)
links.append(link)
これを行うには「with」を使用しないでください (ただし、これが Python であることを考えると、奇妙な副作用と Python のダイナミズムを使用すれば、ほぼ確実に使用できます)。
Python の「with」の目的は次のとおりです。 ドキュメントに記載されているように, 、「コンテキスト マネージャーによって定義されたメソッドでブロックの実行をラップします。これにより、一般的な try...excel...finally の使用パターンをカプセル化し、再利用しやすくなります。」
Python の「with」と JavaScript/VisualBasic 「with」は見た目は似ているかもしれませんが、実質的には無関係です。
古き良き itertoolsするます。
from itertools import imap
links.extend(imap(searchForLink, imap(open, urls)))
多分あなたは好む、けれども機能するます。
from functional import *
funcs = [partial(compose(compose(links.append, searchForLink), open), url) for url in urls]
for func in funcs: func()
私はそれがwith
用のクラスを作成する価値があるとは思わない:それはそれだけのヘルパー関数を記述するよりも、__enter__
と__exit__
を作成するために、より多くの仕事です。
あなたはより良いあなたが後にしている遅れた計算を達成するための発電機を使用している可能性があります。
def MakeLinks(urls):
for url in urls:
page = open(url)
link = searchForLink(page)
yield link
links = MakeLinks(urls)
あなたがリンクをしたいときます:
for link in links:
print link
URLは(あなたが避けるためにトリングているように見えるもの)このループ中に見上げ、そしてないすべてを一度されます。