Vince M
Vince M

Reputation: 1186

Python: How to share class variable logic across different classes?

I have the following code:

from abc import ABC

class Employee(ABC):
  count = 0
  def __init__(self, name: str):
    self.name = name
    Employee.count += 1

class Engineer(Employee):
  count = 0
  def __init__(self, name: str):
    super().__init__(name)
    Engineer.count +=1
 

class Manager(Employee):
  count = 0
  def __init__(self, name: str):
    super().__init__(name)
    Manager.count += 1

Engineer(name='Alice')
Engineer(name='Bob')
Manager(name='Charlie')

print('number of employee', Employee.count)
print('number of engineer', Engineer.count)
print('number of manager', Manager.count)

This code works but it has code duplication (count logic is duplicated across all classes). Is there a way to avoid this code duplication (if possible a way that does not remove VS Code autocomplete)?

Upvotes: 0

Views: 68

Answers (1)

JarroVGIT
JarroVGIT

Reputation: 5279

UPDATE This would keep counters of any class and subclass, on the class itself. Again I would like to emphasise that holding dynamic data on a class level is probably not a great idea.

from abc import ABC
from inspect import getmro


class Employee(ABC):
    direct_count = 0
    direct_and_indirect_count = 0

    def __init__(self, name: str):
        self.name = name
        for index, cls in enumerate(getmro(type(self))):
            if cls == ABC:
                break
            elif index == 0:
                cls.direct_count += 1
                cls.direct_and_indirect_count += 1
            else:
                cls.direct_and_indirect_count += 1


class Engineer(Employee):
    def __init__(self, name: str):
        super().__init__(name)


class Manager(Employee):
    def __init__(self, name: str):
        super().__init__(name)


class SubManager(Manager):
    def __init__(self, name: str):
        super().__init__(name)


SubManager(name="submanager")
Manager(name="Charlie")
Engineer(name="Alice")
Engineer(name="Bob")

print("number of direct employee", Employee.direct_count)
print("number of direct + indirect employee", Employee.direct_and_indirect_count)

print("number of direct engineer", Engineer.direct_count)
print("number of direct + indirect engineer", Engineer.direct_and_indirect_count)

print("number of direct manager", Manager.direct_count)
print("number of direct + indirect manager", Manager.direct_and_indirect_count)

print("number of direct submanager", SubManager.direct_count)
print("number of direct + indirect submanager", SubManager.direct_and_indirect_count)

ORIGINAL ANSWER

I would recommend not using a class as holder of non-static information, but this would do what you like:

from abc import ABC


class Employee(ABC):
    count = 0
    employee_count = 0

    def __init__(self, name: str):
        self.name = name
        type(self).count += 1
        Employee.employee_count += 1


class Engineer(Employee):
    def __init__(self, name: str):
        super().__init__(name)


class Manager(Employee):
    def __init__(self, name: str):
        super().__init__(name)


Manager(name="Charlie")
Engineer(name="Alice")
Engineer(name="Bob")

print("number of employee", Employee.employee_count)
print("number of engineer", Engineer.count)
print("number of manager", Manager.count)

Upvotes: 1

Related Questions