2009-10-09 3 views
4

파이썬에서 로컬 변수를 바인딩하는 좋은 방법이 있는지 궁금합니다. 대부분의 작업에는 짧은 데이터 나 텍스트 처리 스크립트를 일련의 표현식 (파이썬이 허용하는 경우)과 함께 사용하여 객체 클래스를 정의하고 (이름 공간으로 사용) 인스턴스화하는 방법이 있습니다.파이썬에서 로컬 변수 바인딩하기

data = [1,2,3] 
output = ((lambda x: x + x) 
      (data[2])) 

입니다 함께

그래서 내가 생각했던 당신이 파이썬에서

(setq data '(1 2 3)) 
(setq output 
     (let ((x (nth 2 data))) 
     x + x)) 

처럼 뭔가를 할 수 (공통) 혀짤배기에서 같은 것이 있었다 최고의 내가 올 수 이것들은 물론 매우 간단한 예제이지만 lisp에서 let 또는 let만큼 확장 가능한 것이 있을까요? ? 클래스에게 가장 좋은 방법을 정의하는 것은 ... 로컬 네임 스페이스를 만들로 이동합니다 (그러나 좀 덜 상호 작용하는 방법을 느낌)하는

편집 : 그래서 더, 내가 원하는 (애매 내 사과) 의도를 설명하기 전역 변수의 사용을 줄입니다. 그래서 위의 경우, 필자는 추출 연산자를 반복하지 않으려는 모든 유형의 연산의 일반적인 경우로 사용하려고했습니다. 예를 들어, 하나는 하나

output = data[2] + data[2] 

또는

x = data[2] 
output = x + x 
del x 

이 같은 결과를 달성하기 위해 작성할 수 있습니다. 본질적으로 '데이터'에 대한 원하는 작업이 두 번째 항목을 가져 오는 것이 더 복잡하면 여러 번 입력하거나 컴퓨터가 동일한 표현식의 값을 필요한 것보다 더 많이 계산하게하지 마십시오. 따라서 대부분의 경우 연산 결과 (이 경우에는 data [2] 또는 operator.itemgetter (2) (data))를 전역 공간의 일부 변수에 할당하지만 주변 변수를 남기려는 혐오감이 있습니다 전역 공간에서 중간 값을 계산에 저장할 필요가 있다면 ... 'del'명령을 즉시 사용하십시오. 로컬 환경 또는 네임 스페이스를 정의하고 중간 결과를 로컬 변수에 바인딩하는 것이 이상적인 대안입니다.

+0

확인, 내 대답이 업데이트되었습니다. –

답변

3

내가 할 수있는 유일한 두 번째 레나와 다니엘 - 파이썬은 리스프 아니라, 언어 X를 언어 Y에 쓰려고하면 대개 비효율적이며 기껏해야 실망합니다.

첫 번째 점 : 당신의 예제 코드

data = [1,2,3] 
output = ((lambda x: x + x) 
      (data[2])) 

훨씬 더 읽기와 같은 것 :

data = [1, 2, 3] 
output = (lambda x=data[2] : x +x)() 

어쨌든,이 구체적인 경우에, 람다를 사용하여 overcomplexificated 총 과잉이다, 주로 무능한. 뇌사

output = data[2] + data[2] 

것 JustWork (TM) -!)

지금 WRT/지역 바인딩/네임 스페이스로, 일반적인 솔루션을 사용하는 ...입니다 기능 - 결국 중첩. 100 % 객체 ("모든 것이 객체"와 같이)는 파이썬은 순수한 객체가 아니며 일반 함수도 좋습니다. FWIW, "스크립트"에 대해서조차도 논리를 함수에 넣고 함수를 호출해야합니다. 함수의 로컬 네임 스페이스 액세스는 "전역"(실제로는 모듈 수준) 네임 스페이스 액세스보다 빠릅니다. 정규 패턴, 즉

def main(): 
    data = [1, 2, 3] 
    def foo(): 
     x = data[2] 
     return x + x 
    print foo() 
    data = [4, 5, 6] 
    print foo() 
    # if you want the nested function to close over its arguments: 
    def bar(data=data): 
     x = data[2] 
     return x + x 
    print bar() 
    data = [7, 8, 9] 
    print bar() 

,

import whatever 

def some_func(args): 
    code_here 

def some_other_func(args) 
    code_here 

def main(args): 
    parse_args 
    some_func(something) 
    some_other_func(something_else) 
    return some_exit_code 

if __name__ == '__main__' 
    import sys 
    sys.exit(main(sys.argv))   

참고 또한 중첩 된 기능도 둘러싸는 네임 스페이스에 액세스 할 수 있습니다 HTH

