Подсчет экземпляров правильно с подклассами - PullRequest
0 голосов
/ 13 мая 2018

Я экспериментирую с ООП и пытаюсь реализовать наследование некоторых классов со счетчиками количества экземпляров каждого класса и подкласса.

Я хотел бы иметь переменную класса, которая увеличивается в методе класса __init__, чтобы при создании экземпляра класса счетчик для этого класса и для всех его родительских и родительских классов увеличивался .

Тем не менее, после ряда попыток я пытаюсь добиться этого, изолируя счетчики для каждого подкласса от родительского класса.

Скажем, у меня есть классы "Cls", "SubCls" и "SubSubCls", как показано ниже.

class Cls():
    count = 0

    def __init__(self):
        #general init stuff
        self.__class__.count += 1

class SubCls(Cls):
    pass

class SubSubCls(SubCls):
    pass

Мне бы хотелось следующее поведение:

a = Cls()
SubSubCls.count #returns 0
SubCls.count    #returns 0
Cls.count       #returns 1

b = SubCls()
SubSubCls.count #returns 0
SubCls.count    #returns 1
Cls.count       #returns 2

c = SubSubCls()
SubSubCls.count #returns 1
SubCls.count    #returns 2
Cls.count       #returns 3

Рациональным для этого является то, что если Cls - это что-то вроде 'Entity', SubCls - это 'Physical Entity', а SubSubCls - это 'Tree', и я создаю один экземпляр Tree, у меня теперь есть 1 Tree, 1 Physical Entity, 1 Сущность - даже если они все в одном объекте.

Лучшее, что я до сих пор придумал, это следующее:

class Cls():
    count = 0

    def __init__(self):
        #general init stuff
        self.inc_count()

    def inc_count(self):
        Cls.count += 1
        super().inc_count() #removing this avoids AttributeError but means having
                            # unique methods for inc_count in all SubCls level Classes
class SubCls(Cls):
    count = 0

    def __init__(self):
        super().__init__()
        #unique init stuff

    def inc_count(self):
        SubCls.count += 1
        super().inc_count()        


class SubSubCls(SubCls):
    count = 0

    def __init__(self):
        super().__init__()
        #unique init stuff

    def inc_count(self):
        SubSubCls.count += 1
        super().inc_count()

Это имеет правильное поведение, но я чувствую, что наследство должно быть лучше. Я не хочу определять inc_count() отдельно для каждого класса, когда они очень похожи - я хочу, чтобы здесь все было масштабируемым.

  1. Я могу видеть случаи с множественным наследованием как осложнение в будущем, но я пока оставлю это в покое.

  2. Я уверен, что смогу обойти super().inc_count() в определении для Cls, вызывая AttributeError, либо используя try и исключения, либо определив MetaCls выше Cls - так что я не слишком волнуюсь там.

  3. Однако я почти уверен, что не смогу просто заменить Cls.count += 1, SubCls.count += 1 и SubSubCls.count += 1 в определении inc_count() на self.__class__.count += 1 или type(self).count += 1, так как это просто приведите к действию на счетчик «самого низкого» класса экземпляра несколько раз. (т.е. создание экземпляра SubSubCls приведет к увеличению общего количества SubSubCls на 3, а количество его родительских классов останется неизменным).

Чтобы решить эту проблему, существует ли абстрактный способ ссылки на класс, от которого унаследован метод? Так что мой inc_count определен только на верхнем уровне как что-то вроде этого (и унаследовано всеми подклассами).

def inc_count(self):
    DirectParentClassDefinedAtRunTime.count += 1
    super().inc_count()

Очевидно, что если я собираюсь получить желаемый эффект совершенно неправильно, я буду рад любым указателям. Мой единственный предыдущий набег в ООП был с Flash в возрасте 12 лет - очень давно.

...