Preventing class methods from being defined

Alex Martelli aleax at mail.comcast.net
Sun Jan 15 22:35:45 EST 2006


David Hirschfield <davidh at ilm.com> wrote:

> Here's a strange concept that I don't really know how to implement, but
> I suspect can be implemented via descriptors or metaclasses somehow:

Yeah, a custom metaclass will do it, easily.

> I want a class that, when instantiated, only defines certain methods if
> a global indicates it is okay to have those methods. So I want something
> like:
> 
> global allow
> allow = ["foo","bar"]
> 
> class A:
>     def foo():
>         ...
> 
>     def bar():
>         ...
> 
>     def baz():
>         ...
> 
> any instance of A will only have a.foo() and a.bar() but no a.baz() 
> because it wasn't in the allow list.
> 
> I hope that makes sense.

Sure.  If you don't need to worry about inheritance, and want to
'snapshot' the set of methods and other class attributes based on the
value of 'allow' at the time the class statement executes:

class meta_only_allowed(type):
    def __new__(mcl, name, bases, cdict):
        for k in cdict.keys():
            if k not in allow:
                del cdict[k]
        return super(mcl, meta_only_allowed).__new__(
                             mcl, name, bases, cdict)

[[untested, but I hope the concept is clear]].

If you want the value of 'allow' at class-*instantiation* time to be in
control, then what you need to override is __call__ rather than __new__.
You'll need to make a special class on the fly for the purpose (make
sure you memoize it to avoid needless duplication).

If you do need to worry about inheritance, and want to disallow
inherited methods as well, then you need to loop over all methods in
base classes (use standard library module inspect for that) and
construct an artificial dict, then drop the 'bases' and use an empty
tuple of bases for the supercall (real inheritance doesn't let you
"hide" methods, or other superclass attributes, ever).

Etc, etc -- it's most surely possible to do what you want, whatever what
you DO want is exactly!-)


Alex



More information about the Python-list mailing list