당신이하자 뭔가를 얻을 수있는 기능 장식 및 기본 매개 변수를 결합 할 수
+0

감사! 예 - 2.4 (?) 이후로 파이썬의 어휘 범위 규칙을 알고 있습니다 ...하지만 명명 된 함수없이 훨씬 더 많은 일을 할 수 있기를 바랬습니다. 그러나 삽화에 감사드립니다. – hatmatrix

+0

파이썬의 함수형 프로그래밍 지원은 실제로 제한적입니다.하지만 파이썬은 함수형 언어 인 척하지 않습니다. –

1

나는 Lisp을 알지 못한다. 나는 당신이 여기서하려고하는 것을 볼 수 없다. 그러나 저는 일반적으로 마치 파이썬이 마치 다른 언어 인 것처럼 Lisp이나 실제로 어떤 언어로 작성하려고해서는 안된다고 말하고 싶습니다. 저는 파이썬에서 5 년 동안 프로그래밍을 해오 고 있으며, 여러분이 위에서 시도한 것을 할 필요성을 본 적이 없습니다.

위의 경우에 대한 유스 케이스의 예를 제공 할 수 있습니까? 최종 결과와 관련하여 실제로하려는 것은 무엇입니까? 어쩌면 우리는 Lisp보다는 파이썬에서 가장 좋은 방법을 알려줄 수 있습니다.

2

그것은 당신이 무엇을 요구 조금 불분명, 어쨌든 대답하려고합니다 비트 :

당신은 파이썬에서 =와 이름에 변수를 바인딩합니다. 따라서 data = [1,2,3][1,2,3]이라는 이름을 data이라는 이름으로 바인딩합니다.

클래스 및 함수/메소드를 사용하여 로컬 네임 스페이스를 만들 수 있습니다.

let과 가장 비슷한 값은 deflambda입니다. 파이썬은 Lisp가 아니라 (특히 어떤 사람들이 당신에게 말하려고 시도 함에도 불구하고) 특별히 기능적이지 않기 때문에 사고 방식을 약간 수정해야합니다.

업데이트 : 아, 지금 무슨 뜻인지 알고 있습니다.

모든 변수는 Python에서 매우 로컬합니다. 전역 변수에서 가장 가까운 것은 from <module> import <variable>으로 액세스 할 수 있기 때문에 모듈 공간에 정의 된 변수입니다. global 키워드로 수정하려는 경우를 제외하고는 모듈에서 어디에서든지 액세스 할 수 있지만 수정하지는 마십시오. 함수/메소드 또는 클래스 정의에서 정의한 모든 것은 해당 네임 스페이스에서만 액세스 할 수 있습니다. 그래서 짧은

:.. 당신이 지금에 대해 걱정 것들에 대해 걱정할 필요가 없습니다 파이썬은 당신을 위해 그것을 처리합니다 :)

+0

나는 파이썬이 Lisp이 될 수없는 것처럼 열심히 노력한다고 말한다. – Svante

+0

흠, 나는 그렇게 생각하지 않았다! 하지만 결국 함수 또는 모듈에 포함되지 않은 변수를 덮어 쓰거나 잘못된 (예기치 않은) 값을 스크립트에서 더 이상 호출 할 수 없다고 생각합니다. 터프 하나 ... 고마워요! – hatmatrix

2

범위가 지정된 변수를 차단하십시오.

def let(func): 
    return func() 


data = [1,2,3] 
@let 
def output(x=data[2]): 
    return x + x 
print(output) # 6 

# or if a single expression is enough: 
output = let(lambda x=data[2]: x+x) 

is는 Python에서 널리 쓰이는 관용구가 아니므로 코드를 다른 사람들이 쉽게 이해할 수 있도록 피하는 것이 좋습니다. 일반 지역 변수를 사용하십시오 :

data = [1,2,3] 
x = data[2] 
output = x + x 

이것이 실제 문제가되는 경우 단일 기능에서 너무 많이 수행하려고 시도하는 좋은 징후입니다.

+0

감사! ...하지만 "정규 지역 변수"는 함수의 범위 또는 let() 환경과 같은 것으로 정의되지 않은 한 실제로는 로컬이 아닙니다. – hatmatrix

+0

좋은 점, 나는 너무 익숙해 져 있습니다. 코드가 함수에서 실행된다는 것을 암묵적으로 가정 한 함수의 모든 것. 최상위 수준에서만 선언 구조를 사용하는 것이 우수 사례라는 것을 알게되었습니다. 어림짐작의 좋은 규칙은 변수의 범위가 문제가되는 경우에, 도우미 기능을 창조하기위한 것일 것입니다. –