【问题标题】:how to add methods to class attributes in python?如何在python中为类属性添加方法?
【发布时间】:2020-01-31 13:44:44
【问题描述】:

我正在创建一个自定义类来存储有关 CFD 模拟结果的信息。

现在它的设置方式是它实例化一个空的类对象,然后使用一个名为load_mesh的方法,它调用一个外部函数来读取关于网格的所有信息,并返回一个包含所有信息的字典. load_mesh 方法然后从字典中的值分配一堆类属性。

问题是我计划存储比网格更多的信息,而且我不希望我的类对象有 1000 个属性。然后我想将它们存储在适当的容器中(?),每个容器都有自己的方法。

例如,我的代码目前看起来像这样(省略了一些不必要的东西):

class CFD():
    def __init__(self, infile=None):
        self.file = infile

    def load_mesh(self):
        mesh = load_cfd_mesh(self) #calls outside function to load mesh info, uses self.file, returns dict
        self.proj = mesh['proj']
        self.static_items = mesh['static_items']
        self.nnodes = mesh['nnodes']
        self.node_coords = mesh['node_coords']
        self.node_codes = mesh['node_codes']
        self.nelements = mesh['nelements']
        self.element_types = mesh['element_types_str']
        self.node_connectivity = mesh['node_connectivity']
        self.element_node_ids = mesh['element_node_ids']
        self.element_coords = mesh['element_coords']
        self.element_elevs = mesh['element_elevs']
        self.horizontal_units = mesh['horizontal_units']
        self.vertical_units = mesh['vertical_units']

test = CFD('testfile.txt') #instantiate
test.load_mesh() #load mesh information to attributes

现在,我可以通过以下方式访问任何网格信息:

test.proj
self.nnodes
self.coords

等等……

但我想做的是将所有这些信息存储在test.mesh 中,其中test.mesh 具有所有这些属性,但也具有test.mesh.load() 方法。

我认为我可以这样做:

class CFD():
    def __init__(self, infile=None):
        self.file = infile
        self.mesh = None

    def load_mesh(self):
        mesh = load_cfd_mesh(self) #calls outside function to load mesh info, uses self.file, returns dict
        setattr(self.mesh, 'proj', mesh['proj'])
        #etc....

那么我就可以做到:

test = CFD('testfile.txt') #instantiate
test.load_mesh() #load mesh information to attributes
test.mesh.proj

但我不知道如何将load_mesh 方法添加到self.mesh

如何实现以下方法:

test = CFD('testfile.txt') #instantiate
test.mesh.load() #load mesh information to attributes
test.mesh.proj

我必须在主类中定义另一个类吗?赞class mesh(self):

另外,如果我提出的向 self.mesh 添加属性的方法没有意义..请帮忙!

【问题讨论】:

  • 您想用具有属性的类替换字典?除了一点可读性,我不会推荐这个。坚持使用字典:这是一个非常好的数据结构。不要仅仅因为mydata.some_key 看起来比mydata['some_key'] 好一点就强行把它放到一个类中。
  • 好的,不管我如何将信息存储在self.mesh 中,我如何向其中添加load 方法,主要问题是添加方法
  • @00 不,class CFD(): 很好,如果看起来有点奇怪。
  • 最后我可以做self.mesh['proj']如果我愿意,但是我如何通过调用self.mesh.load()来加载网格信息
  • @chepner 实际上还有更多内容我只是为了问题的极简主义而删除了它......应该删除括号,但无论如何

标签: python class inner-classes


【解决方案1】:

认为您可能正在寻找类似属性的东西,以便在需要时延迟加载网格 - 我真的不明白为什么会有一个“空”的网格对象,您必须明确地这样做.load():

class Mesh:
    def __init__(self, filename):
        mesh = load_cfd_mesh(filename)
        self.proj = mesh["proj"]
        self.static_items = mesh["static_items"]
        # ...


class CFD:
    def __init__(self, filename):
        self.filename = filename
        self._mesh = None

    @property
    def mesh(self):
        if not self._mesh:
            self._mesh = Mesh(self.filename)
        return self._mesh


test = CFD("testfile.txt")
print(test.mesh.proj)

【讨论】:

  • 我认为这可能正是我正在寻找的东西——在工作中,但我会在今天的某个时候尝试一下,然后回复你..感谢
  • 这更像是“你应该怎么做”。您可能不希望它的__init__ 进行加载,并将加载方法保留在CFD 上 - 因为我认为代码看起来很奇怪 - 在第一次访问时,您必须将 cfd.mesh 作为可调用线程, cfd.mesh("myfile") 以及在后续访问中您将使用 cfd.mesh.mesh_attr 。如果在CFD.__init__ 上触发加载,这会更干净。
  • 感谢两位。这是我走的路线。我没有在初始化中包含负载,因为网格可能很大,如果不需要,我不想浪费时间初始化类实例。如果需要,它将加载一次,然后保持加载以供后续调用
【解决方案2】:

您可以使用内部类来做到这一点(下面是用于演示的简化代码):

class CFD:
    class Mesh:
        def __init__(self, file):
            self._file = file

        def load_mesh(self):
            # implement here your own code...
            print("loading from file", self._file)
            self.proj = "PROJ"

    def __init__(self, file):
        self.mesh = self.__class__.Mesh(file)

【讨论】:

  • 谢谢,在你的方法和@AKX 的方法之间,我想我能够实现我想要做的事情。我稍后可以测试并返回你..非常感谢
  • 请注意,嵌套类声明本身没有任何好处——这里class Mesh 可能——而且可能应该——在class CFD 本身的主体之外。如果您查看成千上万个使用关系数据库的 Web 后端代码项目,例如,Person 必须有一个关联的 Contact 实例,这就是它的完成方式。
  • @jsbueno:我获得了封装。如果打算在 CFD 类之外使用 Mesh 类,则必须在外部声明它。如果它的所有对象都打算成为 CFD 对象的属性,那么最好将其设为内部类。
  • 这不是通常的做法,我希望你至少承认这一点。通过将代码放入正确的模块文件中,可以获得足够的封装。它可能感觉更语义化——这可能是件好事。啊 - 我记得这样做的棘手部分 - 人们可能会认为从 Mesh 实例内部可以访问所有者 CFD - 并且没有隐含的机制。如果需要,必须将所有者明确传递给 Mesh 的__init__。否则,反对意见实际上只是“平面优于嵌套”
  • 感谢您的帮助,但我最终制作了一个外部课程,因此接受了另一个答案。非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多