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)
...