python - 创建“视图对象”的模式
问题描述
在 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