小能豆

我可以更改 Python 字典中键的比较方式吗?我想使用运算符“is”而不是 ==

py

假设我有两个属于同一类的对象: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'.

阅读 11

收藏
2024-11-12

共1个答案

小能豆

Pythondict使用__eq____hash__方法来确定键的唯一性。由于first_h1 == second_h1计算结果为True,因此它们的哈希值相同,因此字典将它们视为相同的键。

要将和my_dict视为不同的键,您可以:first_h1``second_h1

  1. 使用对象 ID 作为字典键,或
  2. 创建一个自定义的类似字典的对象,将键与 进行比较,is而不是==

以下是使用每种方法可以实现此目的的方法:

方法 1:使用对象 ID 作为键

使用id(obj)确保每个对象都被视为唯一的:

my_dict = {id(first_h1): 1, id(second_h1): 2}
print(len(my_dict))  # This will print 2

要访问原始对象,可以将它们与其 ID 一起存储:

id_to_tag = {id(first_h1): first_h1, id(second_h1): second_h1}

is方法 2:创建具有比较功能的自定义字典类

如果您需要更灵活的解决方案,可以定义一个使用以下命令比较键的字典子类is

class IdentityDict(dict):
    def __setitem__(self, key, value):
        super().__setitem__(id(key), (key, value))

    def __getitem__(self, key):
        return super().__getitem__(id(key))[1]

    def __contains__(self, key):
        return id(key) in self

    def items(self):
        return ((kv[0], kv[1]) for kv in super().values())

# Usage
my_dict = IdentityDict()
my_dict[first_h1] = 1
my_dict[second_h1] = 2

print(len(my_dict))  # This will print 2

IdentityDict__setitem____getitem__和 中,__contains__所有操作都使用id(key),它强制使用身份比较 ( is) 而不是相等性比较 ( ==),因此每个对象都被视为唯一的。

2024-11-12