불행히도 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
은 외장형 범위가 아닌 변수입니다.