将被视为服务的类的良好设计是什么:它从磁盘上的大数据初始化,然后响应来自另一个模块的请求?
它可以只是带有静态数据的类吗?通过调用 Init 函数从磁盘加载数据,然后可以向该类发出请求。
你能批评这个解决方案吗?你会推荐更好的东西吗?
将被视为服务的类的良好设计是什么:它从磁盘上的大数据初始化,然后响应来自另一个模块的请求?
它可以只是带有静态数据的类吗?通过调用 Init 函数从磁盘加载数据,然后可以向该类发出请求。
你能批评这个解决方案吗?你会推荐更好的东西吗?
根据您的描述,我了解到您建议将磁盘中的所有数据读取到类实例或类似的成员中(如果您计划这样做,我不会使用模块全局变量),然后使用该数据响应请求 - 有我对你的理解正确吗?
只要您在系统上有足够的内存,这种方法就可以正常工作 - 因为我不知道您的数据有多大,所以我无法评论这是否现实。但是,您对代码施加了可伸缩性限制,因此如果数据变得更大,那么您的代码可能会运行非常缓慢或导致崩溃。不同的平台对内存耗尽的反应略有不同,但结果几乎总是不优雅。
在可能的情况下,根据需要从磁盘读取数据可能会更好,如果合适的话,可能会使用一些内存缓存。如果可以的话,我建议将您的数据转换为结构化格式,例如SQLite是一种创建结构化文件数据的相当简单的方法。然后,您可以编写执行 SQL 查询的方法,以便根据需要从文件中恢复数据。
如果您需要通过在内存中缓存常见结果来获得更好的性能,您可以使用 Python 3 的LRU 缓存装饰器围绕您想要缓存的所有函数。这确实假设函数的结果仅取决于其参数。如果您使用的是 Python 2.x,那么您也可以找到它的实现,尽管不在标准库中。
如果您的结果取决于类成员以及函数参数,则您可能需要做一些额外的工作,要么编写自己的缓存层,要么使用上述解决方案,并在适当的类成员更改时手动清除缓存。如果对您的问题有更多了解,我无法为您提供具体信息,但希望能涵盖所涉及的问题。
这是否回答了您的问题,还是我错过了重点?如果您需要不同的答案,请提供说明。
编辑
在您在下面发表评论之后,我想我会添加更多说明。
首先,我不确定您所说的“静态”数据是什么意思——Python 并没有像 C/C++ 或 Java 这样的东西那样真正拥有这个概念。您可以将类属性存储在类对象中并且对实例可用,就好像它们是常规属性一样:
class MyClass(object):
class_attribute = 123
def method(self):
print "Class attribute value: %d" % (self.class_attribute,)
...但在这种情况下,我认为这不是一个好主意。也许“静态”只是指作为类实例的属性存储的一堆数据,如果是这样,那么对于您所描述的内容来说,这似乎是一个非常明智的选择。
因此,您的类最终会得到一个__init__()
方法,该方法可能会将文件名之类的东西作为参数(即使您存储数据的文件现在已修复,但将来可能不会,另外使用不同的单元测试)。然后,此方法将导致数据被加载并存储为实例属性。我建议将实际加载委托给另一种方法,这样您就可以重新加载数据而无需构建新实例。
举个简单的例子,如果你的类存储文件中的行,那么你可能有:
class FileLines(object):
def __init__(self, filename):
self.lines = []
self.load_file(filename)
def load_file(self, filename):
with open(filename, "r") as fd:
self.lines = [i.rstrip() for i in fd]
(我意识到设置lines
in__init__()
并不是严格要求的,因为它是在 中重置的load_file()
,但我认为在 中初始化所有属性是一个好习惯__init__()
)。
这显然是一个毫无意义的课程,但你明白了——从中读取数据__init__()
,然后使其可用。顺便说一句,我故意没有为lines
属性添加“getter”方法——在 Python 中,直接访问属性是完全可以接受的,不需要在 C/C++ 和 Java 中经常看到的“getter”和“setter”方法。这是因为以后如果需要实现更复杂的功能,可以使用Python 中的属性将简单的属性替换为方法。因此,您现在可以拥有基本属性的简单性,以后也可以灵活使用。
此外,假设您的数据具有结构,您应该考虑如何存储它。字典、列表和集合在 Python 中都非常强大,但是如果您的数据具有命名字段,那么请考虑使用collections.namedtuple
或自定义类来表示它。这使得该类的用户访问它更方便(因此更不容易出错)。理想情况下,我建议尝试将对象的内存中表示保留在一个类中,并使用代码在其他地方解析磁盘上的表示,从而生成内存版本的实例。以这种方式保持表示分离将允许您将您的类的用户与磁盘表示的更改隔离开来。
希望这会有所帮助。