类实例的__dict__
属性对于将给定的dict
对象映射到类实例非常有用(dict的键在进程中变为类实例属性)。
示例:
>>> class SomeClass(object):
... def __init__(self):
... self.numbers = [1, 3, 5, 7, 9]
...
>>> inst = SomeClass()
>>> inst.__dict__
{'numbers': [1, 3, 5, 7, 9]}
>>> inst.__dict__.update({
... 'letters': ['a', 'b', 'c', 'd'],
... 'numbers': [2, 4, 6, 8, 10]
... })
>>> inst.letters, inst.numbers
(['a', 'b', 'c', 'd'], [2, 4, 6, 8, 10])
但是,如果类属性声明如下,则不起作用:
>>> class SomeClass(object):
... numbers = [1, 3, 5, 7, 9]
...
>>> inst = SomeClass()
>>> inst.__dict__
{}
在这种情况下,有没有办法访问它们?我的意思是,有没有办法列出它们独立于其他特殊类属性,如方法或默认属性?
答案 0 :(得分:3)
这些是 class 属性,而不是实例属性。类属性在实例之间共享。这也是实例继承其类方法的方式。具有相同名称影子类属性的实例属性,因此您可以在实例上设置numbers
以为实例提供自己的副本。
您可以在实例上使用dir()
列出实例和类属性名称的组合视图:
>>> inst = SomeClass()
>>> dir(inst)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'numbers']
您可以使用inspect.getmembers()
过滤属性类型。
另一个选项是使用__dict__
列出类属性:
>>> vars(type(inst))
dict_proxy({'__dict__': <attribute '__dict__' of 'SomeClass' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'SomeClass' objects>, 'numbers': [1, 3, 5, 7, 9], '__doc__': None})
>>> {k: v for k, v in vars(type(inst)).iteritems() if not k.startswith('__') and not inspect.isfunction(v)}
{'numbers': [1, 3, 5, 7, 9]}
来自Class definitions documentation:
类定义中定义的变量是类属性;它们由实例共享。可以使用
self.name = value
在方法中设置实例属性。类和实例属性都可以通过符号“self.name
”访问,并且实例属性在以这种方式访问时会隐藏具有相同名称的类属性。
答案 1 :(得分:1)
如果您将numbers
定义为类属性,
class SomeClass(object):
numbers = [1, 3, 5, 7, 9]
然后将其放入SomeClass.__dict__
:
In [5]: SomeClass.__dict__
Out[5]: dict_proxy(
{'__dict__': <attribute '__dict__' of 'SomeClass' objects>,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'SomeClass' objects>,
'numbers': [1, 3, 5, 7, 9],
'__doc__': None})
答案 2 :(得分:1)
我的建议是,您应该避免修改__dict__
,locals()
等。
为什么不在字典中明确存储您期望动态的属性?这样你就不会最终得到一堆你没想到的属性的对象,因为它们没有在类中定义,而是被其他地方的代码修补过来。
我认为这更清晰,更不可怕:
class MyClass(object):
classattrs = {'numbers': [1,2,3,4,5]}
MyClass.classattrs['letters'] = ['a','b','c']
归结为人们期望dict的内容发生变化。他们不希望类的属性发生变化。
在任何情况下,inspect
,dir
及其同类将无法过滤掉所有其他类属性,例如特殊方法等。
这种保持名称和属性(合理)静态的想法已经被人们表达得比我更聪明,更有经验:http://nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html