Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 通过切换对象的类来管理对象_Python - Fatal编程技术网

Python 通过切换对象的类来管理对象

Python 通过切换对象的类来管理对象,python,Python,我有一个特定程序的数据输入文件。文件中有不同类型的数据行,对于每种类型的输入行,在我之前创建的另一个模块中都有一个对应的类。最简单的例子: #data module class AnalysisObject: pass class BoundaryNode(AnalysisObject): pass class MaterialDefiniton(AnalysisObject): pass 根据它所表示的数据类型,为每一行分配一个类,并将该对象对应的AnalysisObject作为r/w属性描

我有一个特定程序的数据输入文件。文件中有不同类型的数据行,对于每种类型的输入行,在我之前创建的另一个模块中都有一个对应的类。最简单的例子:

#data module
class AnalysisObject: pass
class BoundaryNode(AnalysisObject): pass
class MaterialDefiniton(AnalysisObject): pass
根据它所表示的数据类型,为每一行分配一个类,并将该对象对应的
AnalysisObject
作为r/w属性描述符,似乎是一个好主意,因此我首先建立了一个接口(由于下面解释的原因,我不能使用
abc.ABCMetaclass
):

我的问题是如何将文件行的每一行分配给正确的类,同时保持数据输入模块和数据模块之间的分离

我的想法是首先将每一行加载到
str
的子类中。然后,当调用该子类的任何方法时,该子类可以将该对象重新分配给正确的类(使用
myobject.\uu class\uu=NewClass

这一切似乎都正常工作,但是,我不确定以这种方式重新分配对象的类是否是一个好主意。它似乎还没有给我带来任何问题,但我不是特别有经验,也不知道该找什么

class DataLine(LineBase):
    def _switch_class(self,klass):
        self.__class__ = klass
    def __getattr__(self,name):
        self.__class__ = line_type_detector(self.line)
        return getattr(self, name)
附加说明:该类是我无法使LineBase成为abc.ABCMetaclass
abc.ABCMetaclass
的原因:

@abc.abstract 
def analysis_object(self): etc. etc. etc.
…因为这样在调用
DataLine().analysis\u object
时就不会发生类重新分配

检测每一行应该是哪一类不是问题;我有一个简单的
线型检测器

def line_type_detector(data_line):
    -figure out what class the line should be-
    return ItShouldBeThisClass

我不知道一旦构建了对象,如何更改它的类。所以我宁愿在创建时分配类。您可以使用函数
createLine
明确地执行此操作,该函数将返回相应子类的对象:

def createLine(data_line):
    typ = line_type_detector
    if (typ == BoundaryNodeLine):
        return BoundaryNodeLine(data_line)
    ...
您也可以在
LineBase
中使用
\uuuuu new\uuuuu
特殊方法:

class LineBase:
    def __new__(cls, data_line):
        return createLine(data_line)
    ...
其中createLine与上述函数相同

然后,您只需使用以下工具创建对象:

line = LineBase(data_line)

并直接获得正确子类的对象

我不知道在构建对象后如何更改对象的类。所以我宁愿在创建时分配类。您可以使用函数
createLine
明确地执行此操作,该函数将返回相应子类的对象:

def createLine(data_line):
    typ = line_type_detector
    if (typ == BoundaryNodeLine):
        return BoundaryNodeLine(data_line)
    ...
您也可以在
LineBase
中使用
\uuuuu new\uuuuu
特殊方法:

class LineBase:
    def __new__(cls, data_line):
        return createLine(data_line)
    ...
其中createLine与上述函数相同

然后,您只需使用以下工具创建对象:

line = LineBase(data_line)

并直接获得正确子类的对象

我不知道在构建对象后如何更改对象的类。所以我宁愿在创建时分配类。您可以使用函数
createLine
明确地执行此操作,该函数将返回相应子类的对象:

def createLine(data_line):
    typ = line_type_detector
    if (typ == BoundaryNodeLine):
        return BoundaryNodeLine(data_line)
    ...
您也可以在
LineBase
中使用
\uuuuu new\uuuuu
特殊方法:

class LineBase:
    def __new__(cls, data_line):
        return createLine(data_line)
    ...
其中createLine与上述函数相同

然后,您只需使用以下工具创建对象:

line = LineBase(data_line)

并直接获得正确子类的对象

我不知道在构建对象后如何更改对象的类。所以我宁愿在创建时分配类。您可以使用函数
createLine
明确地执行此操作,该函数将返回相应子类的对象:

def createLine(data_line):
    typ = line_type_detector
    if (typ == BoundaryNodeLine):
        return BoundaryNodeLine(data_line)
    ...
您也可以在
LineBase
中使用
\uuuuu new\uuuuu
特殊方法:

class LineBase:
    def __new__(cls, data_line):
        return createLine(data_line)
    ...
其中createLine与上述函数相同

然后,您只需使用以下工具创建对象:

line = LineBase(data_line)

并直接获取正确子类的对象通常,当使用不同的类型来标识这种不同的数据时,更专门的类型将被期望具有额外的属性或方法,这些属性或方法对于它们来说是特殊的。例如,
materialdefinition
可能包含基本
AnalysisObject
不包含的有关物料的信息。因此,选择不同类型的原因是能够存储不常见的属性

现在,如果情况并非如此,并且类型仅用于标识,而不用于状态或行为差异,那么您根本不应该使用不同的类型。只需使用一种类型,并使其具有类似
kind
的属性,该属性告诉您所引用的数据类型。例如,您可以使用
obj.kind='materialdefinition'
,或者
obj.kind='boundarynode'

但我将假设情况并非如此,这些对象实际上是不同的,并且在解析一行时,您希望根据行类型使用值填充不同的属性

那么,数据类型能够自己解析这样的行有什么错呢?没什么,我想说。具有能够序列化或取消序列化的类型是非常常见的。我不认为这会是一个缺少关注点分离的问题;毕竟,类型确保其状态可以存储在文件中,或从文件加载

在Python中,您实际上可以实现一个类型的
\uuuu repr\uuuu
方法来获取可以保存到文件中的字符串表示形式
repr
旨在为您提供完全代表对象状态的内容。对于解析,您只需创建一个函数,该函数接受字符串并根据函数解析的内容返回其中一个对象。例如:

def parse (line):
    data = line.split()
    if data[0] == 'material':
        obj = MaterialDefiniton()
        obj.material = data[1]
        obj.otherstuff = data[2]
    elif data[0] == 'boundary':
        obj = BoundaryNode()
        obj.boundary = data[1]
    else:
        obj = AnalysisObject()

    obj.raw_data = data
    return obj
您还可以将对该类型的单独解析移动到该类型的构造函数中,这样您就可以将该行传递给对象,它们将自己构建。或者创建一个明确解析数据的classmethod:

class MaterialDefinition:
    @classmethod
    def parse (cls, data):
        obj = cls() # This is equivalent to `obj = MaterialDefinition()`
        obj.material = data[1]
        obj.otherstuff = data[2]
        return obj
然后,您可以在general
parse
函数中选择所需的对象:

def parse (line):
    data = line.split()
    if data[0] == 'material':
        return MaterialDefinition.parse(data)
    elif data[0] == 'boundary':
        return BoundaryNode.parse(data)
    else:
        return AnalysisObject.parse(data)
您甚至可以移动
解析
函数的逻辑