Python 制作';iInstance';与装饰师合作

Python 制作';iInstance';与装饰师合作,python,decorator,isinstance,Python,Decorator,Isinstance,Pythonisinstance函数如何在内部工作?我可以做些什么来改变它的结果,比如在类中定义一个特殊的函数或者其他什么?以下是我的用例: class Decorator: def __init__(self, decorated): self._decorated = decorated def __call__(self): return self._decorated() @Decorator class Foo: pass

Python
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
的行为几乎像一个混音器,只是混音器在这里并不合适。有什么方法可以让上面的代码工作吗?我还应该注意,
isinstance
行也给出了以下错误:

isinstance(f,Foo)
TypeError:isinstance()arg 2必须是类型或类型的元组


那么以下内容如何:

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)
    works
  • f()
基本思想是确保修饰的
Foo
仍然是一个类,并且还确保修饰的
Foo
是原始
Foo
的子类


另外,我并不完全清楚这一切的目的;元类可能是实现您想要做的事情的更好方法。

问题在于您的示例中的
Foo
不是类

此代码:

@Decorator
class Foo:
    pass
相当于:

class Foo:
    pass
Foo = Decorator(Foo)

这意味着
Foo
是类
Decorator
的实例。因为
Foo
不是clas或类型,
isinstance
会抱怨。

如果不调用
Foo
就无法获取
Foo
返回的对象类型

isinstance
抱怨它的第二个参数,因为它是一个实例,在您的例子中是
修饰的实例。虽然您认为Foo
像一个类,但实际上它只是一个可调用的对象,而不是一个类

也许下一步将帮助您重新思考/解决您的问题:

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

在装饰类时,装饰后的返回值也是类型通常是有用的或可取的;实现这一点最明显的方法是让decorator构造并直接返回一个新类

该功能已经由元类处理;事实上,元类比装饰器更强大,因为在构建装饰类之前,您就可以描述新类了

另一个选项是返回传入的相同对象;但是有一些变化。这对于装饰者来说是一个更好的用途,因为当你嵌套装饰者时,它工作得很好。由于您在使用
Foo()
时正在修改行为,因此您可能需要修改Foo的
\uuuu init\uuuu
,它可能如下所示:

>>> 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

你到底想用这个做什么?你还没有告诉我们你的装饰师是做什么的,所以很难知道什么会起作用。考虑用装饰器来改变类本身的属性,然后返回类,或者用元元组来代替类,而不是修饰器。这只解决了他的“应该注意”,它没有告诉他如何使IS实例工作。