Reputation: 383
The script below tries to remove the Inner1
nested class from the class Outer
. I get the clear error "TypeError: can't delete __class__ attribute". Dead end?
def Loader(cls):
for key in dir(cls):
value = getattr(cls, key)
if isinstance(value, type):
delattr(cls, key)
return cls
@Loader
class Outer:
class Inner1:
X = 1
print(Outer.Inner1.X)
Upvotes: 0
Views: 471
Reputation: 1070
The problem is that the following line:
if isinstance(value, type):
Is matching everything that inherits from type
. If you wish to only delete that inner classes that are explicitly defined in the decorated class, you could use something like this:
from inspect import isclass
def Loader(cls):
# vars returns the __dict__ attributes, so only names that are explicitely defined in cls.
for key, value in vars(cls).copy().items():
# If it is a class, delete it
if isclass(value):
delattr(cls, key)
return cls
@Loader
class Outer:
class Inner1:
X = 1
print(Outer.Inner1.X) # AttributeError: type object 'Outer' has no attribute 'Inner1'
An alternative, would be to make your decorator a class and tell it specifically the names you want to delete. E.g.
class Loader:
def __init__(self, *args):
# Store the given names to delete
self.names = args
def __call__(self, cls):
for name in self.names:
try:
delattr(cls, name)
except AttributeError:
pass
return cls
@Loader('Inner1', 'Inner2', 'etc')
class Outer:
class Inner1:
X = 1
print(Outer.Inner1.X) # AttributeError: type object 'Outer' has no attribute 'Inner1'
That said, I'm not sure why you would decorate a class and define inner classes that you will dynamically delete... why not... just not define them at all? :D
Upvotes: 1