I want to separate the DB models from the actual classes. But i need two static functions for fetching data from the DB regardless of the subclass type. the implementation for both functions are the same across all DB models.
pyright showing an error that cls inside get() and get_all() functions doesn't have a db property.
from abc import ABC, abstractstaticmethod
class DogsDB:
lists = ["DOG1", "DOG2", "DOG3"]
@classmethod
def get(cls, id):
return cls.lists[id]
class CatsDB:
lists = ["CAT1", "CAT2", "CAT3"]
@classmethod
def get(cls, id):
return cls.lists[id]
class Animal(ABC):
def __init__(self, name):
self.name = name
@abstractstaticmethod
def save(m):
pass
@abstractstaticmethod
def _from_model(obj):
pass
@classmethod
def get(cls, id):
obj = cls.db.get(id)
return cls._from_model(obj)
@classmethod
def get_all(cls):
objs = cls.db.lists
lists = []
for obj in objs:
e = cls._from_model(obj)
lists.append(e)
return lists
def __repr__(self):
return self.name
class DogSound:
def __init__(self, name):
self.name = name
def sound(self):
print(self.name, ": DOG SOUND!!")
class Dog(Animal, DogSound):
db = DogsDB
def __init__(self, name, age):
super(Dog, self).__init__(name)
self.age = age
@staticmethod
def save(m):
print(m)
@staticmethod
def _from_model(obj):
return Dog(obj, 4)
class Cat(Animal):
db = CatsDB
def __init__(self, name, age):
super().__init__(name)
self.age = age
@staticmethod
def save(m):
print(m)
@staticmethod
def _from_model(obj):
return Cat(obj, 4)
print(Cat.get(1))
print(Dog.get(1))
print(Cat.get_all())
print(Dog.get_all())
Dog.get(1).sound()
CodePudding user response:
I cannot duplicate your first error.
Your second issue is a result of method sound implicitly returning None since it has no return statement and you have print(Dog.get(1).sound()), which will print out the return value from that method. You either want to change this to just Dog.get(1).sound() or modify the sound method to return what it is currently being printed and remove the print statement (my choice).
As an aside, I found this class structure a bit difficult to follow. Why do you need a separate DogSound class with a name attribute which should belong to Animal? Also, it seems to me that age could/should be an attribute of Animal since both cats and dogs have an age.
from abc import ABC, abstractstaticmethod
class DogsDB:
lists = ["DOG1", "DOG2", "DOG3"]
@classmethod
def get(cls, id):
return cls.lists[id]
class CatsDB:
lists = ["CAT1", "CAT2", "CAT3"]
@classmethod
def get(cls, id):
return cls.lists[id]
class Animal(ABC):
def __init__(self, name, age):
self.name = name
self.age = age
@abstractstaticmethod
def save(m):
pass
@abstractstaticmethod
def _from_model(obj):
pass
@classmethod
def get(cls, id):
obj = cls.db.get(id)
return cls._from_model(obj)
@classmethod
def get_all(cls):
objs = cls.db.lists
lists = []
for obj in objs:
e = cls._from_model(obj)
lists.append(e)
return lists
def __repr__(self):
return self.name
class Dog(Animal):
db = DogsDB
def __init__(self, name, age):
super().__init__(name, age)
def sound(self):
return f"{self.name}: DOG SOUND!!"
@staticmethod
def save(m):
print(m)
@staticmethod
def _from_model(obj):
return Dog(obj, 4)
class Cat(Animal):
db = CatsDB
def __init__(self, name, age):
super().__init__(name, age)
self.age = age
@staticmethod
def save(m):
print(m)
@staticmethod
def _from_model(obj):
return Cat(obj, 4)
print(Cat.get(1))
print(Dog.get(1))
print(Cat.get_all())
print(Dog.get_all())
print(Dog.get(1).sound())
Prints:
CAT2
DOG2
[CAT1, CAT2, CAT3]
[DOG1, DOG2, DOG3]
DOG2: DOG SOUND!!
If for some reason you want DogSound to be a separate class, then there is no need for the name attribute to be duplicated:
...
class DogSound: # A "Mixin" class
def sound(self):
return f"{self.name}: DOG SOUND!!"
class Dog(Animal, DogSound):
db = DogsDB
def __init__(self, name, age):
super().__init__(name, age)
@staticmethod
def save(m):
print(m)
@staticmethod
def _from_model(obj):
return Dog(obj, 4)
...
