只是出于好奇,我在Python类上玩__dict__
属性。
我在某个地方读到python中的"class"是一种dict,在类实例上调用__dict__
将该实例转换为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)
我有这个:
>>>{'arg1': 'value1'}
>>>{'arg1': 'value1', 'arg2': 'value2'}
>>>value2
这很好,但是:
fooclass
还有1个属性吗?我怎么能确定呢- 这样添加属性安全吗
- 你有没有遇到过这种方法派上用场的案例
- 我发现我不能做
fooclass.__dict__['arg2'] = 'value2'
。。那么,为什么类和实例之间存在这种差异呢
您正在更改实例的属性。从__dict__
中添加和删除正是大多数自定义类实例所发生的情况。
例外情况是当您有一个使用__slots__
的类时;这种类的实例不具有__dict__
属性,因为属性以不同的方式存储。
Python是一种成年人自愿使用的语言;在任何情况下都无法防止使用__dict__
向实例添加属性,因此将它们添加到字典或使用setattr()
也没有什么区别。
当您想要使用现有的dict
方法来访问或更改属性时,访问__dict__
非常有用;可以使用dict.update()
,例如:
def Namespace(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
当尝试读取实例上的属性时,这也很有帮助,因为类上有相应的数据描述符;要绕过后者,可以访问实例上的__dict__
以获取属性。您还可以使用它来测试实例上的属性,并忽略类或基类可能定义的任何内容。
对于fooclass.__dict__
;您将类与类的实例混淆。它们是单独的对象。类是不同类型的对象,ClassObj.__dict__
只是一个代理对象;您仍然可以在类上使用setattr()
来添加任意属性:
setattr(fooclass, 'arg2', 'value2')
或直接设置属性:
fooclass.arg2 = value2
类需要有一个__dict__
代理,因为实际的__dict__
属性是一个描述符对象,用于在实例上提供相同的属性。请参阅__dict__是什么__Python类的dict__属性?
有关Python对象如何工作的详细信息,请参阅Datamodel参考文档。