2012-12-08 3 views
2

다음 코드를 사용합니다. 대부분의 코드가 어색하고 혼란 스럽거나 상황이 복잡해 보이지만 대부분은 훨씬 큰 코드의 부분을 보여주기위한 것입니다. 에 문제가있다. 조심스럽게__getattr__을 사용하여 호출 매개 변수와 인수에 액세스하는 방법

# The following part is just to demonstrate the behavior AND CANNOT BE CHANGED UNDER NO CIRCUMSTANCES 
# Just define something so you can access something like derived.obj.foo(x) 
class Basic(object): 
    def foo(self, x=10): 
     return x*x 

class Derived(object): 
    def info(self, x): 
     return "Info of Derived: "+str(x) 
    def set(self, obj): 
     self.obj = obj 

# The following piece of code might be changed, but I would rather not 
class DeviceProxy(object): 
    def __init__(self): 
     # just to set up something that somewhat behaves as the real code in question 
     self.proxy = Derived() 
     self.proxy.set(Basic()) 

    # crucial part: I want any attributes forwarded to the proxy object here, without knowing beforehand what the names will be 
    def __getattr__(self, attr): 
     return getattr(self.proxy, attr) 

# ====================================== 
# This code is the only I want to change to get things work 

# Original __getattr__ function 
original = DeviceProxy.__getattr__ 

# wrapper for the __getattr__ function to log/print out any attribute/parameter/argument/... 
def mygetattr(device, key): 
    attr = original(device, key) 
    if callable(attr): 
     def wrapper(*args, **kw): 
      print('%r called with %r and %r' % (attr, args, kw)) 
      return attr(*args, **kw) 
     return wrapper 
    else: 
     print "not callable: ", attr 
     return attr 

DeviceProxy.__getattr__ = mygetattr 


# make an instance of the DeviceProxy class and call the double-dotted function 
dev = DeviceProxy() 
print dev.info(1) 
print dev.obj.foo(3) 

내가 원하는 모든 방법 등등 모든 인수/매개 변수를 인쇄 할 수 있도록 DeviceProxy 호출 잡을 것입니다 읽어 보시기 바랍니다. 주어진 예에서 이것은 info(1)을 호출 할 때 훌륭하게 작동합니다. 모든 정보가 인쇄됩니다. 그러나 이중 점으로 찍은 함수 dev.obj.foo(3)을 호출하면이 호출 가능하지 않다는 메시지 만 표시됩니다.

두 번째 경우에도 내 정보를 얻을 수 있도록 위 코드를 어떻게 수정할 수 있습니까? === 아래의 코드 만 수정할 수 있습니다.

+0

문제는'dev.obj.foo (3)'에 대해,'devget' 장치와'obj' 장치로'mygetattr'가 호출되고 있다는 것입니다. 실제로는 호출 할 수 없습니다. 필요한 것은 디바이스'obj'와 키'foo'로 호출하는 방법을 찾는 것입니다. (그 방법은 나에게는 분명하지 않습니다.) – khagler

+0

네, 그게 정확히 문제입니다. 나는 래퍼 (wrapper) 같은 다른 레이어가 필요할 것 같지만, 얼마나 많은 것들이 있는지 확실히 알지 못한다. 'device.service.info.version.firmware'와 같은 호출이있을 수 있습니다. – Alex

+0

내가 알 수있는 한, "Basic"과 "Derived"는 이름에도 불구하고 상속을 사용하지 않습니다. –

답변

3

당신은 dev에 불과 __getattr__을 가지고 있고 당신은 당신이 dev.obj.foo을 수행 할 때 foo에 액세스 할 수 있도록,이 __getattr__ 내에서 원하는. 불가능합니다. 속성 액세스는 전체적으로 액세스되는 점으로 구분 된 함수가 아닙니다. 속성 액세스 순서 (점)는 왼쪽에서 오른쪽으로 한 번에 하나씩 평가됩니다. dev.obj에 액세스 할 때 나중에 foo에 액세스한다는 것을 알 수있는 방법이 없습니다. dev.__getattr__ 메서드는 dev에 액세스하는 특성 만 알고 있으며 나중에 액세스 할 수있는 특성은 아닙니다.

원하는 것을 얻는 유일한 방법은 obj에 배치 동작을 포함시키는 것입니다. "Base"/ "Derived"클래스를 수정할 수 없으므로 그렇게 할 수 없다고 말합니다. 이론적으로 DeviceProxy.__getattr__에 액세스 된 속성의 실제 값을 반환하지 않고 해당 객체를 다른 프록시로 랩핑하고 프록시를 반환 할 수 있습니다. 그러나이 방법은 조금 까다 롭고 코드를 이해하기 어렵고 디버그하기가 어려울 수 있습니다. 많은 수의 객체가 씬 프록시로 래핑 된 상태로 끝날 수 있기 때문입니다.