我有一个类的多实例与类属性的问题



这篇文章实际上是对一篇旧文章的编辑,因为上一篇文章根本不清楚我的问题。

我想当你创建从另一个类继承并共享相同属性的类的实例时,我对真正发生的事情有疑问。

我有一段代码,它使用了scapy.packets中的包库。它的目的是创建一个报头,一个数据层,将这两者结合起来形成一个数据包。

我决定创建两个类Header和Layer,它们都继承自Packet,因此共享类属性fields_desc. 在这两个类中,我添加了两个类方法为了在我即将生成的包中添加一些字段。然后,我创建了一个header实例,一个layer实例,并将这两个包组合成最终的包:

class Init:
class Header(Packet):
name = "RESM_header"
fields_desc = []
@classmethod
def add_IntField(cls, name, value):
cls.fields_desc.append(IntField(name, value))
@classmethod
def reset(cls):
"""
Allows for the fields_desc to be set to []
"""
cls.fields_desc=[]
class Layer(Packet):
name = "DATA"
fields_desc = []
@classmethod
def add_IntField(cls, name, value):
cls.fields_desc.append(IntField(name, value))
@classmethod
def reset(cls):
"""
Allows for the fields_desc to be set to []
"""
cls.fields_desc = []

如果我想创建一个标题字段"id"我将使用:

if __name__ == '__main__':
Init.Header.add_IntField("id",4) # adds the requested field with its value
a = Init.Header() # creates the packet with the fields_desc already filled 

如果我显示包,我有结果:

a.show() 
###[ RESM_header ]### 
id        = 4
然而,在我的整个项目中,我必须创建几个不同的头。例如,我想用python a.reset()重置我的头的fields_desc,然后用python Init.Header.add_IntField("id",6)添加一个新字段和一个新值。

然而,我的id的值仍然是前一个值。下面的代码两次返回相同的数据包:

if __name__ == '__main__':
Init.Header.add_IntField("id",4)
a = Init.Header()
a.show()
a.reset()
Init.Header.add_IntField("id",5)
a = Init.Header()
a.show()
a.reset()

更奇怪的是,如果我决定创建另一个与前一个不同的字段,代码会出错,并出现几个错误:

if __name__ == '__main__':
Init.Header.add_IntField("id",4)
a = Init.Header()
a.show()
a.reset()
Init.Header.add_IntField("another_field",5)  # try to create another field
a = Init.Header()
a.show()
a.reset()

返回错误:

Traceback (most recent call last):
File "F:/IVS_NG/Tests/DebugTest.py", line 46, in <module>
a.show()
File "D:UsersT0267246-AAppDataRoamingPythonPython37site-packagesscapypacket.py", line 1464, in show
return self._show_or_dump(dump, indent, lvl, label_lvl)
File "D:UsersT0267246-AAppDataRoamingPythonPython37site-packagesscapypacket.py", line 1414, in _show_or_dump
fvalue = self.getfieldval(f.name)
File "D:UsersT0267246-AAppDataRoamingPythonPython37site-packagesscapypacket.py", line 411, in getfieldval
return self.payload.getfieldval(attr)
File "D:UsersT0267246-AAppDataRoamingPythonPython37site-packagesscapypacket.py", line 1824, in getfieldval
raise AttributeError(attr)
AttributeError: another_field

如果有人知道是怎么回事,我将非常感激!欢呼声

我将把这个作为一个答案,因为它不适合在评论中。我不是scapy方面的专家,所以我不知道这是否能满足您的需要,但是在浏览了文档之后,在我看来,它的设计并不是像您试图做的那样动态更改字段。相反,您应该预先定义所有字段,然后可以为每个实例设置值。例如,您的Header类可能看起来像这样:

class Header(Packet):
name = "RESM_header"
fields_desc = [ IntField("id", 0) ] # define a field called "id" with default 0

就是这样,真的。现在您可以创建具有任意id的Header实例,如下所示:

header = Header(id = 12345) # pass the desired id to the constructor here
header.show()
# ###[ RESM_header ]###
#   id        = 12345

如果您需要Header有另一个字段,只需静态地将其添加到fields_desc列表:

class Header(Packet):
name = "RESM_header"
fields_desc = [ IntField("id", 0),
IntField("another_field", 0) ]

并像前面那样创建实例:

header = Header(id = 12345, another_field = 69)
header.show()
# ###[ RESM_header ]###
#   id        = 12345
#   another_field= 69

在你的子类中试试

def __init__(self):
super().__init__()

https://realpython.com/python-super/

相关内容

  • 没有找到相关文章

最新更新