Python - 使用键从列表中访问类

1 投票
5 回答
3552 浏览
提问于 2025-04-15 21:14

有没有办法让一个类的列表在Python中像集合一样工作?

简单来说,我正在开发一个软件,它需要进行复杂的字符串比较。我为处理这些字符串创建了一个自定义类。因此,每个字符串都有一个类的实例。

结果就是,我有一个很大的列表,里面包含了所有这些类。我希望能够像这样访问它们:list[key],这里的key是基于字符串的(注意:一旦类被创建,这个字符串就不会改变,所以它应该是可以哈希的)。

我觉得我应该能比较简单地做到这一点,比如在类中添加一些像__cmp__这样的东西,但要么是我理解得不够清楚(很可能),要么是我在文档中遗漏了什么。

基本上,我想能够做到类似这样的事情(Python提示符示例):

>>class a:
... def __init__(self, x):
...  self.var = x
...
>>> from test import a
>>> cl = set([a("Hello"), a("World"), a("Pie")])
>>> print cl
set([<test.a instance at 0x00C866C0>, <test.a instance at 0x00C866E8>, <test.a instance at 0x00C86710>])
>>> cl["World"]
<test.a instance at 0x00C866E8>

谢谢!

编辑 一些额外的调整:

class a:
... def __init__(self, x):
...     self.var = x
... def __hash__(self):
...     return hash(self.var)
...
>>> v = a("Hello")
>>> x = {}
>>> x[v]=v
>>> x["Hello"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Hello'
>>> x["Hello"]

5 个回答

1

集合(set)和字典(dict)会使用一个对象的 __hash__ 方法返回的值来查找这个对象,所以这样做就能达到你想要的效果:

>>class a:
... def __init__(self, x):
...  self.var = x
...
... def __hash__(self):
...  return hash(self.var)
2

你为什么不直接这样做呢:

>>> v = MyStr("Hello")
>>> x = {}
>>> x[v.val]=v
>>> x["Hello"]
MyStr("Hello")

为什么要费那么大劲去创建一个自定义的字典,使用的键还和你传入的不同呢?(比如用“Hello”而不是 MyStr("Hello"))。

举个例子:

class MyStr(object):
    def __init__(self, val):
        self.val = str(val)

    def __hash__(self):
        return hash(self.val)

    def __str__(self):
        return self.val

    def __repr__(self):
        return 'MyStr("%s")' % self.val


>>> v = MyStr("Hello")
>>> x = {}
>>> x[str(v)]=v
>>> x["Hello"]
MyStr("Hello")
2

只需要写一个类,让它的行为有点像一个映射(就像字典那样):

class ClassDict(object):
  def __init__(self):
    self.classes = {}

  def add(self, cls):
    self.classes[cls.__name__] = cls

  def remove(self, cls):
    if self.classes[cls.__name__] == cls:
      del self.classes[cls.__name__]
    else:
      raise KeyError('%r' % cls)

  def __getitem__(self, key):
    return self.classes[key]

  def __repr__(self):
    return 'ClassDict(%s)' % (', '.join(self.classes),)

class C(object):
  pass

class D(object):
  pass

cd = ClassDict()
cd.add(C)
cd.add(D)

print cd

print cd['C']

撰写回答