我的代码中有两个类。 first
是父项,second
继承。
class first(object):
def __init(self,**kwargs):
pass
def __setattr__(self,name,value):
self.__dict__[name] = value
class second(first):
def do_something(self):
self.a = 1
self.b = 2
self.c = 3
当我打印第二课时(例如second.__dict__
),我得到无序字典。这很明显。我想更改此行为以使用OrderedDict
类获取有序字典,但它不起作用。我正在通过以下方式更改first
的实施:
class first(OrderedDict):
def __init__(self,**kwargs):
super(first,self).__init__(**kwargs)
def __setattr__(self,name_value):
super(first,self).__setattr__(name_value)
我想使用second
或__dict__
打印__repr__
,但我收到了无序词典。我应该改变什么?
答案 0 :(得分:8)
您只需将所有属性访问权限重定向到OrderedDict
:
class first(object):
def __init__(self, *args, **kwargs):
self._attrs = OrderedDict(*args, **kwargs)
def __getattr__(self, name):
try:
return self._attrs[name]
except KeyError:
raise AttributeError(name)
def __setattr__(self, name, value):
if name == '_attrs':
return super(first, self).__setattr__(name, value)
self._attrs[name] = value
演示:
>>> from collections import OrderedDict
>>> class first(object):
... def __init__(self, *args, **kwargs):
... self._attrs = OrderedDict(*args, **kwargs)
... def __getattr__(self, name):
... try:
... return self._attrs[name]
... except KeyError:
... raise AttributeError(name)
... def __setattr__(self, name, value):
... if name == '_attrs':
... return super(first, self).__setattr__(name, value)
... self._attrs[name] = value
...
>>> class second(first):
... def do_something(self):
... self.a = 1
... self.b = 2
... self.c = 3
...
>>> s = second()
>>> s.do_something()
>>> s._attrs
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
您不能用__dict__
实例替换OrderedDict
属性,因为Python通过使用具体的类API来访问C中的字典内部优化实例属性访问,绕过{{1完全挂钩(见issue #1475692)。
答案 1 :(得分:4)
我认为此主题中的解决方案过于关注使用OrderedDict
,就好像它是必需的一样。该类已经有一个内置__dict__
方法,唯一的问题是订购密钥。以下是我按照输入顺序从班级中检索(key, value)
对的方法:
class MyClass:
def __init__(self, arg1, arg2, arg3):
self._keys = []
self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3
def __setattr__(self, key, value):
# store new attribute (key, value) pairs in builtin __dict__
self.__dict__[key] = value
# store the keys in self._keys in the order that they are initialized
# do not store '_keys' itelf and don't enter any key more than once
if key not in ['_keys'] + self._keys:
self._keys.append(key)
def items(self):
# retrieve (key, value) pairs in the order they were initialized using _keys
return [(k, self.__dict__[k]) for k in self._keys]
>>> x = MyClass('apple', 'orange', 'banana')
>>> print x.items()
[('arg1', 'apple'), ('arg2', 'orange'), ('arg3', 'banana')]
>>> x.arg1 = 'pear'
>>> print x.items()
[('arg1', 'pear'), ('arg2', 'orange'), ('arg3', 'banana')]
我正在使用一个类来存储大约70个用于配置和运行更大程序的变量。我保存了初始(key, value)
对的文本副本,可以用来初始化类的新实例。我还在运行程序后保存了(key, value)
对的文本副本,因为在程序运行期间设置或更改了其中几个。当我想要扫描结果时,按顺序排列(key, value)
只会提高文本文件的可读性。
答案 2 :(得分:1)
你可以尝试用OrderedDict实际替换__dict__:
from collections import OrderedDict
class Test(object):
def __init__(self):
self.__dict__ = OrderedDict()
self.__dict__['a'] = 0
self.__dict__['b'] = 1
self.__dict__['c'] = 2
test = Test()
print test.__dict__
test.a, test.b, test.c = 'a', 'b', 'c'
print test.__dict__
这应该打印输出:
OrderedDict([('a', 0), ('b', 1), ('c', 2)])
OrderedDict([('a', 'a'), ('b', 'b'), ('c', 'c')])
答案 3 :(得分:-1)
另一种选择;如果您愿意,也可以操纵新。
from collections import OrderedDict
class OrderedClassMeta(type):
@classmethod
def __prepare__(cls, name, bases, **kwds):
return OrderedDict()
class OrderedClass(metaclass=OrderedClassMeta):
pass
class A(OrderedClass):
def __init__(self):
self.b=1
self.a=2
def do(self):
print('do')
class B(OrderedClass):
def __init__(self):
self.a=1
self.b=2
def do(self):
print('do')
a=A()
print(a.__dict__)
b=B()
print(b.__dict__)