Preventing class methods from being defined

Bengt Richter bokr at oz.net
Tue Jan 17 19:12:09 CET 2006


On Mon, 16 Jan 2006 18:55:43 -0800, David Hirschfield <davidh at ilm.com> wrote:

>Thanks for this, it's a great list of the ways it can be done. Here's a 
Actually, your way is yet another ;-)

>bit more insight into the arrangement I'm trying to get:
>
>restrict = True
Why a global value? If it is to affect class instantiation, why not pass it
or a value to the constructor, e.g., C(True) or C(some_bool)?

>
>class A(object):
       ^--should that be R?
>    _restrict = ["test"]
>   
>    def _null(self, *args, **kws):
>        raise Exception,"not allowed to access"
>       
>    def test(self):
>        print "test restricted"
>   
>    def __init__(self):
>        if restrict:
>            for f in self._restrict:
>                setattr(self,f,self._null)
I assume you know that you are using a bound method attribute
on the instance to shadow the method of the class, for a per-instance
effect as opposed to an all-instances shared effect.

>       
>class C(R):
>    def __init__(self):
>        super(C,self).__init__()
>       
>    def test(self):
>        print "test from c"
>
>
>In this design, calling c.test() where c is an instance of C will raise 
>an exception. Now, the only thing I'd like is to not have to fill out 
>that _restrict list like that, but to have some function or something 
>that let's me say which methods are restricted in the same way you 
>define class methods or properties, i.e.:
>
>class A(object):
>    _restrict = []
>   
>    def _null(self, *args, **kws):
>        raise Exception,"not allowed to access"
>       
>    def test(self):
>        print "test restricted"
>    restrict(test)
>    #### this does some magic to insert "test" into the _restrict list
>
>
>I can't really find a way to make that work with descriptors, and it 
>can't just be a function call, because I won't know what object to get 
>the _restrict list from. Is there a way to refer to the class that "is 
>being defined" when calling a function or classmethod?
>So, ideas on how to accomplish that...again, greatly appreciated.

You can do it with a decorator, though it doesn't really do decoration,
just adding the decoratee to the associated _restrict list. You don't
have to factor out mkrdeco if you'r'e only defining the restrict decorator
in one class.

I changed A to R, and made the global restriction flag a constructor argument,
but you can easily change that back, either by using the global restricted
in R.__init__ as a global, or by passing it explicitly like c = C(restricted).

 >>> def mkrdeco(rlist):
 ...     def restrict(f):
 ...         rlist.append(f.func_name)
 ...         return f
 ...     return restrict
 ...
 >>> class R(object):
 ...     _restrict = []
 ...     restrict = mkrdeco(_restrict)
 ...     def _null(self, *args, **kws):
 ...         raise Exception,"not allowed to access"
 ...     def __init__(self, restricted):
 ...         if restricted:
 ...             for f in self._restrict:
 ...                 setattr(self,f,self._null)
 ...     @restrict
 ...     def test(self):
 ...         print "test restricted"
 ...
 >>> class C(R):
 ...    def __init__(self, restricted=False):
 ...        super(C,self).__init__(restricted)
 ...
 ...    def test(self):
 ...        print "test from c"
 ...
 >>> c = C(True)
 >>> c.test()
 Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 5, in _null
 Exception: not allowed to access
 >>> c2 = C(False)
 >>> c2.test()
 test from c
 >>> vars(c)
 {'test': <bound method C._null of <__main__.C object at 0x02EF3C4C>>}
 >>> vars(c2)
 {}
 >>> R._restrict
 ['test']
 
Still don't know what real application problem this is solving, but that's ok ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list