我正在尝试理解一些代码,这些代码使用了下面的类:
class Base(object):
def __init__(self, **kwargs):
self.client = kwargs.get('client')
self.request = kwargs.get('request')
...
def to_dict(self):
data = dict()
for key in iter(self.__dict__): # <------------------------ this
if key in ('client', 'request'):
continue
value = self.__dict__[key]
if value is not None:
if hasattr(value, 'to_dict'):
data[key] = value.to_dict()
else:
data[key] = value
return data
我知道它获取传递给Base
类的关键字参数,例如Base(client="foo", request="bar")
。
我的困惑是,为什么要使用self.__dict__
将__init__
中的变量转换为dict(例如{"client": "foo", "request": "bar"}
),而不是在其他方法中通过self.client
和self.request
调用它们?何时以及为什么应该使用self.__dict__
?
3条答案
按热度按时间rkue9o1l1#
几乎在所有情况下,都不应该使用
self.__dict__
。如果你访问的是
self.client
这样的属性,也就是说,属性名是已知的并且是固定的,那么self.__dict__['client']
和self.__dict__['client']
之间的唯一区别就是,如果示例中缺少属性,self.__dict__['client']
不会在类中查找该属性。很少有理由这样做,但是区别如下所示:self.__dict__
的主要用例是当你 * 不 * 想访问一个固定的、已知的属性名时。如果确实需要使用未知字符串动态查找某些内容,则应该自己创建一个字典,并编写self.that_dict[key]
而不是self.__dict__[key]
。因此,只有在编写需要工作的代码时,才应该真正使用
__dict__
,而不管示例可能具有哪些属性;也就是说,你特别想要的代码,即使你改变了类的结构或它的属性名,也能工作,或者代码能跨多个具有不同结构的类工作。__repr__
方法__repr__
方法的作用是返回一个代表示例的字符串,方便程序员使用REPL。为了调试/测试的目的,这个字符串通常包含对象状态的信息。下面是一个实现它的常用方法:这意味着如果你写
obj = Foo(1, 'y', True)
来创建一个示例,那么repr(obj)
将是字符串"Foo(1, 'y', True)"
,这很方便,因为它显示了示例的整个状态,而且字符串本身是Python代码,它创建了一个具有相同状态的示例。但上述实现存在一些问题:如果类的属性改变了,我们就必须改变它,它不会为子类的示例给予有用的结果,而且我们必须为具有不同属性的不同类编写大量类似的代码。如果我们改用
__dict__
,我们就可以解决所有这些问题:现在
repr(obj)
将是Foo(foo=1, bar='y', baz=True)
,它也显示了示例的整个状态,也是可执行的Python代码。如果Foo
的结构发生变化,这个通用的__repr__
方法仍然可以工作,它可以通过继承在多个类之间共享。并且它返回__init__
接受其属性作为关键字参数的任何类的可执行Python代码。l5tcr1uw2#
__dict__
保存类中的 * 所有 * 变量。在这种情况下,请注意:
__dict__
是一个很好的方法,可以在调用该类的当前示例中获取属于该类的所有变量。您可以在此处查看__dict__
的文档。bwleehnv3#
**dict**用于检查对象具有哪些示例变量(数据属性)。
所以,如果下面有
Person
类:**dict**会取得
name
和age
,其值位于字典中,如下所示:如果示例化后添加新示例变量
gender
,如下所示:**dict**会取得
name
、age
和gender
,其值位于字典中,如下所示: