Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
对类对象重新排序的最具python风格的方式是什么';属性?_Python_Xml_Dictionary_Attributes - Fatal编程技术网

对类对象重新排序的最具python风格的方式是什么';属性?

对类对象重新排序的最具python风格的方式是什么';属性?,python,xml,dictionary,attributes,Python,Xml,Dictionary,Attributes,我正在创建一组Python 2.7/3+工具,以编程方式修改团队经常使用的XML文件的内容。到目前为止,我正在将XML解析为有意义的类对象属性(通过**kwargs和和dict\uuuuu.update()或setattr()),我已经将一些相当复杂的方法与之关联。我非常喜欢能够根据方法调用定义我的自动化,例如foo.do\u complex\u modification(x) 现在,我想将修改后的数据写回XML文件,供软件的其余部分使用。文件的内容很好,但不幸的是,我们的遗留工具只接受保留顺序

我正在创建一组Python 2.7/3+工具,以编程方式修改团队经常使用的XML文件的内容。到目前为止,我正在将XML解析为有意义的类对象属性(通过
**kwargs
dict\uuuuu.update()
setattr()
),我已经将一些相当复杂的方法与之关联。我非常喜欢能够根据方法调用定义我的自动化,例如
foo.do\u complex\u modification(x)

现在,我想将修改后的数据写回XML文件,供软件的其余部分使用。文件的内容很好,但不幸的是,我们的遗留工具只接受保留顺序的XML,我不能指望Python对象字典提供这一点。在解析XML时,我可以按照“正确”的顺序阅读,而不会出现任何问题,并以某种方式存储,但修改遗留系统不是一种选择

可能是相关的,XML还有一个XSD模式

问题:序列化类属性以保持其原始顺序的最简洁或优雅的方式是什么?如果合适,当从对象的
\uuuu dict\uuu
读回时,我将如何编写,比如说,
.sort(key=ordering\u函数)

class Foo(object):
    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)
    def really_complex_method(self):
        pass


def attrs(cls):   
    return [(k, v) for k, v in cls.__dict__.items() if k[:1] != '_']

d = dict(bar=1, baz=2, quux=3)  # Need them back in this particular order
print(attrs(Foo(**d)))
返回

[('quux', 3), ('bar', 1), ('baz', 2)]

并且在Python 3.6之前的任何版本上都是未排序的。

即使您对类属性进行排序,只要它们存储在
dict中,顺序就会改变。最好的方法是使用
OrderedDict
,它将保留
sorted()
方法的顺序

from collections import OrderedDict

class Foo(object):
    def __init__(self, **kwargs):
        for k, v in kwargs.items():
            setattr(self, k, v)
    def really_complex_method(self):
        pass


def attrs(cls):
    return OrderedDict(sorted(cls.__dict__.items()))

d = dict(bar=1, baz=2, quux=3)
print(attrs(Foo(**d)))

最大的问题可能是因为您一直在传递关键字参数,这并没有保留它们的定义顺序。另一个问题是
类.\uu dict\uu
是无序的。这里有一种解决这两个问题的方法(并不假设您希望属性按名称的字母顺序排列)。替换类的special
\uuuu dict\uuu
属性的技术是允许的,因为正如所说的,它可以是“字典或其他映射对象”(emphasis mine)。在Python2和Python3中都是如此

from collections import OrderedDict
from operator import itemgetter

class Foo(object):
    def __init__(self, *keyvalues):
        self.__dict__ = OrderedDict(keyvalues)

    def really_complex_method(self):
        pass

def attrs(instance):
    """ Return a list of instance attributes sorted by their value. """
    return sorted(instance.__dict__.items(), key=itemgetter(1))

print(attrs(Foo(('bar', 1), ('baz', 2), ('quux', 3), ('question', -42))))
输出:

[('question', -42), ('bar', 1), ('baz', 2), ('quux', 3)]
使用
OrderedDict
的替代方法是创建自己的映射类。这里有一个takien(关于Python3中的元类,但与主题无关)。它也适用于Python 2和Python 3):

另一种方法是,让类跟踪添加到实例中的顺序属性,然后按该顺序迭代它们,而不需要更改实例的

from operator import itemgetter

class Foo(object):
    def __init__(self, *keyvalues):
        self._sequence = []
        for (key, value) in keyvalues:
            setattr(self, key, value)
            self._sequence.append(key)  # keep track of order added

    def __iter__(self):
        for key in self._sequence:
            yield key, getattr(self, key)

    def really_complex_method(self):
        pass

def attrs(instance):
    """ Return a list of instance attributes sorted their value. """
    return sorted((item for item in instance), key=itemgetter(1))

print(attrs(Foo(('bar', 1), ('baz', 2), ('quux', 3), ('question', -42))))

注意在所有这些实现中,如果未使用
sorted()
函数
attrs()
函数,则属性将按照添加的顺序进行访问(这是您在修改问题之前最初似乎唯一需要的内容)。

您的回答非常感谢realtom。我知道我应该在我的示例中使用一个列表:取消排序实际上是在设置对象属性的
\uu dict\uu
时发生的。不幸的是,调用
orderedict
从中读取并不能解决这个问题。事实上,我已经更新了这个问题来强调这一点。你能私下告诉我你的口述顺序吗?换句话说,在继续这个过程之前,你能得到你想要的订单吗?@Chiheb-Nexus:当然。将更新问题以反映这一点。好吧,正如我所看到的,整个问题是查找返回dict是否具有与
d dict相同的顺序。正确的?如果不返回实质上具有相同顺序的dict,则返回yes。请注意,我使用的实际的
\uuuu dict\uuu
包含相当多的元素。但是我黑客攻击的每一种方法似乎都太冗长了,而且都不是pythonesque。我从来没想过你可以将
\uuuu dict\uuuu
重新转换为
有序的dict
。那是非常非常聪明的马蒂诺先生!弗朗索瓦:谢谢。Python并不总是允许您做这样的事情,但是在
\uuuuu dict\uuuu
的情况下,它确实允许您做这样的事情
OrderedDict
是内置的
dict
类的一个子类,因此它完全适合账单。
from operator import itemgetter

class Foo(object):
    def __init__(self, *keyvalues):
        self._sequence = []
        for (key, value) in keyvalues:
            setattr(self, key, value)
            self._sequence.append(key)  # keep track of order added

    def __iter__(self):
        for key in self._sequence:
            yield key, getattr(self, key)

    def really_complex_method(self):
        pass

def attrs(instance):
    """ Return a list of instance attributes sorted their value. """
    return sorted((item for item in instance), key=itemgetter(1))

print(attrs(Foo(('bar', 1), ('baz', 2), ('quux', 3), ('question', -42))))