我目前正在使用Python来解析CAN数据库文件。我在实现过程中遇到了列表问题并给它一个快速的补丁,使其工作,但它有点难看,似乎有一个更优雅的解决方案。
我已经定义了一个对象CAN数据库,其中一个方法需要解析文件,其中包含数据库中消息的定义。我遍历文件中的每一行,当我遇到一条指示消息描述的行时,我创建了一个临时变量,引用了我为CAN消息定义的对象,其中一些成员是列表。我使用基于文件中下一行的方法将元素放在这些列表中。
现在,当我完成这个临时对象时,我将它添加到CAN数据库对象中。由于我不再需要此变量引用的数据,因此我将值None
分配给它,并在下一次迭代中重新实现clean slate变量,以检测消息描述符。或者那就是计划。
当我经历下一次迭代并需要使用此变量时,我会向这些列表添加一些值,并发现它们实际上并不是空的。似乎尽管将变量指定为引用None
,但列表中的值仍然存在并且未被清除。
下面你可以看到我的解决方案,即专门堆叠更多方法以摆脱持久列表元素。
以下是该文件的一些相关部分:
解析循环
for line in file:
line = line.rstrip('\n')
line_number += 1 # keep track of the line number for error reporting
if line.startswith("BU_:"):
self._parseTransmittingNodes(line)
elif line.startswith("BO_"):
can_msg = self._parseMessageHeader(line).ResetSignals().ResetAttributes()
building_message = True
elif line.startswith(" SG_") and building_message:
can_msg.AddSignal(self._parseSignalEntry(line))
# can_msg.updateSubscribers()
elif line == "":
if building_message:
building_message = False
self._messages += [can_msg]
can_msg = None
重置方法
def ResetSignals(self):
"""
Flushes all the signals from the CANMessage object.
"""
self._signals = []
return self
def ResetAttributes(self):
"""
Flushes all the attributes from the CANMessage object.
"""
self._attributes = []
return self
如何每次都将此变量设为新对象?我是否应该使用一种方法清除所有内部内容,而不是像C#中的None
接口那样分配IDispose
?
编辑:这是CANMessage对象的完整源代码:
class CANMessage:
"""
Contains information on a message's ID, length in bytes, transmitting node,
and the signals it contains.
"""
_name = ""
_canID = None
_idType = None
_dlc = 0
_txNode = ""
_comment = ""
_signals = list()
_attributes = list()
_iter_index = 0
_subscribers = list()
def __init__(self, msg_id, msg_name, msg_dlc, msg_tx):
"""
Constructor.
"""
self._canID = msg_id
self._name = msg_name
self._dlc = msg_dlc
self._txNode = msg_tx
def __iter__(self):
"""
Defined to make the object iterable.
"""
self._iter_index = 0
return self
def __next__(self):
"""
Defines the next CANSignal object to be returned in an iteration.
"""
if self._iter_index == len(self._signals):
self._iter_index = 0
raise StopIteration
self._iter_index += 1
return self._signals[self._iter_index-1]
def AddSignal(self, signal):
"""
Takes a CANSignal object and adds it to the list of signals.
"""
self._signals += [signal]
return self
def Signals(self):
"""
Gets the signals in a CANMessage object.
"""
return self._signals
def SetComment(self, comment_str):
"""
Sets the Comment property for the CANMessage.
"""
self._comment = comment_str
return self
def CANID(self):
"""
Gets the message's CAN ID.
"""
return self._canID
def AddValue(self, value_tuple):
"""
Adds a enumerated value mapping to the appropriate signal.
"""
for signal in self:
if signal.Name() == value_tuple[0]:
signal.SetValues(value_tuple[2])
break
return self
def AddAttribute(self, attr_tuple):
"""
Adds an attribute to the message.
"""
self._attributes.append(attr_tuple)
return self
def ResetSignals(self):
"""
Flushes all the signals from the CANMessage object.
"""
self._signals = []
return self
def ResetAttributes(self):
"""
Flushes all the attributes from the CANMessage object.
"""
self._attributes = []
return self
def Name(self):
return self._name
def TransmittingNode(self):
return self._txNode
def DLC(self):
return self._dlc
答案 0 :(得分:0)
您看到的问题是因为您使用了类属性而不是实例属性。如果将属性的初始化移动到__init__
从类范围到__init__
,则每个实例都有自己的一组列表。
这就是看起来的样子:
class CANMessage:
"""
Contains information on a message's ID, length in bytes, transmitting node,
and the signals it contains.
"""
def __init__(self, msg_id, msg_name, msg_dlc, msg_tx):
"""
Constructor.
"""
self._canID = msg_id
self._name = msg_name
self._dlc = msg_dlc
self._txNode = msg_tx
self._name = ""
self._canID = None
self._idType = None
self._dlc = 0
self._txNode = ""
self._comment = ""
self._signals = list()
self._attributes = list()
self._iter_index = 0
self._subscribers = list()
# the rest of the class is unchanged, and not repeated here...