2011-12-02 1 views
4

파이썬으로 검은 색과 더러운 마술을 수행해야합니다.Python 인트로 피싱 : 메소드에서 어떤 필드에 액세스하는지 감지하는 방법

내 이전 질문 Lazy data-flow (spreadsheet like) properties with dependencies in Python에 이어 파생 속성이 자동으로 계산 기능을 검사하여 필드의 목록을 채우고 싶습니다.

나는 func_code.co_names 속성을 사용할 수 있다고 생각하지만 거기에 몇 가지주의 사항이 있는지 잘 모르겠다. documentation은별로 도움이되지 않는다.

아이디어가 있으십니까?

답변

2

불행히도 func_code.co_names은별로 도움이되지 않습니다. 여기에는 전역 변수를 포함하여 코드 세그먼트 내에서 액세스되는 모든 이름이 표시됩니다.

class Test(object): 
    def calc_a(self): 
     return self.b + self.c 

    def calc_x(self): 
     return self.y.a + self.y.b 

>>> Test.calc_a.func_code.co_names 
('b', 'c') 
>>> Test.calc_x.func_code.co_names 
('y', 'a', 'b') 

'a'와 'b'가 'self'또는 'self.y'에서로드 된 경우이 배열에서 알 수 없습니다. 일반적으로 코드를 실행하지 않고 약간의 코드의 액세스 패턴을 파악하는 유일한 방법은이를 분해하는 것입니다.

>>> import dis 
>>> dis.dis(Test.calc_x) 
23   0 LOAD_FAST    0 (self) 
       3 LOAD_ATTR    0 (y) 
       6 LOAD_ATTR    1 (a) 
       9 LOAD_FAST    0 (self) 
      12 LOAD_ATTR    0 (y) 
      15 LOAD_ATTR    2 (b) 
      18 BINARY_ADD   
      19 RETURN_VALUE   

우리는 그 객체가로드에서 함수가 그 객체가 'Y'속성 (co_names[0])를로드에서 다음, (항상 바인딩 기능 co_varnames[0]입니다) 변수 '자기'를로드하고 있음을 볼 수 속성 'a'(co_names[1]). 두 번째 스택 객체가 self.y.b에서 푸시 된 다음 두 개가 추가됩니다.

표준 lib 디렉토리에서 dis.py 소스를보고 C 파이썬 이진 코드가 어떻게 분해되었는지 확인하십시오. 0 번째 변수의로드는 바운드 함수에 중요합니다. 또 다른 유용한 점은 함수에 대한 인수가 (나머지 또는 varnames는 locals 임)이고 co_freevars은 외장형 범위가 아닌 변수입니다.