Preventing class methods from being defined
Bengt Richter
bokr at oz.net
Tue Jan 17 13:12:09 EST 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