0

类实例的__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__
{}

在这种情况下有没有办法访问它们?我的意思是,有没有办法独立于其他特殊类属性(例如方法或默认属性)列出它们?

4

3 回答 3

3

这些是属性,而不是实例属性。类属性在实例之间共享。这也是实例继承其类的方法的方式。实例属性具有同名的影子类属性,因此您可以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]}

类定义文档中:

类定义中定义的变量是类属性;它们由实例共享。实例属性可以在带有 的方法中设置self.name = value。类和实例属性都可以通过符号“<code>self.name”访问,并且以这种方式访问​​时,实例属性会隐藏同名的类属性。

于 2013-04-18T21:20:21.663 回答
1

我的建议是你应该避免修改__dict__locals()等等。

为什么不将您期望动态的属性显式存储在字典中?这样,您最终不会有一堆带有您不期望的属性的对象,因为它们不是在类中定义的,而是由其他地方的代码进行猴子修补的。

我认为这更清晰,更不可怕:

class MyClass(object):
    classattrs = {'numbers': [1,2,3,4,5]}

MyClass.classattrs['letters'] = ['a','b','c']

归结为人们期望 dict 的内容会改变的事实。他们不期望类的属性会改变。

在任何情况下inspectdir和它们的同类将难以过滤掉所有其他类属性,如特殊方法等。

这种保持名称和属性(合理地)静态的想法已经被比我更聪明、更有经验的人表达了:http: //nedbatchelder.com/blog/201112/keep_data_out_of_your_variable_names.html

于 2013-04-18T21:28:38.667 回答
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})
于 2013-04-18T21:24:22.523 回答