前言

一般情况下,我们在初始化 dict (字典)时会直接 {key: value} 这么定义,亦或是使用 dict(key=value) 定义使用。而当处理对象变成了在一个类,在使用 obj.__dict__ 魔法函数时,我们拿到的将会是这个类的实例变量,定义在类体中的类变量,我们是无法直接获取到的。

纷争开始

要想实现以 dict 的方式读取类/实例变量,我们duck不必使用库或其他依赖。下面我们看个例子:

上述代码在实际运行时,将会得到 TypeError: ‘A’ object is not iterable 的错误。这是因为 dict 对象是需要可迭代的,也就是需要属于 iter,或者实现其所有方法。

我们再看一个例子:

当我们在 keys 这个方法上打上断点,以断点调试的方法运行程序时会发现,程序将会停在这一行代码上。这是因为,在默认情况下,我们在将对象直接传给 dict 的时候,dict 将会去这个类里寻找 keys 方法,以期望拿到字典的所有键。而这些键是由我们自己定义并返回的。再看下面的例子:

运行上述代码我们将会得到 TypeError: 'A' object is not subscriptable 的错误。这是因为,在默认情况下我们无法以中括号的方式去访问一个对象,但是我们可以使用一个方法,以改变这种情况。再看下面的例子:

运行代码之后将会发现,代码不再报错并且打印出来的数值与 __getitem___ 所返回的值一样。这就是使用中括号调用的结果。如果我们想拿到某个变量所对应的值,我们可以使用 getattr。如下所示:

上述代码将会打印出:

{'a': 1, 'b': 2, 'c': 3, 'd': 4}

通过上述代码,我们已经将对象以字典的方法拿到了类里的变量,不论类变量还是实例变量。

片尾

以上便是本次文章的所有内容,介绍了如何以 dict 的方式访问实例变量。并没有同时介绍以对象的方式读取 dict 数据,因为反过来我们可以很容易的实现这个需求,这里推荐使用 namedtuple 内置库。

本文不涉及 dict 的基础知识以及底层原理,毕竟网上教程已经非常之充实了,这里不再赘述。

dict 的键,必须是可 hash 的。这是 dict 非常重要的一点。