首页 > 解决方案 > 使用类组织创建或扩展文本文件的函数?

问题描述

我是全新的课程,我真的不知道什么时候使用它们。我想编写一个用于模拟 EPR/NMR 光谱的程序,该程序需要有关模拟系统的信息。相关的事情是这样的:我有一个调用的函数rel_inty(I_n,N),它从两个值计算这些相关信息。问题是当这些值中的任何一个变大时它会变得非常慢(I_n,N >= 10)。这就是为什么我选择rel_inty(I_n,N)预先计算最相关的 ( I_n,N) 组合并将它们保存在字典中。我将该字典写入文件并可以使用导入它eval(),因为rel_inty(I_n,N)在每次执行时动态计算会太慢。

现在我有了以下想法:如果我创建一个class manage_Dict():,它的方法可以用 a 重新创建一个基本字典def basic():,以防旧文件以某种方式被删除,或者用一种def expand():方法扩展现有字典,如果基本字典不包含用户指定的 ( I_n,N) 组合?

这将是该课程的大纲:

class manage_Dict(args):

    def rel_inty(I_n,N):
        '''calculates relative intensities for a combination (I_n,N)'''

    def basic():
        '''creates a dict for preset combinations of I_n,N'''

        with open('SpinSys.txt','w') as outf:

            Dict = {}
            I_n_List = [somevalues]
            N_List = [somevalues]

            for I_n in I_n_List:
                Dict[I_n] = {}
                for N in N_List:
                    Dict[I_n][N] = rel_inty(I_n,N)

            outf.write(str(Dict))

    def expand(*args):
        '''expands the existing dict for all tuples (I_n,N) in *args'''

        with open('SpinSys.txt','r') as outf:

            Dict = eval(outf.read())

            for tup in args:
                I_n = tup[0]
                N = tup[1]

                Dict[I_n][N] = rel_inty(I_n,N)

         os.remove('SpinSys.txt')

         with open('SpinSys.txt','w') as outf:

             outf.write(str(Dict))

用法:

'''Recreate SpinSys.txt if lost'''
manage_Dict.basic()

'''Expand SpinSys.txt in case of missing (I_n,N)'''
manage_Dict.expand((10,5),(11,3),(2,30))

这会是一个明智的解决方案吗?我想知道,因为我通常会看到带有self__init__创建对象实例的类,而不仅仅是管理函数调用。

标签: pythonpython-3.xfunctionclasstext-files

解决方案


如果我们要使用一个对象,让我们确保它为我们做了一些有用的工作,并且界面比仅仅使用函数更好。我将提出一些让生活更轻松的大调整:

  • 我们可以dict对自己进行子类化,然后我们的对象是一个字典,以及我们所有的自定义花哨的东西
  • 使用JSON代替文本文件,这样我们可以快速、自然、安全地序列化和反序列化
import json


class SpectraDict(dict):
    PRE_CALC_I_N = ["...somevalues..."]
    PRE_CACL_N = ["...somevalues..."]

    def rel_inty(self, i_n, n):
        # Calculate and store results from the main function
        if i_n not in self:
            self[i_n] = {}

        if n not in self[i_n]:
            self[i_n][n] = self._calculate_rel_inty(i_n, n)

        return self[i_n][n]

    def _calculate_rel_inty(self, i_n, n):
        # Some exciting calculation here instead...
        return 0

    def pre_calculate(self):
        s_dict = SpectraDict()

        for i_n in self.PRE_CALC_I_N:
            for n in self.PRE_CACL_N:
                # Force the dict to calculate and store the values
                s_dict.rel_inty(i_n, n)

        return s_dict

    @classmethod
    def load(cls, json_file):
        with open(json_file) as fh:
            return SpectraDict(json.load(fh))

    def save(self, json_file):
        with open(json_file, 'w') as fh:
            json.dump(self, fh)

        return self

现在,当使用该函数请求值时,rel_inty()我们会立即将答案存储在自己中,然后再将其返回。这称为记忆/缓存。因此,要用预先计算的值预先填充我们的对象,我们只需要向它询问很多答案,它就会存储它们。

之后,我们可以很自然地使用 JSON 加载或保存:

# Bootstrapping from scratch:
s_dict = SpectraDict().pre_calculate().save('spin_sys.json')

# Loading and updating with new values
s_dict = SpectraDict.load('spin_sys.json')
s_dict.rel_inty(10, 45)  # All your new calculations here...
s_dict.save('spin_sys.json')

推荐阅读