假设我有两个属于同一类的对象:objA 和 objB。它们的关系如下:
(objA == objB) #true
(objA is objB) #false
如果我将这两个对象用作 Python 字典中的键,那么它们将被视为相同的键,并相互覆盖。有没有一种方法可以覆盖字典比较器以使用 is
比较而不是 ==
以便将两个对象视为字典中的不同键?
也许我可以覆盖类中的 equals 方法或其他方法?更具体地说,我说的是 BeautifulSoup4 库中的两个 Tag 对象。
这是我所说的更具体的例子:
from bs4 import BeautifulSoup
HTML_string = "<html><h1>some_header</h1><h1>some_header</h1></html>"
HTML_soup = BeautifulSoup(HTML_string, 'lxml')
first_h1 = HTML_soup.find_all('h1')[0] #first_h1 = <h1>some_header</h1>
second_h1 = HTML_soup.find_all('h1')[1] #second_h1 = <h1>some_header</h1>
print(first_h1 == second_h1) # this prints True
print(first_h1 is second_h1) # this prints False
my_dict = {}
my_dict[first_h1] = 1
my_dict[second_h1] = 1
print(len(my_dict)) # my dict has only 1 entry!
# I want to have 2 entries in my_dict: one for key 'first_h1', one for key 'second_h1'.
最佳答案
first_h1
和second_h1
是 Tag
class实例。当您执行 my_dict[first_h1]
或 my_dict[second_h1]
时,标签的字符串表示 用于散列。问题是,这两个 Tag
实例都具有相同的字符串表示形式:
<h1>some_header</h1>
这是因为Tag
类有__hash__()
魔术方法定义如下:
def __hash__(self):
return str(self).__hash__()
解决方法之一是使用 id()
值作为散列,但是在 BeautifulSoup
本身中重新定义 Tag
类存在问题。您可以通过制作自己的自定义“标签包装器”来解决该问题:
class TagWrapper:
def __init__(self, tag):
self.tag = tag
def __hash__(self):
return id(self.tag)
def __str__(self):
return str(self.tag)
def __repr__(self):
return str(self.tag)
然后,您将能够:
In [1]: from bs4 import BeautifulSoup
...:
In [2]: class TagWrapper:
...: def __init__(self, tag):
...: self.tag = tag
...:
...: def __hash__(self):
...: return id(self.tag)
...:
...: def __str__(self):
...: return str(self.tag)
...:
...: def __repr__(self):
...: return str(self.tag)
...:
In [3]: HTML_string = "<html><h1>some_header</h1><h1>some_header</h1></html>"
...:
...: HTML_soup = BeautifulSoup(HTML_string, 'lxml')
...:
In [4]: first_h1 = HTML_soup.find_all('h1')[0] #first_h1 = <h1>some_header</h1>
...: second_h1 = HTML_soup.find_all('h1')[1] #second_h1 = <h1>some_header</h1>
...:
In [5]: my_dict = {}
...: my_dict[TagWrapper(first_h1)] = 1
...: my_dict[TagWrapper(second_h1)] = 1
...:
...: print(my_dict)
...:
{<h1>some_header</h1>: 1, <h1>some_header</h1>: 1}
不过,它并不漂亮,使用起来也不太方便。我会重申你最初的问题,并检查你是否真的需要将标签放入字典中。
您还可以使用 Python 的内省(introspection)功能对 bs4
进行猴子修补,例如 it was done here ,但这将进入一个相当危险的领域。
关于python - 我可以更改 Python 字典中键的比较方式吗?我想使用运算符 'is' 而不是 ==,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44595688/