문제

모호한 제목을 양해해 주시기 바랍니다.누구든지 제안 사항이 있으면 알려주세요!또한 더 적절한 태그로 다시 태그를 지정해 주세요!

문제

가져온 클래스의 인스턴스가 가져오기 도구의 범위(전역, 로컬)에 있는 항목을 볼 수 있도록 하고 싶습니다.여기서 작동하는 정확한 메커니즘을 확신할 수 없기 때문에 말보다 짧은 내용으로 훨씬 더 잘 설명할 수 있습니다.

## File 1
def f1():  print "go f1!"

class C1(object):
    def do_eval(self,x):  # maybe this should be do_evil, given what happens
        print "evaling"
        eval(x)
        eval(x,globals(),locals())

그런 다음 반복 세션에서 이 코드를 실행하면 NameErrors

## interactive
class C2(object):
    def do_eval(self,x):  # maybe this should be do_evil, given what happens
        print "evaling"
        eval(x)
        eval(x,globals(),locals())

def f2():
    print "go f2!"

from file1 import C1
import file1

C1().do_eval('file1.f1()')
C1().do_eval('f1()')
C1().do_eval('f2()')

file1.C1().do_eval('file1.f1()')
file1.C1().do_eval('f1()')
file1.C1().do_eval('f2()')

C2().do_eval('f2()')
C2().do_eval('file1.f1()')
C2().do_eval('f1()')

이런 종류의 작업에 대한 일반적인 관용어/패턴이 있나요?내가 완전히 잘못된 나무를 짖고 있는 걸까요?

도움이 되었습니까?

해결책

이 예에서는 함수를 객체로 메서드에 넘겨주기만 하면 됩니다. C1:

>>> class C1(object):
>>>    def eval(self, x):
>>>        x()
>>>
>>> def f2(): print "go f2"
>>> c = C1()
>>> c.eval(f2)
go f2

Python에서는 함수와 클래스를 다른 메서드에 전달하고 거기에서 호출/생성할 수 있습니다.

실제로 코드 문자열을 평가하려면 Thomas가 이미 언급한 것처럼 환경을 지정해야 합니다.

위의 모듈이 약간 변경되었습니다.

## File 1
def f1():  print "go f1!"

class C1(object):
    def do_eval(self, x, e_globals = globals(), e_locals = locals()):
        eval(x, e_globals, e_locals)

이제 대화형 통역사에서:

>>> def f2():
>>>    print "go f2!"
>>> from file1 import *    # 1
>>> C1().do_eval("f2()")   # 2
NameError: name 'f2' is not defined

>>> C1().do_eval("f2()", globals(), locals()) #3
go f2!
>>> C1().do_eval("f1()", globals(), locals()) #4
go f1!

일부 주석

  1. 여기서는 모든 객체를 삽입합니다. file1 이 모듈의 네임스페이스에
  2. f2 의 네임스페이스에 속하지 않습니다. file1, 그러므로 우리는 NameError
  3. 이제 환경을 명시적으로 전달하고 코드를 평가할 수 있습니다.
  4. f1 우리가 그것을 가져왔기 때문에 이 모듈의 네임스페이스에 있습니다.

편집하다:환경을 명시적으로 전달하는 방법에 대한 코드 샘플을 추가했습니다. eval.

다른 팁

함수는 메서드 및 클래스 본문과 마찬가지로 항상 정의된 범위에서 실행됩니다.다른 범위에서는 실행되지 않습니다.가져오기는 또 다른 할당문일 뿐이고 Python의 모든 내용은 참조이므로 함수, 클래스 및 모듈은 가져오는 위치조차 알지 못합니다.

다음 두 가지 작업을 수행할 수 있습니다.사용하기를 원하는 '환경'을 명시적으로 전달하거나 스택 해커를 사용하여 호출자의 네임스페이스에 액세스합니다.전자는 후자만큼 구현에 의존하지 않고 취약하지 않기 때문에 후자보다 훨씬 더 선호됩니다.

비슷한 작업을 시도하는 string.Template 클래스를 살펴보는 것이 좋습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top