0

I have a parent class, SongStat, with attributes that are supposed to be separate among the instances. I also have a child of that class called SongStatCount, and two children of that class called StatArtistCount and StatAlbumCount.

class SongStat(ABC):
  output = []
  statName = ""

  @abstractmethod
  def process_song(self, song):
    pass

  @abstractmethod
  def calculate_final(self):
    pass

  @abstractmethod
  def get_output(self, n):
    pass


class SongStatCount(SongStat):
  countDict = {}
  keysList = []
  label = ""

  def process_song(self, songParts):
    for part in songParts:
      if part in self.countDict:
        self.countDict[part] = self.countDict[part] + 1
      else:
        self.countDict[part] = 1

  def calculate_final(self):
    self.keysList = list(self.countDict.keys())
    self.keysList.sort(reverse=True, key=lambda x: self.countDict[x])

  def get_output(self, n):
    self.calculate_final()
    self.output = []
    cutIndex = min(len(self.keysList), n)
    self.keysList = self.keysList[:cutIndex]
    self.output.append(f"Top {n} {self.label}:\n")
    for i, key in enumerate(self.keysList):
      self.output.append(f"{i + 1}: {key} ({self.countDict[key]})")
    self.output.append("\n")

    return self.output


class StatArtistCount(SongStatCount):
  label = "artists"
  statname = "Artist Count"

  def process_song(self, song):
    if song.artist == "":
      return
    songParts = song.artist.split(", ")
    super().process_song(songParts)


class StatAlbumCount(SongStatCount):
  label = "albums"
  statname = "Album Count"

  def process_song(self, song):
    if song.album == "":
      return
    super().process_song([song.album])

The issue is that when I instantiate variables of StatArtistCount or StatAlbumCount, they share the same countDict properties. For example,

artist = StatArtistCount()
album = StatAlbumCount()

artist.countDict["hello"] = "world"
print(album.countDict["hello"])

This outputs world. So it seems that the variables are being declared and modified as static variables and not as instance variables. Why is that?

Kevin2566
  • 425
  • 8
  • 20
  • 1
    Attributes that should be separate for each instance should be assigned in the `__init__()` method, not as class variables. – Barmar Jul 02 '21 at 02:22
  • If I do that, and assign variables in the `__init__()` method for a superclass, the child class can't access them. I get an `AttributeError: 'Child class' object has no attribute 'attribute'` – Kevin2566 Jul 02 '21 at 02:26
  • You assigned to `self.countDict`? – Barmar Jul 02 '21 at 02:29
  • Sounds like you wrote your `__init__` methods wrong, perhaps forgetting to delegate to the superclass `__init__` in subclass `__init__` methods. – user2357112 Jul 02 '21 at 02:32
  • You're right, my `__init__` methods didn't call the superclass's `__init__`. Thanks! – Kevin2566 Jul 02 '21 at 12:12

0 Answers0