Python 何时以及为什么使用self.\uuu dict\uuuu而不是self.variable

Python 何时以及为什么使用self.\uuu dict\uuuu而不是self.variable,python,class,dictionary,oop,Python,Class,Dictionary,Oop,我试图理解下面使用此类的一些代码结构: 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.__d

我试图理解下面使用此类的一些代码结构:

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
类基(对象):
定义初始(自我,**kwargs):
self.client=kwargs.get('client'))
self.request=kwargs.get('request'))
...
def到dict(自身):
数据=dict()

对于输入iter(self.uu dict_uu):#
u dict_u
保存类中的所有变量。参加以下课程:

class A():
定义初始化(self,foo):
self.foo=foo
def新_变量(自身,条形):
self.bar=bar
在这种情况下,请注意:

a = A('var1')
print(a.__dict__) # {'foo': 'var1'}

b = A('var1')
b.new_var('var2')
b.foobar = 'var3'
print(b.__dict__) # {'foo': 'var1', 'bar': 'var2', 'foobar': 'var3'}

在你的情况下,你可以做或
\uuuu dict\uuuu
是一种很好的方法,可以在调用该类的当前实例中获取属于该类的所有变量。您可以在
\uuuu dict\uuuu
上查看文档,几乎所有时间都不应该使用
self.\uu dict\uuuu

如果您正在访问一个属性,如
self.client
,即属性名是已知的和固定的,那么它与
self.\uu dict\uuu['client']
之间的唯一区别是,如果实例上缺少该属性,则后者不会在类上查找该属性。很少有理由这样做,但区别如下所示:

>>A类:
...     b=3#类属性,不是实例属性
... 
>>>A.b#该类具有此属性
3.
>>>a=a()
>>>a.b#实例没有此属性,请回退到类
3.
>>>a.uu dict_uu['b']#实例没有此属性,但没有回退
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
键错误:“b”
self.\uuuu dict\uuuu
的主要用例是当您不想访问固定的、已知的属性名称时。在几乎所有的代码中,您总是知道要访问哪个属性;如果您确实需要使用未知字符串动态查找某些内容,您应该自己创建一个字典,并编写
self.that\u dict[key]
,而不是
self

因此,您真正应该使用
\uuu dict\uuu
的唯一时间是在编写需要工作的代码时,无论实例可能具有哪些属性;i、 e.您特别需要即使更改类的结构或属性名称也能正常工作的代码,或者需要能够跨多个具有不同结构的类工作的代码。我将在下面展示一个示例

\uuuu repr\uuu
方法
\uuuuu repr\uuuu
方法用于返回表示实例的字符串,以方便程序员使用REPL。出于调试/测试目的,此字符串通常包含有关对象状态的信息。以下是实现此功能的常用方法:

Foo类:
定义初始化(self、foo、bar、baz):
self.foo=foo
self.bar=bar
self.baz=baz
定义报告(自我):
返回'Foo({!r},{!r},{!r})'.format(self.Foo,self.bar,self.baz)
这意味着如果您编写
obj=Foo(1,'y',True)
来创建一个实例,那么
repr(obj)
将是字符串
“Foo(1,'y',True)”
,这很方便,因为它显示了实例的整个状态,而且字符串本身也是创建具有相同状态的实例的Python代码

但是上面的实现存在一些问题:如果类的属性发生了变化,我们就必须对其进行更改,它不会为子类的实例提供有用的结果,并且我们必须为具有不同属性的不同类编写大量类似的代码。如果我们改用
\uuuuu dict\uuuu
,我们可以解决所有这些问题:

def\uuu repr\uu(自):
返回'{}({}')。格式(
self.\uuuuu类\uuuuuuu名\uuuuuuuuu,
“,”.join(“{}={!r}.”在self中为k,v设置格式(k,v)。_dict__.items()
)

现在
repr(obj)
将是
Foo(Foo=1,bar='y',baz=True)
,它还显示实例的整个状态,也是可执行的Python代码。如果
Foo
的结构发生变化,这种通用的
\uuuuu repr\uuuuu
方法仍然可以工作,它可以通过继承在多个类之间共享,并为属性被
\uuu init\uuuuu
接受为关键字参数的任何类返回可执行的Python代码,但它的真实世界用例是什么?为什么我要使用它而不是仅仅通过self.name调用呢?一个很好的例子是模块,它允许您将类保存到文件中并加载它们以供以后使用——在这种情况下,
pickle
将使用类
\u dict\u
将类序列化为
.p
文件。另一个例子是,如果您从外部模块初始化某个类,但不确定该类的属性是什么。。。打印
class.\uuuu dict.\uuuu
是检查您可以访问的变量的一种简单方法。我还邀请您使用上面的示例类(而不是
A.\uu dict.\uuu
)执行
A.\uuu dict.\uuu
)。您会注意到,
\uuuuuu dict\uuuu
将返回给定类中的所有函数+一些额外的内容。总之,
\uuu dict\uuu
可以用于现实世界中的许多事情,但是正如本文或文档所示,它是Python中数千种可访问的工具中唯一的一种。