From e9ae8a56947593860a4b23d1442d77700232909c Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Sat, 2 Dec 2000 04:11:32 +0000 Subject: [PATCH] Talk about PEP 213, which is related and can be (mostly) implemented using the __findattr__() hook. --- pep-0231.txt | 69 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/pep-0231.txt b/pep-0231.txt index cf81ac773..99ecdf5bd 100644 --- a/pep-0231.txt +++ b/pep-0231.txt @@ -110,6 +110,16 @@ Key Differences with the Existing Protocol is used. +Related Work + + PEP 213 [9] describes a different approach to hooking into + attribute access and modification. The semantics proposed in PEP + 213 can be implemented using the __findattr__() hook described + here, with one caveat. The current reference implementation of + __findattr__() does not support hooking on attribute deletion. + This could be added if it's found desirable. See example below. + + Examples One programming style that this proposal allows is a Java @@ -368,9 +378,9 @@ Examples assert 0, 'AttributeError expected' - And finally, C++-like access control can also be accomplished, - although less cleanly because of the difficulty of figuring out - what method is being called from the runtime call stack: + C++-like access control can also be accomplished, although less + cleanly because of the difficulty of figuring out what method is + being called from the runtime call stack: import sys import types @@ -520,6 +530,58 @@ Examples assert b.getname() == 'A' + Here's an implementation of the attribute hook described in PEP + 213 (except that hooking on attribute deletion isn't supported by + the current reference implementation). + + class Pep213: + def __findattr__(self, name, *args): + hookname = '__attr_%s__' % name + if args: + op = 'set' + else: + op = 'get' + # XXX: op = 'del' currently not supported + missing = () + meth = getattr(self, hookname, missing) + if meth is missing: + if op == 'set': + return setattr(self, name, *args) + else: + return getattr(self, name) + else: + return meth(op, *args) + + + def computation(i): + print 'doing computation:', i + return i + 3 + + + def rev_computation(i): + print 'doing rev_computation:', i + return i - 3 + + + class X(Pep213): + def __init__(self, foo=0): + self.__foo = foo + + def __attr_foo__(self, op, val=None): + if op == 'get': + return computation(self.__foo) + elif op == 'set': + self.__foo = rev_computation(val) + # XXX: 'del' not yet supported + + x = X() + fooval = x.foo + print fooval + x.foo = fooval + 5 + print x.foo + # del x.foo + + Reference Implementation The reference implementation, as a patch to the Python core, can be @@ -537,6 +599,7 @@ References [6] http://www.python.org/doc/essays/metaclasses/ [7] http://www.foretec.com/python/workshops/1998-11/dd-ascher-sum.html [8] http://www.python.org/doc/howto/rexec/rexec.html + [9] http://python.sourceforge.net/peps/pep-0213.html Copyright