2010-02-04 5 views
4

다음 코드를 변환하고 싶습니다 :Python : "with"를 사용하여 즉석에서 새로운 함수 정의하기

... 
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 작업은 단지 하나의 기능이 아니라 많은 기능이있는 경우 목록 내장은 좋지 않습니다. 그것은 극도로 읽을 수없는 코드로 바뀔 것입니다. 예를 들어, 이렇게해도 목록 내포에 문제가 될 수 있습니다.

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) 
+1

우선 : 왜 함수를 전달하려고합니까? 예, 거기에는 용도가 있습니다. 그러나 그 공통점은 아닙니다. 둘째, 왜 함수를 사용하지 않는 것입니까? 함수에는 아무런 문제가 없습니다. :) –

+0

당신이 길을 잃은 경우 (내가 한 것처럼) 이것은 대답이되는 질문입니다 : 목록 이해력을 사용하십시오. – telliott99

답변

4
약간 틀에 얽매이지 않는

,하지만 당신은 장식이 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) 
+0

"Unconvential", 최소한. 그래, 멋지게 아름다워;) –

+0

매번 겹쳐 쓰는 함수'func'가 생각납니다. 그래서 나는 마지막 URL 즉, 마지막 url을 처리하는 함수를 가지고 떠날 것입니다. 내가? – Guy

+0

+1 : 이것은 정말 영리합니다! @ Guy : 기본 인수는 정의 시간에 평가되므로 바인딩은 Ok입니다. –

2

라인을 잃게 <STATEMENT>(funcs):

편집 :

내 말은 :이 작업을 수행하는 이유? 각 페이지마다 새로운 기능을 정의하는 이유는 무엇입니까? 왜 그냥하지 않습니까?

urls = [many urls] 
links = [] 
for url in urls: 
    page = open(url) 
    link = searchForLink(page) 
    links.append(link) 
+0

어쩌면 사람 일뿐입니다. 물론 당신은 당신의 제안을 할 수는 있지만 그건 제 질문이 아닙니다. – Guy

+0

Meh. 나는 +1을 투표했다. 그러나 "잠시 멈춤"하고 투표를 거치지 않았으므로 지금 +1을 투표하기로 결정했다. 이것은 지금까지 어떤 의미로든 유일한 대답입니다. –

+0

하지만 질문에 대답하지 않습니다. – Guy

6

여기서 with을 사용하는 것은 의미가 없습니다. 대신에 지능형리스트를 사용

기능을 만들 수있는 두 가지 방법이 있습니다
funcs = [getFunc(url, links) for url in urls] 
+0

함수 객체를 반환하려고하는 함수를 호출합니다. –

+5

@Lasse :'getfunc()'는 이미 함수 객체를 반환합니다. –

+0

'getFunc()'함수를 사용하고 싶지 않습니다. 그것이 바로 포인트 – Guy

2

: deflambda. 람다는 작은 기능을위한 것이므로 귀하의 경우에 적합하지 않을 수 있습니다. 당신이 정말로 원하는 경우, 당신은 서로 내에서 두 개의 람다를 동봉 할 수 있습니다 내 취향

urls = [many urls] 
links = [] 
funcs = [(lambda x: 
      lambda: 
       links.append(searchForLink(open(x))))(u) 
     for u in urls] 

이 너무 LISPish.

+0

+1 "LISPish"라고 5 번 빨리 말하십시오 ... –

+0

... 저에게 lispy에 동의하십시오. – Guy

1

"with"를 사용해서는 안됩니다 (파이썬이라면, 거의 확실하게, 기묘한 부작용과 파이썬의 동적 효과를 사용합니다).

파이썬에서 "with"의 목적은 "as described in the docs"이며 컨텍스트 관리자가 정의한 메소드로 블록의 실행을 감싸는 것입니다. 이렇게하면 일반적인 try ... except ... finally 사용 패턴을 캡슐화 할 수 있습니다. 편리한 재사용. "

저는 여러분이 파이썬의 "with"와 Javascript/VisualBasic "with"를 혼동하고 있다고 생각합니다. 이것은 "외관상 비슷하지만 효과가없는"것일 수 있습니다.

1

좋은 오래된 itertools.

from itertools import imap 
links.extend(imap(searchForLink, imap(open, urls))) 

어쩌면 functional을 선호 할 수도 있습니다.

from functional import * 
funcs = [partial(compose(compose(links.append, searchForLink), open), url) for url in urls] 
for func in funcs: func() 

가 나는 with 사용하기위한 클래스를 만드는 가치있는 생각하지 않습니다 : 그것은 단지 도우미 함수를 작성하는 것보다 __enter____exit__을 만드는 데 더 많은 작업입니다.

+0

꽤 이상합니다. 가장 좋은 답변은 아직 있습니다. - 감사합니다. '나는'무엇을하는지 이해한다고 생각합니다. 나는'__enter__'에'def func() :'을,'__exit__'에'funcs.append (func)'를 붙이기를 바랬다. 그러나 분명히 쉽지는 않을 것입니다. – Guy

1

당신은 뒤에있어 지연 계산을 달성하기 위해 발전기를 사용하여 더 나은 될 수있다.

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이 (당신이 피하기 위해 트링있는 것처럼 보이는) 모든 번이 루프 동안 고개 될 것입니다.

관련 문제