如何更改实时对象的isinstance()行为?

时间:2018-03-04 00:44:17

标签: python python-3.x class inheritance metaclass

我想更改实时python对象的isinstance行为。

一种解决方案是创建一个简单的包装器,如下所示,但我不喜欢它:

class Widget:
    def __init__(self, obj):
        self.inner_self = obj

lizard = ['head', 'nose', 'tail']
wlizard = Widget(lizard)
assert(isinstance(wlizard, Widget)) # no assertion error thrown 

我不喜欢这个特定的包装器,我们必须先从lizard中提取wlizard才能再次使用lizard

try:
    wlizard[0]
except:
    print('sorry, wlizard doesn\'t behave like a lizard')

lizard = wlizard.inner_self
print(lizard[0]) # works fine

我真正想要的是wlizard的行为与蜥蜴完全相同,只是isinstanceTrue返回wlizard,而lizard则返回false。 / p>

以下类型的作品,但有一些缺点:

class Widget:
    pass

def MakeAWidget(obj):

    class Blah(type(obj), Widget):
        pass
        # inherits type(obj)'s __init__ method

    wobj = Blah(obj)  # calls type(obj)'s copy constructor
    return wobj

一个问题是,只有当type(obj)的{​​{1}}方法不只是__init__()时才会有效;特别是,self可以接受__init__的实例,当它type(obj)时,它会将obj的属性复制到self。即使obj没有复制构造函数,我也想要一些有用的东西。类似下面的内容可能会强制存在复制构造函数:

import copy
class Blah(type(obj), Widget):
    def __init__(*args, **kwargs):
        if isinstance(args[0], type(obj)):
            self = copy.deepcopy(args[0])
            return self
        return super(type(self), self).__init__(*args, **kwargs)

但是,我宁愿不复制对象,只能就地修改它。 可能会出现以下内容,但我不确定__BLAH__会是什么:

obj = ['apple', 'pear', 'banana']
assert(not isinstance(obj, Widget)) # no error thrown    
obj.__BLAH__.append('Widget')
assert(isinstance(obj, Widget))  # no error thrown

1 个答案:

答案 0 :(得分:0)

这是我认为你想要的东西。 0函数动态创建一个类,该类派生自传递给它的wrap()参数的类,然后返回从中创建的该类的实例。这假设obj类支持复制构造(从相同或派生类的实例初始化)。

obj