I want to do something like the below. But one thing I'm not sure about is that the "expected_limbs" only exists for concrete classes. I have a method that in the "Pet" class that references "expected_limbs" but does not actually have that attribute. This should be fine during runtime, but I'm curious if this is ok and if it's not what is the correct approach? I could always just set it as None in the abstract class but seems imperfect.
from abc import ABC, abstractmethod
class Pet(ABC):
    def __init__(self, name, limbs):
        self.name = name
        self.limbs = limbs
    def has_all_limbs(self):
        for limb, limb_count in self.expected_limbs.items():
            if self.limbs[limb] != limb_count:
                return False
        else:
            return True
    @abstractmethod
    def speak(self):
         pass
class Dog(Pet):
    def __init__(self, name, limbs):
        super().__init__(name, limbs)
        self.expected_limbs = {"legs": 4}
    def speak(self):
        print("Bark")
class Bird(Pet):
    def __init__(self, name, limbs):
        super().__init__(name, limbs)
        self.expected_limbs = {"legs": 2, "wings": 2}
    def speak(self):
        print("Chirp")
Runtime this is ok.
toucan = Bird("Sam", {"legs": 2, "wings": 1})
print(toucan.has_all_limbs())
False
