2011-09-22 3 views
0

파이썬 isinstance 함수는 내부적으로 어떻게 작동합니까? 결과를 변경하기 위해 할 수있는 일이 있나요? 예를 들어 클래스 내부에 특수 함수를 정의 할 수 있습니까? 혼합 여기에 적절하지 않을 것 제외데코레이터로 'isinstance'작업하기

class Decorator: 
    def __init__(self, decorated): 
     self._decorated = decorated 

    def __call__(self): 
     return self._decorated() 

@Decorator 
class Foo: 
    pass 

f = Foo() 

# How can I make this be true? 
isinstance(f, Foo) 

Decorator 역할을 믹스 인 같은 거의 : 여기 내 사용 사례입니다. 위의 코드가 작동하도록 할 수있는 방법이 있습니까? 위의 코드와

def Decorator(decorated): 
    class Dec(decorated): 
     def __call__(self): 
      print 'in decorated __call__' 
      return decorated.__call__(self) 
    return Dec 

@Decorator 
class Foo(object): 
    def __call__(self): 
     print 'in original __call__' 

f = Foo() 

# How can I make this be true? 
print isinstance(f, Foo) 

: 다음에 대한

    isinstance(f, Foo)
TypeError: isinstance() arg 2 must be a type or tuple of types

+3

을 당신이 실제로이 달성하려고하는 무엇을 : 당신이 Foo()를 사용하는 경우의 동작을 수정하고 있기 때문에, 그때는 아마 푸의 __init__, 다음과 같을 수있는을 수정하려면? –

+0

당신은 당신의 데코레이터가하는 것을 우리에게 말하지 않았기 때문에, 어떤 것이 효과가 있을지 알기가 어렵습니다. 데코레이터로 클래스 자체의 속성을 변경 한 다음 클래스를 반환하거나 데코레이터 대신 메타 클래스로 클래스를 다시 작성하십시오. – agf

답변

1

귀하의 예에서 Foo은 클래스가 아닙니다.

이 코드 : FooDecorator 클래스의 인스턴스임을 의미

class Foo: 
    pass 
Foo = Decorator(Foo) 

:

@Decorator 
class Foo: 
    pass 

는 동일하다. Foo은 clas 또는 유형이 아니기 때문에 isinstance이 불평합니다.

+1

이것은 "주목해야한다"라고 말하면서, isinstance 작업을하는 방법을 알려주지 않습니다. – agf

4

방법 : 나는 또한 isinstance 라인은 또한 다음과 같은 오류주는 있음을 유의

  • isinstance(f, Foo) 작품;
  • f()은 데코 레이팅 된 메서드를 호출 한 다음 원래 메서드로 전달합니다.

기본 개념은 장식 Foo 여전히 클래스, 또한 장식 Foo 원래 Foo서브 클래스이 있는지 확인 있는지 확인하는 것입니다.

P. 이 모든 것의 목적은 내게 완전히 명확하지 않습니다. 메타 클래스가 당신이하려는 것을 달성하는 더 좋은 방법 일 수 있습니다.

0

Foo이 반환하는 개체 유형을 가져올 수 없습니다. Foo을 호출하지 않습니다.

isinstance은 인스턴스이므로 Decorated의 두 번째 인수에 대해 불만을 나타냅니다. Foo은 클래스와 비슷하지만 실제로는 호출 할 수있는 객체이며 클래스가 아닙니다. 당신이 당신의 문제를/재고 해결하는 데 도움이 될 것입니다

아마 다음 : 클래스를 장식 할 때, 종종 장식 반환 값도 형식이어야하기에 유용하거나 바람직의

>>> isinstance(f, Foo._decorated) 
True 
0

; 이를 달성하는 가장 확실한 방법은 데코레이터가 새로운 클래스를 직접 생성하고 반환하도록하는 것입니다.

해당 기능은 이미 메타 클래스로 처리됩니다. 실제로 장식 클래스보다 메타 클래스가 훨씬 강력합니다. 장식 클래스가 생성되기 전에 새 클래스를 설명 할 수 있기 때문입니다.

또 다른 옵션은 전달 된 동일한 개체를 반환하는 것입니다. 그러나 약간의 변화와 함께. 데코레이터를 더 잘 사용할 수 있습니다. 데코레이터를 중첩 할 때 잘 작동하기 때문입니다.

>>> def Decorator(cls): 
...  assert isinstance(cls, type) 
...  try: 
...   old_init = cls.__init__.im_func 
...  except AttributeError: 
...   def old_init(self): pass 
...  def new_init(self): 
...   # do some clever stuff: 
...   old_init(self) 
...  cls.__init__ = new_init 
...  return cls 
... 
>>> @Decorator 
... class Foo(object): 
...  def __init__(self): pass 
... 
>>> @Decorator 
... class Bar(object): 
...  pass 
... 
>>> f = Foo() 
>>> isinstance(f, Foo) 
True