出于好奇,我正在使用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'
..那么为什么一个类和一个实例之间存在这种差异?答案 0 :(得分:5)
您正在更改实例的属性。添加和删除__dict__
正是大多数自定义类实例所发生的事情。
例外情况是你有一个使用__slots__
的课程;此类的实例没有__dict__
属性,因为属性以不同的方式存储。
Python是一种同意成年人的语言;在任何情况下,都没有保护以防止向__dict__
的实例添加属性,因此将它们添加到字典或使用setattr()
没有任何区别。
如果要使用现有的__dict__
方法访问或更改属性,访问dict
会很有帮助;您可以使用dict.update()
例如:
def Namespace(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
尝试读取在类上有相应data descriptor的实例上的属性时,它也很有用;绕过后者,您可以访问实例上的__dict__
以获取属性。您还可以使用它来测试实例上的属性,并忽略类或基类可能定义的任何内容。
至于fooclass.__dict__
;您将类与类的实例混淆。它们是独立的对象。类是不同类型的对象,ClassObj.__dict__
只是一个代理对象;你仍然可以在类上使用setattr()
来添加任意属性:
setattr(fooclass, 'arg2', 'value2')
或直接设置属性:
fooclass.arg2 = value2
一个类需要有一个__dict__
代理,因为实际的__dict__
属性是一个描述符对象,用于在实例上提供相同的属性。见What is the __dict__.__dict__ attribute of a Python class?
有关Python对象如何工作的详细信息,请参见Datamodel reference documentation。