Есть ли способ удалить вложенный класс в Python? - PullRequest
0 голосов
/ 29 января 2020

Сценарий ниже пытается удалить вложенный класс Inner1 из класса Outer. Я получаю явную ошибку «Ошибка типа: невозможно удалить атрибут __class__». Тупик?

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)

1 Ответ

1 голос
/ 29 января 2020

Проблема в том, что следующая строка:

if isinstance(value, type):

Соответствует всему, что наследуется от type. Если вы хотите sh удалить только те внутренние классы, которые явно определены в декорированном классе, вы можете использовать что-то вроде этого:

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'

В качестве альтернативы вы можете сделать свой декоратор классом и указать это конкретно имена, которые вы хотите удалить. Например,

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'

Тем не менее, я не уверен, почему вы должны декорировать класс и определять внутренние классы, которые вы будете динамически удалять ... почему бы и нет ... просто не определить их вообще? : D

...