首页 > 解决方案 > 创建“视图对象”的模式

问题描述

在 Python 中创建自定义“视图对象”是否有任何推荐的模式,通过该模式可以查看其他对象,但不能修改?就像,和返回的视图对象一样。dict.keys()dict.values()dict.items()

特别是,我想知道对象的视图对象v是否o应该包含(引用)o,或者只是分离的方法o,如果给定对象的视图对象o应该是唯一的并且是的一部分o,视图类如何类的对象C应该与C...相关

更新。 我认为这可能是仅提供对部分界面的访问权限的特殊情况。到目前为止,我提出了一种装饰器方法:

class _AccessorBase:
    __slots__ = ("owner")

    def __init__(self, owner):
        self.owner = owner

def _make_delegating_method(name, method=None):
    if method is None:
        method = name

    if isinstance(method, str):
        def delegating_method(self, *args, **kwargs):
            return getattr(self.owner, method)(*args, **kwargs)

    elif callable(method):
        def delegating_method(self, *args, **kwargs):
            return method(self.owner, *args, **kwargs)

    else:
        raise TypeError

    delegating_method.__name__ = name
    return delegating_method

def withaccessor(access_name, *method_names, **methods):
    class Accessor(_AccessorBase):
        __slots__ = ()

    for name in method_names:
        if name in methods:
            raise ValueError("name '{}' is given twice".format(name))
        methods[name] = name

    for name, method in methods.items():
        setattr(Accessor, name, _make_delegating_method(name, method))

    access_member_attr_name = "_" + access_name

    def access_method(self):
        return getattr(self, access_member_attr_name)

    access_method.__name__ = access_name

    def decor(cls):
        class C(cls):
            __doc__ = cls.__doc__
            __slots__ = access_member_attr_name

            def __init__(self, *args, **kwargs):
                setattr(self, access_member_attr_name, Accessor(self))
                return super(__class__, self).__init__(*args, **kwargs)

        C.__name__ = cls.__name__
        setattr(C, access_name, access_method)
        return C

    return decor

# Tests
if __name__ == "__main__":
    def sub(self):
        return self.a - self.b

    @withaccessor("view", "sum", product="prod", difference=sub)
    class C:
        __slots__ = ("a", "b")

        def __init__(self, a, b):
            self.a = a
            self.b = b

        def sum(self):
            return self.a + self.b

        def prod(self):
            return self.a * self.b

    o = C(2, 3)
    v = o.view()
    assert o.view() is v
    assert v.sum() == 5
    assert v.product() == 6
    assert v.difference() == -1
    o.a = 0
    assert v.sum() == 3
    assert v.product() == 0
    assert v.difference() == -3

标签: pythonobjectoopdesign-patterns

解决方案


推荐阅读