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

时间:2014-09-11 11:21:57

标签: python class dictionary

出于好奇,我正在使用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

那没关系,但是:

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

1 个答案:

答案 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