:mod:`zope.proxy` Narrative Documentation ========================================= Subclassing :class:`ProxyBase` ------------------------------ If you subclass a proxy, instances of the subclass have access to data defined in the class, including descriptors. Your subclass instances don't get instance dictionaries, but they can have slots. .. doctest:: >>> from zope.proxy import ProxyBase >>> class MyProxy(ProxyBase): ... __slots__ = 'x', 'y' ... ... def f(self): ... return self.x >>> l = [1, 2, 3] >>> p = MyProxy(l) You can use attributes defined by the class, including slots: .. doctest:: >>> p.x = 'x' >>> p.x 'x' >>> p.f() 'x' You can also use attributes of the proxied object: .. doctest:: >>> p [1, 2, 3] >>> p.pop() 3 >>> p [1, 2] Using get descriptors in proxy classes -------------------------------------- A non-data descriptor in a proxy class doesn't hide an attribute on a proxied object or prevent writing the attribute. .. doctest:: >>> class ReadDescr(object): ... def __get__(self, i, c): ... return 'read' >>> from zope.proxy import ProxyBase >>> class MyProxy(ProxyBase): ... __slots__ = () ... ... z = ReadDescr() ... q = ReadDescr() >>> class MyOb: ... q = 1 >>> o = MyOb() >>> p = MyProxy(o) >>> p.q 1 >>> p.z 'read' >>> p.z = 1 >>> o.z, p.z (1, 1) Marking proxy attributes as non-overridable ------------------------------------------- Normally, methods defined in proxies are overridden by methods of proxied objects. This applies to all non-data descriptors. The non_overridable function can be used to convert a non-data descriptor to a data descriptor that disallows writes. This function can be used as a decorator to make functions defined in proxy classes take precedence over functions defined in proxied objects. .. doctest:: >>> from zope.proxy import ProxyBase >>> from zope.proxy import non_overridable >>> class MyProxy(ProxyBase): ... __slots__ = () ... ... @non_overridable ... def foo(self): ... return 'MyProxy foo' >>> class MyOb: ... def foo(self): ... return 'MyOb foo' >>> o = MyOb() >>> p = MyProxy(o) >>> p.foo() 'MyProxy foo' Changing the proxied object --------------------------- .. doctest:: >>> from zope.proxy import ProxyBase >>> from zope.proxy import setProxiedObject, getProxiedObject >>> class C(object): ... pass >>> c1 = C() >>> c2 = C() >>> p = ProxyBase(c1) `setProxiedObject()` allows us to change the object a proxy refers to, returning the previous referent: .. doctest:: >>> old = setProxiedObject(p, c2) >>> old is c1 True >>> getProxiedObject(p) is c2 True The first argument to `setProxiedObject()` must be a proxy; other objects cause it to raise an exception: .. doctest:: >>> try: ... setProxiedObject(c1, None) ... except TypeError: ... print("TypeError raised") ... else: ... print("Expected TypeError not raised") TypeError raised