2010-04-05 70 views
1

有没有什么办法让类的列表像Python中的一组行为一样?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"] 
+0

SET使用索引而不是键。字典看起来更像你想要的,但是你使用的是传递(“你好”)的密钥,并试图用不同的值 - “你好”来检索它。 – 2010-04-05 10:08:29

+0

您还应该为类__a__定义\ _ \ _ cmp \ _ \ _方法,这将在散列值冲突的情况下调用。 – Yaroslav 2010-04-05 10:18:25

+0

请使用UpperCase名称作为类别。请继承对象。像这样:'A类(对象)'。这将使我们更容易阅读,也更容易让你弄清楚。 – 2010-04-05 10:23:00

回答

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

嗯。它看起来应该可以工作,但是当我尝试评估'ClassDict'中的键时,它会失败并出现keyerror错误,'__getitem__'函数中的打印语句显示它正在传递'0'键。 – 2010-04-05 09:34:28

+0

Doh - 需要添加'__contains__' – 2010-04-05 09:34:46

+0

我最终这样做,因为它让我可以处理一些重复数据删除问题。 OTOH,我现在遇到了2GB 32位内存限制的问题。 \*叹\* – 2011-01-01 10:21:56

1

我记得 “集” 和 “字典” 也__hash__

使用来自Python 2.x doc

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

1

集和字典使用由对象的__hash__方法来查找对象返回的值,因此这将做你想做的:

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

当类'a'的'__hash __(self)'返回与字符串'x'相同的哈希值时,您可以获得额外的好处,无论您对a(x)进行字典查找还是'x'。 – ndim 2010-04-05 09:08:06

+0

好吧,但我该如何将类插入字典? 由于定义了__hash__,尝试将类的实例添加到字典中,可能会给我一个语法错误,或者在字典中使用键作为类本身的条目。 – 2010-04-05 09:13:20

0

你想是这样的

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> 
2

为什么你不只是做:

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

为什么要通过试图创建一个使用比你传递的那些不同的键手卷字典所有的麻烦在? (即“Hello”而不是MyStr(“Hello”))。

ex。

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")