【问题标题】:Python - Access a class from a list using a keyPython - 使用键从列表中访问一个类
【发布时间】:2010-04-05 08:42:24
【问题描述】:

有什么方法可以让类列表在 python 中表现得像一个集合?

基本上,我正在开发一款涉及字符串比较的软件,并且我有一个用于处理字符串的自定义类。因此,每个字符串都有一个类的实例。

因此,我有一个包含所有这些类的大列表。我希望能够像list[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"]

【问题讨论】:

  • 一个 SET 使用索引,而不是键。字典似乎更符合您的要求,但您使用的是 a("Hello") 键的传递,并尝试使用不同的值——“Hello”来检索它。
  • 您还应该为类 a 定义 __cmp__ 方法,该方法将在哈希值冲突的情况下调用。
  • 请使用大写的类名。请从对象继承。像这样:class A(object)。它会让我们更容易阅读,也更容易理解。

标签: python class


【解决方案1】:

只需编写一个行为有点像映射的类:

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']

【讨论】:

  • 嗯。看起来它应该可以工作,但是当我尝试评估 key in ClassDict 时,它会因 keyerror 而失败,__getitem__ 函数中的打印语句显示它正在传递 0 的键。
  • Doh - 需要添加__contains__
  • 我最终这样做了,因为它让我处理了一些我也遇到的重复数据删除问题。 OTOH,我现在遇到了 2gb 32 位内存限制的问题。 *叹气*
【解决方案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")

【讨论】:

    【解决方案3】:

    Set 和 dict 使用对象的 __hash__ 方法返回的值来查找对象,所以这会做你想做的事:

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

    【讨论】:

    • a__hash__(self) 类返回与字符串x 相同的哈希值时,您将获得额外的好处,无论您是否对a(x) 进行字典查找都没有区别或x.
    • 好的,但是如何将类插入字典?定义 __hash__ 后,尝试将类的实例添加到字典中要么会导致语法错误,要么会导致字典中的条目,键是类本身。
    【解决方案4】:

    我记得“set”和“dict”也使用__hash__

    来自Python 2.x doc

    字典的键几乎是任意值。不是hashable 的值,即包含列表、字典或其他可变类型的值(按值而不是对象标识进行比较)不能用作键。

    【讨论】:

      【解决方案5】:

      你想要这样的东西

      class A(object):
          ALL_INSTANCES = {}
          def __init__(self, text):
              self.text = text
              self.ALL_INSTANCES[self.text] = self
      
      
      
      a1 = A("hello")
      a2 = A("world")
      
      print A.ALL_INSTANCES["hello"]
      

      输出:

      <__main__.A object at 0x00B7EA50>
      

      【讨论】:

        猜你喜欢
        • 2017-10-20
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 2016-09-28
        • 1970-01-01
        • 2010-10-07
        相关资源
        最近更新 更多