【问题标题】:Python class using large lookup tables使用大型查找表的 Python 类
【发布时间】:2019-04-17 12:18:57
【问题描述】:

在过去的几年里,我一直在不断地修改 Python (v3)。作为学习练习,我决定在几周前重构我编写的一系列 bash 脚本。我还认为该语言的某些功能将大大加快处理速度。这些 bash 脚本通常运行 5 或 6 天,处理巨大的数据文件。 Python版本还显着提高了代码的可读性和可维护性。

首先,我将算法作为程序放在一个文件中。该算法使用几个大型查找表,以列表和字典的形式实现。现在我想把它分解——核心逻辑进入一个文件,第二个文件包含一个包含查找表及其相关函数的类(es?)。数据表大约需要 350 行代码,函数大小也差不多。

问:构建类模块文件的首选方式是什么?

比如我一开始是这样做的,我们称之为案例1:

class Zebra:
    _stripe_keys = [ ....... ]
    _stripe_info = [ [.....], [.....], ... [.....] ]
    _stripes = [ dict(zip( stripe_keys, info )) for info in stripe_info ]
    <<< many such tables >>>
    def __init__(self, name):
        self.name = name
    def function_one(self):
        do something
    def function_two(self):
        do something
    <<< etc... >>>

然后我意识到这可能会更好,案例 2:

_stripe_keys = [ ....... ]
_stripe_info = [ [.....], [.....], ... [.....] ]
_stripes = [ dict(zip( stripe_keys, info )) for info in stripe_info ]
<<< many such tables >>>
class Zebra:
    def __init__(self, name):
        self.name = name
    def function_one(self):
        do something
    def function_two(self):
        do something
    <<< etc... >>>

然后我看到了另一种可能性,案例 3,但不知何故,我不得不将数据类传递给函数类:

class ZebraTables:
    _stripe_keys = [ ....... ]
    _stripe_info = [ [.....], [.....], ... [.....] ]
    _stripes = [ dict(zip( stripe_keys, info )) for info in stripe_info ]
    <<< many such tables >>>
    def __init__(self, name):
        self.name = name
class Zebra:
    def __init__(self, name):
        self.name = name
    def function_one(self):
        do something
    def function_two(self):
        do something
    <<< etc... >>>

数据表基本上是不变的。如果有理由创建此类的两个实例,则数据应该共享而不是重复。源代码中的静态数据占用了几十MB的内存,加上启动时从磁盘读取的额外数据,总计约600MB)。我认为这意味着案例 2 是我想要的,但我不确定。我来自嵌入式背景,主要使用 C,所以面向对象技术还不是我的专长!

【问题讨论】:

  • 如果数据是不变的,你可以把所有的东西都放在模块级别并完成它。仅在对您的代码有意义的情况下才使用一个类,您不必必须对所有事情都使用 OO。
  • 一旦您在脚本中导入其中一个类,您的查找表就会被加载到内存中。因此,如果您想避免这种情况,您需要将这些表中的每一个放在不同的模块中并有选择地导入它们。
  • 我同意@Martijn——此外,模块的行为类似于类的单例实例。事实上,如果你愿意,你可以手动将一个类的实例添加到sys.modules,让它看起来是一个(已经导入的)模块。

标签: python class module constants lookup-tables


【解决方案1】:

就个人而言,我不会将大型列表存储在与类相同的模块中。将它们以某种格式保存在外部 python 模块中,管理它们并在需要时加载它们怎么样?

根据大小和需求,您可以使用picklepandascsv,或直接使用 SQL/NoSQL DB。

【讨论】:

  • 这是个好主意。我已经对其进行了测试,通过从泡菜中加载数据,我节省了大约 50% 的初始化时间。由于这些表基本上是恒定的,我可以计算一次数据,将其腌制到磁盘,然后在正常操作中解压缩。
【解决方案2】:

感谢您的建议,他们帮助我找到了一个可行的解决方案,并更好地掌握了模块、类和实例变量。我决定将所有内容放在模块内的一个类中。

class Zebra:
    stripe_keys = []
    stripe_info = []
    stripes = defautdict(list)
    <<< many such tables >>>
    def __init__(self, name):
        self.name = name
        self.init_stripes()
    def function_one(self):
        do something
    def function_two(self):
        do something
    def init_stripes(self):
        Zebra.stripe_keys.extend([.........])
        Zebra.stripe_info.extend([ [...], [...], ..., [...] ])
        Zebra.stripes.extend([ dict(zip( Zebra.stripe_keys, info )) 
                               for info in Zebra.stripe_info ])
    <<< etc... >>>

我在顶部定义空表并在底部使用数据扩展/更新它们的这种安排是解决循环引用问题所必需的。其中一个列表是引用类中函数的跳转表,所以我不能先定义表,也不能先定义函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-29
    • 1970-01-01
    • 2022-11-22
    • 1970-01-01
    • 2016-04-17
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    相关资源
    最近更新 更多