[PYTHON] 인스턴스 메소드 호출을 인터셉트하는 방법은 무엇입니까?
PYTHON인스턴스 메소드 호출을 인터셉트하는 방법은 무엇입니까?
MyWrapper 클래스의 인스턴스 메서드 호출을 가로 채기위한 방법을 찾고있다.
class SomeClass1:
def a1(self):
self.internal_z()
return "a1"
def a2(self):
return "a2"
def internal_z(self):
return "z"
class SomeClass2(SomeClass1):
pass
class MyWrapper(SomeClass2):
# def INTERCEPT_ALL_FUNCTION_CALLS():
# result = Call_Original_Function()
# self.str += result
# return result
def __init__(self):
self.str = ''
def getFinalResult(self):
return self.str
x = MyWrapper()
x.a1()
x.a2()
내 래퍼 클래스를 통해 모든 함수 호출을 가로 채고 싶습니다. 래퍼 클래스에서 모든 결과 문자열을 추적하고 싶습니다.
result = x.getFinalResult()
print result == 'a1a2'
해결법
-
==============================
1.일부 빠르며 더러운 코드 :
일부 빠르며 더러운 코드 :
class Wrapper: def __init__(self, obj): self.obj = obj self.callable_results = [] def __getattr__(self, attr): print("Getting {0}.{1}".format(type(self.obj).__name__, attr)) ret = getattr(self.obj, attr) if hasattr(ret, "__call__"): return self.FunctionWrapper(self, ret) return ret class FunctionWrapper: def __init__(self, parent, callable): self.parent = parent self.callable = callable def __call__(self, *args, **kwargs): print("Calling {0}.{1}".format( type(self.parent.obj).__name__, self.callable.__name__)) ret = self.callable(*args, **kwargs) self.parent.callable_results.append(ret) return ret class A: def __init__(self, val): self.val = val def getval(self): return self.val w = Wrapper(A(10)) print(w.val) w.getval() print(w.callable_results)
철저하지는 않을 수도 있지만 괜찮은 출발점이 될 수 있습니다.
-
==============================
2.당신이하고 싶은 것은이 질문과 아주 비슷합니다. 역순으로 예제 코드를 가져와야합니다. 즉, 메서드 호출의 반환 값을 기록하는 클래스를 만들고,보고 싶은 클래스를 그 클래스에서 상속 받도록 만듭니다. 어떤 것을 줄 것인가?
당신이하고 싶은 것은이 질문과 아주 비슷합니다. 역순으로 예제 코드를 가져와야합니다. 즉, 메서드 호출의 반환 값을 기록하는 클래스를 만들고,보고 싶은 클래스를 그 클래스에서 상속 받도록 만듭니다. 어떤 것을 줄 것인가?
class RetValWatcher(object): def __init__(self): self.retvals = [] def __getattribute__(self, name): attr = super(RetValWatcher, self).__getattribute__(name) if callable(attr): def wrapped(*args, **kwargs): retval = attr(*args, **kwargs) self.retvals.append(retval) return retval return wrapped else: return attr def getFinalRestult(self): return ''.join(self.retvals) class MyClass(RetValWatcher): def a(self): self.internal_z() return 'a1' def b(self): return 'b1' def internal_z(self): return 'z' x = MyClass() x.a() x.b() print x.getFinalResult() #'za1b1'
사소한 변경을하면이 메서드는 모든 RetValWatcher 인스턴스에 반환 값을 기록 할 수도 있습니다.
편집 : singularity의 의견에 의해 제안 된 변경 사항 추가
Edit2 : attr이 메서드가 아닌 경우를 처리하는 것을 잊었습니다 (다시 thx singularity).
-
==============================
3.당신은 꾸미기로 당신의 방법을 감쌀 수있다 :
당신은 꾸미기로 당신의 방법을 감쌀 수있다 :
#!/usr/bin/env python import inspect def log(func): def _logged(*args, **kw): print "[LD] func", func.__name__, "called with:", args, kw result = func(*args, **kw) print "[LD] func", func.__name__, "returned:", result return result return _logged class A(object): def __init__(self): for x in inspect.getmembers(self, (inspect.ismethod)): if not x[0].startswith('__'): setattr(self, x[0], log(getattr(self, x[0]))) def hello(self): print "Hello" def bye(self): print "Bye" return 0
이제 hello 나 bye를 호출하면 통화가 먼저 로그를 통과합니다.
a = A() a.hello() a.bye() # [LD] func hello called with: () {} # Hello # [LD] func hello returned: None # [LD] func bye called with: () {} # Bye # [LD] func bye returned: 0
from https://stackoverflow.com/questions/4723717/how-to-intercept-instance-method-calls by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] matplotlib를 사용하여 boxplot에 점 분산을 추가합니다. (0) | 2018.10.28 |
---|---|
[PYTHON] Python 3.4 : 전체 경로를 사용하여 모듈을 가져 오는 방법은 무엇입니까? (0) | 2018.10.28 |
[PYTHON] Keras : 모델을 저장하고 교육을 계속하는 방법은 무엇입니까? (0) | 2018.10.28 |
[PYTHON] 가로 세로 비율을 유지하면서 크기를 조정하고 세로 및 가로 이미지를 정확히 동일한 크기로 만드시겠습니까? (0) | 2018.10.28 |
[PYTHON] Boto ec2 인스턴스에서 셸 명령을 실행합니다. (0) | 2018.10.28 |