python class(dict)和class(s​​tr)之间的区别

时间:2016-04-06 16:11:43

标签: python

我想知道class(dict)和class(s​​tr)之间存在什么样的差异 这是我的代码

class MyDict3(str):
     def __init__(self):
         self.a = None 

class MyDict(dict):
     def __init__(self):
         self.a = None

这些类是我为澄清而做的 然后我在下面输入

>>> mydict['a'] = 1
>>> mydict
{'a': 1}
>>> mydict3['a'] = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'MyDict3' object does not support item assignment

为什么我的mydict3 ['a']会出错? 我所做的不同只是MyDict(dict)和MyDict(str) 据我所知,我指定的对象(dict,str)只不过像c ++,java这样的构造函数

请给我一个明确的答案。

1 个答案:

答案 0 :(得分:0)

  

为什么我的mydict3 [&#39; a&#39;]会出错?我所做的差异只有MyDict(dict)和MyDict(str)据我所知,我指定的对象(dict,str)只不过是像c ++,java

这样的构造函数。

我相信你在这里做了一个混乱,认为一个类属性和一个项目是一样的,就像下面的javascript代码一样:

> foo = {'a': 42};
{ a: 42 }
> foo.a
42
> foo['a']
42
> foo.a === foo['a']
true

但是在python中foo.afoo['a']是两种不同的机制。当您致电foo.a时,您实际上正在访问通过类定义定义的类的a属性:

class Foo:
    def __init__(self):
        self.a = 42 # declaring and defining the a attribute

然后您可以使用以下方式访问它:

 >>> foo = Foo()
 >>> print(foo.a)
 42

但要使foo['a']正常工作,您必须使用索引机制,该机制通常用于词典或列表:

>>> foo = {'a': 42}
>>> foo['a']
42

该机制正由您班级的__getitem__方法实施,因此您可以根据需要重载:

class Foo:
    def __getitem__(self, val):
        if val == 'a':
            return 42
        raise KeyError('Unknown key') # when the key is unknown, you raise a key error exception

>>> foo = Foo()
>>> foo['a']
42
>>> foo['b']
KeyError: 'Unknown key'

因此,dict类是一个实现__getitem__(和__setitem__以及许多其他类)的类,以便为您提供称为字典的正确映射机制。键可以是任何不可变对象,并且值可以是任何值。对于列表,它应该只是整数(列表中的位置)。

话虽如此,让我们回答你的问题:

  

为什么我的mydict3 [&#39; a&#39;]会出错?

显然它是因为你将mydict3定义为字符串的实现,它具有__getitem__方法的特殊实现:它为你提供了一个字符参数位置,如果列表是一个字符列表(如在C中)。

因此,当您尝试使用mydict3索引'a'时,python只会告诉您,您所要求的内容毫无意义!

所以最后,当你说:

  

我所做的不同只是MyDict(dict)和MyDict(str)

它实际上是一个非常大的差异! dictstr没有相同的界面,因此您想要做的事情无法发挥作用!

P.S。:实际上,没有什么是黑色或白色。一个类的实现实际上是一个dict,你可以访问一个类的所有成员&#39;实例通过实例的__dict__成员:

class Foo():
    def __init__(self):
        self.a = 42

>>> foo = Foo()
>>> foo.__dict__['a']
42

但您永远不会直接直接访问__dict__实例,并使用辅助函数setattrgetattr

>>> setattr(foo, 'b', 42)
>>> getattr(foo, 'b')
42
>>> getattr(foo, 'a')
42

这是一些高级的python技巧,应谨慎使用。如果真的 没有别的办法,那么也许你应该使用它。

此外,还有一个特殊的类将dict项转换为类成员,它是namedtuple

>>> from collections import namedtuple
>>> d = {'a': 42, 'b': 69}
>>> SpecialDict = namedtuple('SpecialDict', d.keys())
>>> foo = SpecialDict(**d)
>>> d.a
42
>>> d.b
69

HTH