1
class Media_Work(object):

  def __init__(self):

    _id: int = 0
    _IdDict: {} 
    _titleDict: {}

class Poem(Media_Work):

  def __init__(self, id, title, author, content, age, mtype, verbs):

    super().__init__()
    self.id = id
    self.title = title
    self.author = author
    self.content = content
    self.age = age
    self.mtype = mtype
    self.verbs = verbs

    Poem._IdDict.update({id: self})

My error message:

AttributeError: 'Poem' object has no attribute '_IdDict'

Similar error if I change the bottom line to:

self._IdDict.update({id:self})

New error message:

AttributeError: type object 'Poem' has no attribute '_IdDict'

elkym
  • 31
  • 4
  • 2
    `Media_Work.__init__()` doesn't actually assign anything to `_IdDict` or `_titleDict`: it merely contains malformed type hints for these attributes. – jasonharper Dec 13 '20 at 02:27
  • 3
    Presumably in the parent class `__init__()` you intended to assign `self._IdDict = {}`. But you didn't do that. – John Gordon Dec 13 '20 at 02:30

3 Answers3

1

As-written, your intended dict _IdDict is really a type hint (see comment by ShadowRanger)!

Set the attribute as either a class variable (probably your intention) or assign the attribute in __init__()


Class Variable
Reference will be created in class declaration and shared by all instances of the class
There is no need to call super() to init in this case

class Media_Work():

    _id     = 0
    _IdDict = {}

Attribute
Reference will be created at class init and unique to each instance of the class

class Media_Work():

    def __init__(self):
        self._id     = 0
        self._IdDict = {} 
ti7
  • 16,375
  • 6
  • 40
  • 68
  • 1
    Every time you say "property", you mean "attribute" (more specifically, instance attribute, as opposed to class attribute); [the former has specific meaning in Python](https://docs.python.org/3/library/functions.html#property) separate from attribute. – ShadowRanger Dec 13 '20 at 03:50
  • 1
    @ShadowRanger you're right - I've updated my question with that and a little rework! – ti7 Dec 13 '20 at 04:02
1

It is inheriting, but you haven't defined the _IdDict class attribute. _IdDict: {} is type hint, not a definition, and it's a local name in __init__, not a class attribute.

Here's an example of how to fix it. You might need to tailor this to fit your needs:

class Media_Work:
    _IdDict = {}

class Poem(Media_Work):
    def __init__(self, _id):
        Poem._IdDict.update({_id: self})

Example usage:

>>> p = Poem(17)
>>> Poem._IdDict
{17: <__main__.Poem object at 0x7f13689a3ba8>}
>>> Media_Work._IdDict
{17: <__main__.Poem object at 0x7f13689a3ba8>}

By the way, don't use id as a variable name, since it's a builtin.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
-2

[My previous version of this answer was lacking].... You have two issues there. The first is that you failed to assign a value to _IdDict so it was not created. Second, you defined it in the wrong scope. If you wanted to create a Class attribute you need to refer to it as Media_Work._IdDict from within the __init__ method or you needed to define it outside the method. Such as:

class Media_Work(object):

    _id: int = 0
    _IdDict: {} = {}
    _titleDict: {} = {}

    def __init__(self):
        Media_Work._id = 0
Curt Welch
  • 339
  • 3
  • 5
  • 2
    Two of those aren't even class attributes; they're annotations that are never assigned (and by type annotation rules, implicitly annotate the instance attributes, not class attributes). This is not a proper fix at all. – ShadowRanger Dec 13 '20 at 02:43
  • @ShadowRanger, so true. I have attempted to improve my bad answer. – Curt Welch Dec 13 '20 at 03:16