パイソン:「with」を使用してその場で新しい関数を定義する

StackOverflow https://stackoverflow.com/questions/2200026

  •  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]
deflambda

関数を作成するための唯一の二つの方法があります。ラムダは小さな機能のために意図されているので、彼らはあなたのケースのために非常に適切ではないかもしれません。あなたが本当にしたい場合は、それぞれ別の内の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は(あなたが避けるためにトリングているように見えるもの)このループ中に見上げ、そしてないすべてを一度されます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top