[英]Achieving single-responsibility principle with python abstract classes
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.
但是无论子类类型如何,我都需要两个 static 函数来从数据库中获取数据。 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. pyright
显示get()
和get_all()
函数中的cls
没有db
属性的错误。
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()
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.您的第二个问题是方法
sound
隐式返回None
的结果,因为它没有 return 语句并且您有print(Dog.get(1).sound())
,它将打印出该方法的返回值。 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).您要么想将其更改为仅
Dog.get(1).sound()
,要么修改sound
方法以返回当前正在打印的内容并删除print
语句(我的选择)。
As an aside, I found this class structure a bit difficult to follow.顺便说一句,我发现这个 class 结构有点难以理解。 Why do you need a separate
DogSound
class with a name
attribute which should belong to Animal
?为什么你需要一个单独的
DogSound
class 和一个应该属于Animal
的name
属性? Also, it seems to me that age
could/should be an attribute of Animal
since both cats and dogs have an age.另外,在我看来,
age
可能/应该是Animal
的一个属性,因为猫和狗都有年龄。
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:如果出于某种原因您希望
DogSound
成为一个单独的 class,则无需复制name
属性:
...
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)
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.