skulled skulled - 4 months ago 10
Python Question

Removing specific methods from child class which are inherited from parent class

The code is as below, just the basic structure:

class FooType(type):
def __new__( cls, name, bases, classdict ):
instance = type.__new__( cls, name, bases, classdict )
# What can I do here?
return instance

class FooBase( object, metaclass=FooType ):
def __init__( self ):
pass

class Foo( FooBase ):
def __init__( self, name ):
self.name = name

def method1( self ):
pass

def method2( self ):
pass

def specialmethod( self ):
pass

class A( Foo ):
pass

class B( Foo ):
pass

class C( Foo ):
_disallowed_methods = ['specialmethod']


What I want to do is that instances of class
C
should not have
specialmethod
, but that method should be available to instances
A
and
B
.

I can override this method in class
C
and raise an error, but I would prefer not to do this.

I realize I can add in code to check for
_disallowed_methods
in the
FooType
and on the basis of that check if the
instance
has any of them in the output of
dir(instance)
. But I cannot seem to remove the method from
__dict__
of
C
using any methods I have tried so far. The methods I tried are
delattr(instance, 'specialmethod')
, and
del instance.__dict__['specialmethod']
.

The
delattr
method results in "AttributeError: specialmethod", and the
del
method results in "TypeError: 'dict_proxy' object does not support item deletion"

Basically many different classes will inherit from
Foo
, but some of them should not have specific methods available to them like
C
which should not have
specialmethod
available to it.

What am I doing wrong? Or how else can I accomplish this?

mac mac
Answer

Or how else can I accomplish this?

You could achieve similar results by using multiple inheritance.

Move the methods that you would like only some of the children to have from Foo to ExtraFoo. Then use class A(Foo, ExtraFoo) or class C(Foo). This way you could even "reattach" a given method further down the children hierarchy.

If reattaching the method is not something you are interested to, then you could simply have ExtraFoo as a child of Foo (so: adding the methods, not detaching them) and have class A(ExtraFoo) and class C(Foo).