如何更改活动对象的isinstance()行为?

问题描述 投票:-1回答:1

我想改变isinstance的行为python对象的行为。

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

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。

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

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)__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
python python-3.x class inheritance metaclass
1个回答
0
投票

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

def wrap(obj):
    class MetaClass(type):
        def __new__(mcls, classname, bases, classdict):
            wrapped_classname = '_%s_%s' % ('Wrapped', type(obj).__name__)
            return type.__new__(mcls, wrapped_classname, (type(obj),)+bases, classdict)

    class Wrapped(metaclass=MetaClass):
        pass

    return Wrapped(obj)

lizard = ['head', 'nose', 'tail']
wlizard = wrap(lizard)
print(type(wlizard).__name__)     # -> _Wrapped_list
print(isinstance(wlizard, list))  # -> True

try:
    wlizard[0]
except Exception as exc:
    print(exc)
    print("sorry, wlizard doesn't behave like lizard")
else:
    print('wlizard[0] worked')
© www.soinside.com 2019 - 2024. All rights reserved.