如何在Python中为不可变类和可变类扩展和添加属性?

时间:2017-06-16 13:01:50

标签: python python-3.x super

我想创建一个类,如果继承任何其他兄弟类将设置一个' origin'实例上的属性。另一个兄弟类可能是可变的或不可变的。

我已经部分工作了。

class MyOrigin(object):
    def __new__(cls, *args, **kwargs):
        origin = kwargs.get('origin')
        if 'origin' in kwargs:
            del kwargs['origin']
        obj = super(MyOrigin, cls).__new__(cls, *args, **kwargs)
        obj.origin = origin
        return obj

    def __init__(self, *args, **kwargs):
        origin = kwargs.get('origin')
        if 'origin' in kwargs:
            del kwargs['origin']
        super(MyOrigin, self).__init__(*args, **kwargs)
        self.origin = origin

class MyListWithOrigin(MyOrigin, type(list())):
    pass
    # This works correctly

class MyDictWithOrigin(MyOrigin, type(dict())):
    pass
    # This works correctly too

class MyStringWithOrigin(MyOrigin, str):
    pass
    # This doesnt work if MyOrigin defines __init__

基本上,如果我在__init__上定义MyOrigin,那么super(MyOrigin, self).__init__会尝试调用object.__init__(因为str是不可变的,所以没有str.__init__ 1}})第一个参数失败并且TypeErrorobject.__init__并不参与。

目前,我创建了两个类(MyOriginMutable和MyOriginImmutable),并在创建MyStrWithOrigin或MyListWithOrigin等时从中进行选择。是否有某种方法可以检测哪个类super()从运行之前获取方法,以便我可以检测到并且不用args调用object.__init__

为清楚起见,这个例子有效,但是有没有办法在没有两个独立的Mutable和Immutable类的情况下做到这一点?

class MyOriginImmutable(object):
    def __new__(cls, *args, **kwargs):
        origin = kwargs.get('origin')
        if 'origin' in kwargs:
            del kwargs['origin']
        obj = super(MyOriginImmutable, cls).__new__(cls, *args, **kwargs)
        obj.origin = origin
        return obj


class MyOriginMutable(object): # Edited so that it DOES NOT inherit from MyOriginImmutable
    def __init__(self, *args, **kwargs):
        # We define __init__ only for mutable classes
        origin = kwargs.get('origin')
        if 'origin' in kwargs:
            del kwargs['origin']
        super(MyOriginMutable, self).__init__(*args, **kwargs)
        self.origin = origin


class MyOriginString(MyOriginImmutable, str):
    """A custom string class to hold origin"""
    pass


class MyOriginList(MyOriginMutable, type(list())):
    """A custom list class to hold origin"""
    pass


class MyOriginDict(MyOriginMutable, type(dict())):
    """A custom dict class to hold origin"""
    pass

if __name__ == '__main__':
    # Testing
    try:
        line = MyOriginString('some string', origin=('somewhere',))
        print(line)
        assert line.origin == ('somewhere',)
        assert line == 'some string'
    except Exception as e:
        print("String like failed")
        # raise e

    try:
        list_like = MyOriginList(['some', 'list'], origin=('somewhere',))
        print(list_like)
        assert list_like.origin == ('somewhere',)
        assert list_like == ['some', 'list']
    except Exception as e:
        print("List like failed")
        # raise e

    try:
        dict_like = MyOriginDict({'some': 'dict'}, origin=('somewhere',))
        print(dict_like)
        assert dict_like.origin == ('somewhere',)
        assert dict_like == {'some': 'dict'}
    except Exception as e:
        print("Dict like failed")
        raise e

0 个答案:

没有答案