从 pickleDB 中的存储列表中删除项目会抛出:list.remove(x): x not in list
Removing item from a stored list in pickleDB throws: list.remove(x): x not in list
我有一个 Message
class:
messages = []
class Message:
id = 1
content = "m1"
def __init__(self, id, content):
self.id = id
self.content = content
以下代码按预期工作:
m1 = Message(1, "m1")
m2 = Message(2, "m2")
messages.append(m1)
messages.append(m2)
messages.remove(m2) #Works as expected
但是当我从 pickleDB 加载 messages
并尝试删除该项目时,它会抛出此错误:
list.remove(x): x not in list
def save_database():
with open("database.db", 'wb') as f:
pickle.dump(messages, f)
def load_database():
global messages
with open("database.db", 'rb') as f:
messages = pickle.load(f)
def add_message(msg):
load_database()
messages.append(msg)
save_database()
m1 = Message(1, "m1")
m2 = Message(2, "m2")
add_message(m1)
add_message(m2)
load_database()
messages.remove(m2) #ERROR: list.remove(x): x not in list
那是因为从 pickle dump 中读取的对象与您程序中的对象不同(pickle.load()
创建了新对象)。
因此,当 list.remove()
查找列表中的对象时,它不会找到它而是引发异常。
另请参阅 this post,其中讨论了默认情况下如何在 Python 中定义对象的相等性。
您需要通过在 Message
class:
中实施自定义 __eq__
方法来覆盖检查相等性的方式
class Message:
def __init__(self, id, content):
self.id = id
self.content = content
def __eq__(self, other):
if isinstance(other, Message):
return self.id == other.id and self.content == other.content
return False
一般的做法是先检查被比较对象的类型是否正确。如果是,则比较相关字段。
如果我不拥有 class,我该如何处理?
您可以子 class 它,然后覆盖 __eq__
。尽管在这种情况下,您可能还需要考虑 super().__eq__
的行为方式。
完全覆盖 __eq__ 的子class:
在这个版本中,我们完全放弃了 superclass 的 __eq__
并实现了我们自己的检查相等性的逻辑。
class MyMessage(Message):
def __init__(self, id, content, extra):
super().__init__(id, content)
self.extra = extra
def __eq__(self, other):
# As an example, we only check `extra`, and ignore everything else
if isinstance(other, MyMessage):
return self.extra == other.extra
return False
Subclass 覆盖并考虑 super().__eq__:
在这个版本中,我们调用了 superclass 的 __eq__
并添加了我们自己的逻辑来检查相等性。
class MyMessage2(Message):
def __init__(self, id, content, extra):
super().__init__(id, content)
self.extra = extra
def __eq__(self, other):
if isinstance(other, MyMessage2):
ret = super().__eq__(other)
if not ret:
return False
return self.extra == other.extra
return False
我有一个 Message
class:
messages = []
class Message:
id = 1
content = "m1"
def __init__(self, id, content):
self.id = id
self.content = content
以下代码按预期工作:
m1 = Message(1, "m1")
m2 = Message(2, "m2")
messages.append(m1)
messages.append(m2)
messages.remove(m2) #Works as expected
但是当我从 pickleDB 加载 messages
并尝试删除该项目时,它会抛出此错误:
list.remove(x): x not in list
def save_database():
with open("database.db", 'wb') as f:
pickle.dump(messages, f)
def load_database():
global messages
with open("database.db", 'rb') as f:
messages = pickle.load(f)
def add_message(msg):
load_database()
messages.append(msg)
save_database()
m1 = Message(1, "m1")
m2 = Message(2, "m2")
add_message(m1)
add_message(m2)
load_database()
messages.remove(m2) #ERROR: list.remove(x): x not in list
那是因为从 pickle dump 中读取的对象与您程序中的对象不同(pickle.load()
创建了新对象)。
因此,当 list.remove()
查找列表中的对象时,它不会找到它而是引发异常。
另请参阅 this post,其中讨论了默认情况下如何在 Python 中定义对象的相等性。
您需要通过在 Message
class:
__eq__
方法来覆盖检查相等性的方式
class Message:
def __init__(self, id, content):
self.id = id
self.content = content
def __eq__(self, other):
if isinstance(other, Message):
return self.id == other.id and self.content == other.content
return False
一般的做法是先检查被比较对象的类型是否正确。如果是,则比较相关字段。
如果我不拥有 class,我该如何处理?
您可以子 class 它,然后覆盖 __eq__
。尽管在这种情况下,您可能还需要考虑 super().__eq__
的行为方式。
完全覆盖 __eq__ 的子class:
在这个版本中,我们完全放弃了 superclass 的 __eq__
并实现了我们自己的检查相等性的逻辑。
class MyMessage(Message):
def __init__(self, id, content, extra):
super().__init__(id, content)
self.extra = extra
def __eq__(self, other):
# As an example, we only check `extra`, and ignore everything else
if isinstance(other, MyMessage):
return self.extra == other.extra
return False
Subclass 覆盖并考虑 super().__eq__:
在这个版本中,我们调用了 superclass 的 __eq__
并添加了我们自己的逻辑来检查相等性。
class MyMessage2(Message):
def __init__(self, id, content, extra):
super().__init__(id, content)
self.extra = extra
def __eq__(self, other):
if isinstance(other, MyMessage2):
ret = super().__eq__(other)
if not ret:
return False
return self.extra == other.extra
return False