Python的"类是一个字典"理论和添加类变量的后果

Hra*_*bal -2 python dictionary class

出于好奇,我正在使用__dict__Python类的属性.

我在某处读到python中的"类"是一种字典,并且调用__dict__类实例将实例转换为字典......我认为"很酷!我可以使用它!"

但这让我怀疑这些行为的正确性和安全性.

例如,如果我这样做:

class fooclass(object):
    def __init__(self, arg):
        self.arg1 = arg

p = fooclass('value1')
print(p.__dict__)
p.__dict__['arg2'] = 'value2'
print(p.__dict__)
print(p.arg2)
Run Code Online (Sandbox Code Playgroud)

我有这个:

>>>{'arg1': 'value1'}
>>>{'arg1': 'value1', 'arg2': 'value2'}
>>>value2
Run Code Online (Sandbox Code Playgroud)

那没关系,但是:

  1. 是否fooclass还有1个属性?我怎么能确定?
  2. 以这种方式添加属性是否安全?
  3. 你曾经有过这个派上用场的案例吗?
  4. 我看到我不能这样做fooclass.__dict__['arg2'] = 'value2'...为什么一个类和一个实例之间存在这种差异?

Mar*_*ers 5

您正在更改实例的属性.添加和删​​除__dict__正是大多数自定义类实例所发生的事情.

例外情况是你有一个使用的类__slots__; 这种类的实例没有__dict__属性,因为属性以不同的方式存储.

Python是一种同意成年人的语言; __dict__在任何情况下都没有防止向实例添加属性的保护,因此将它们添加到字典或使用setattr()没有区别.

__dict__当您想使用现有dict方法访问或更改属性时,访问它会很有帮助; 你可以使用dict.update()例如:

def Namespace(object):
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
Run Code Online (Sandbox Code Playgroud)

在尝试读取类上有相应数据描述符的实例上的属性时,它也很有用; 绕过后者,您可以访问__dict__实例以获取属性.您还可以使用它来测试实例上的属性,并忽略类或基类可能定义的任何内容.

至于fooclass.__dict__; 你把这个与一个类的实例混淆了.它们是独立的对象.类是不同类型的对象,ClassObj.__dict__只是一个代理对象; 你仍然可以setattr()在类上使用添加任意属性:

setattr(fooclass, 'arg2', 'value2')
Run Code Online (Sandbox Code Playgroud)

或直接设置属性:

fooclass.arg2 = value2
Run Code Online (Sandbox Code Playgroud)

类需要有一个__dict__ 代理,因为实际__dict__属性是一个描述符对象,用于在实例上提供相同的属性.请参阅Python类的__dict __.__ dict__属性是什么?

有关Python对象如何工作的详细信息,请参阅Datamodel参考文档.