Python 在类属性上映射dict项

Python 在类属性上映射dict项,python,class,dictionary,Python,Class,Dictionary,类实例的\uuu dict\uuu属性对于将给定的dict对象映射到类实例非常有用(dict的键在此过程中成为类实例属性) 例如: >>> class SomeClass(object): ... def __init__(self): ... self.numbers = [1, 3, 5, 7, 9] ... >>> inst = SomeClass() >>> inst.__dict__ {'numbers':

类实例的
\uuu dict\uuu
属性对于将给定的
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__
{}
在这种情况下,有没有办法访问它们?我的意思是,有没有一种方法可以独立于其他特殊类属性(如方法或默认属性)列出它们?

这些是类属性,而不是实例属性。类属性在实例之间共享。这也是实例继承其类的方法的方式。实例属性具有相同名称的阴影类属性,因此您可以在实例上设置
数字
,为实例提供自己的副本

您可以在实例上使用
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']
您可以使用筛选属性的类型

另一个选项是使用
\uuuuu dict\uuuu
列出类属性:

>>> 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]}
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})
>变量(类型(仪表))
dict_代理(dict_):

在类定义中定义的变量是类属性;它们由实例共享。可以使用
self.name=value
的方法设置实例属性。可以通过符号“
self.name
访问类和实例属性,实例属性以这种方式访问时隐藏具有相同名称的类属性

这些是类属性,而不是实例属性。类属性在实例之间共享。这也是实例继承其类的方法的方式。具有相同名称的实例属性会隐藏类属性,因此您可以在实例上设置
编号
,以使实例具有自己的副本

您可以在实例上使用
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']
您可以使用筛选属性的类型

另一个选项是使用
\uuuuu dict\uuuu
列出类属性:

>>> 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]}
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})
>变量(类型(仪表))
dict_代理(dict_):

在类定义中定义的变量是类属性;它们由实例共享。可以使用
self.name=value
的方法设置实例属性。可以通过符号“
self.name
访问类和实例属性,实例属性以这种方式访问时隐藏具有相同名称的类属性


如果将
numbers
定义为类属性

class SomeClass(object):
    numbers = [1, 3, 5, 7, 9]
然后它被放入
某个类中

>>> 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]}
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})
[5]中的
:某个类__
Out[5]:dict_代理(
{uuuu dict}:,
“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,
"weakref":,,
“数字”:[1,3,5,7,9],
“\uuuuuu doc\uuuuuuuuuuuuuu”:无})

如果将
数字
定义为类属性

class SomeClass(object):
    numbers = [1, 3, 5, 7, 9]
然后它被放入
某个类中

>>> 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]}
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})
[5]中的
:某个类__
Out[5]:dict_代理(
{uuuu dict}:,
“\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,
"weakref":,,
“数字”:[1,3,5,7,9],
“\uuuuuu doc\uuuuuuuuuuuuuu”:无})

我的建议是,你应该避免修改
\uuu dict\uuu
locals()
等等

为什么不在字典中显式地存储您希望是动态的属性呢?这样,您就不会有一堆对象和您不希望的属性,因为它们没有在类中定义,并且被其他地方的代码修补过

我认为这更清楚,也不那么可怕:

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

MyClass.classattrs['letters'] = ['a','b','c']
归根结底,人们希望dict的内容发生变化,而不希望类的属性发生变化

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


保持名称和属性(合理地)静态的想法已经被比我更聪明、更有经验的人表达出来了:

我的建议是,你应该避免修改
\u dict\u
locals()
等等

为什么不在字典中显式地存储您希望是动态的属性呢?这样,您就不会有一堆对象和您不希望的属性,因为它们没有在类中定义,并且被其他地方的代码修补过

我认为这更清楚,也不那么可怕:

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

MyClass.classattrs['letters'] = ['a','b','c']
归根结底,人们希望dict的内容发生变化,而不希望类的属性发生变化

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


比我更聪明、更有经验的人表达了保持名称和属性(合理地)静态的想法:

我理解其原理,但在我的特殊情况下,动态更改属性没有问题。如果我这样做,那是因为我发现了它(矛盾地)更容易处理。就凭你自己吧!如果你想要一个所有非“魔法”属性的列表,你可以尝试使用from
inspect.getmembers
-过滤掉所有双下划线名称:
[name,attr for name,attr in inspect.getmembers(MyClass)If not name.startswith(“\uuu”)而且不要检查。ismethod(attr)]
这太可怕了!:)所以我这样做似乎是错误的。我会尝试另一种方法。谢谢你的建议!我理解其基本原理,但在我的特殊情况下,动态更改属性是没有问题的。如果我这样做,那是因为我发现了它(矛盾的是)更容易处理。就凭你自己吧!如果你想要一个所有非“魔法”属性的列表,你可以尝试用from
inspect.getmembers
-类似的方法过滤掉所有双下划线名称