As an exercise I'm attempting to write a metaclass that causes an exception to be thrown whenever a user tries to access 'attributes' (in the traditional sense) via a direct reference.
Consider: class X( object ): y = 'private value' def get_y( self ): return self.y Normally one can access y here via: X().y or X().get_y() I want the former case, however, to throw an exception. I figured the way to do this would be to introduce a metaclass that overrides the default __getattrribute__ call and throws an exception. So my first attempt was something like: class XType( type ): def __my_getattribute__( self, name ): raise AttributeError() def __init__( klass, name, bases, dict ): super( XType, klass ).__init__( name, bases, dict ) setattr( klass, '__getattribute__', klass.__my_getattribute__ ) But whereas the X().y attribute behaves as I intend, the X().get_y() returns raises that exception as well: >>> X().y Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in __my_getattribute__ AttributeError >>> X().get_y() Traceback (most recent call last): File "<stdin>", line 1, in ? File "<stdin>", line 3, in __my_getattribute__ AttributeError So it looks as if 'attribute' here means any key in self.__dict__, whether referenced via self.var, self.__dict__['var'] (because this references __dict__), or getattr( self, 'var' ) (which is the same as a direct self.var access, I believe). So I tried: class XType( type ): def __my_getattribute__( self, name ): if name != '__dict__': raise AttributeError() return super( self.__class__, self ).__getattribute__( name ) def __init__( klass, name, bases, dict ): super( XType, klass ).__init__( name, bases, dict ) setattr( klass, '__getattribute__', klass.__my_getattribute__ ) This allows me to access X().__dict__ directly (and then X().__dict__['y']), but it still limits caller access to the get_y() method. It sounds then like the "solution" will be to check whether the name referenced is called __dict__ or is a method or function type, otherwise throw the exception, and to ensure all internal calls are handled via self.__dict__[name] not self.name. Something like: import types class XType( type ): def __my_getattribute__( self, name ): if name != '__dict__' and not isinstance( self.__dict__[name], types.FunctionType ): raise AttributeError() return super( self.__class__, self ).__getattribute__( name ) def __init__( klass, name, bases, dict ): super( XType, klass ).__init__( name, bases, dict ) setattr( klass, '__getattribute__', klass.__my_getattribute__ ) Of course this is imperfect as a user can simply bypass the __getattribute__ call too and access __dict__ directly, but it's closer to what I was thinking. The problem is the return value for functions is not bound - how do I bind these to the associated instance? (Caveat - I am not sure whether using __get__ itself in lieu of __getattribute__ would be a better solution; but I would like to see how binding would be done here for general knowledge.) Thanks. Adam -- http://mail.python.org/mailman/listinfo/python-list