在类属性上映射dict项

时间:2013-04-18 21:17:39

标签: python class dictionary

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

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

3 个答案:

答案 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的内容发生变化。他们不希望类的属性发生变化。

在任何情况下,inspectdir及其同类将无法过滤掉所有其他类属性,例如特殊方法等。

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