Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.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 - Fatal编程技术网

在Python中按顺序获取实例变量

在Python中按顺序获取实例变量,python,Python,假设我有以下课程: class Foo(object): def __init__(self, value): self.d = value self.a = value self.s = value self.k = value 我想按照申报的顺序来申报 我尝试了vars(),但没有成功: list(vars(Foo('value')).keys()) # ['a', 'k', 's', 'd'] 我想要的是: lis

假设我有以下课程:

class Foo(object):
    def __init__(self, value):
        self.d = value
        self.a = value
        self.s = value
        self.k = value
我想按照申报的顺序来申报

我尝试了
vars()
,但没有成功:

list(vars(Foo('value')).keys())
# ['a', 'k', 's', 'd']
我想要的是:

list(magic_method(Foo('value')).keys())
# ['d', 'a', 's', 'k']
编辑

显然,每个字段都有不同的值

我的目标是通过对象变量生成XML。为了有效,XML标记必须按正确的顺序排列

这样,再加上
\uuu iter\uuu
覆盖,我只需要管理对象的字典就可以生成XML

让我们以一个图书馆为例。假设你有一本课
日期
作者
借款人

class Book(object):
    def self.__init__()
        self._borrower = Borrower()
        self._author = Author()

class Date(object)
    def __init__(self, date):
        self._date = date

class Person(object):
    def __init__(self, name):
        self._name = name

class Author(object):
    def __init__(self):
        self._person = Person("Daniel")

class Borrower(object):
    def __init__(self):
        self._person = Person("Jack")
        self._date = Date("2016-06-02")
我想创建以下XML:

<Book>
    <Borrower>
        <Person>Jack</Person>
        <Date>2016-06-02</Date>
    </Borrower>
    <Author>
        <Person>Daniel</Person>
    </Author>
</Book>

杰克
2016-06-02
丹尼尔
我知道这些类可能看起来很奇怪(比如这里的Date),但我想让问题尽可能简单(还有一些字段非常有意义)。实际上,我会查询数据库,并可能在初始值设定项中传递记录标识符。关键是有些数据遵循相同的语法(即这里的Person)


总之,我想使用Python对象创建这样一个XML。秩序很重要。这就是为什么我想检索变量以达到这个目的:然后我可以提取类并生成XML标记。

如果不使用元类,就很难做到这一点(正如@Daniel所说)。但是,如果您想要一个产生类似效果的解决方案,您可以将所有“实例变量”存储在:


如果您想对对象变量进行排序,可以使用以下方法:

from collections import OrderedDict

class FooModel(object):
    def __new__(cls, *args, **kwargs):
        instance = object.__new__(cls)
        instance.__odict__ = OrderedDict()
        return instance

    def __setattr__(self, key, value):
        if key != '__odict__':
            self.__odict__[key] = value
        object.__setattr__(self, key, value)

    def keys(self):
        return self.__odict__.keys()

    def iteritems(self):
        return self.__odict__.iteritems()


class Foo(FooModel):
    def __init__(self, value):
        self.d = value
        self.a = value
        self.s = value
        self.k = value
输出:

>>> f = Foo('value')
>>> f.x = 5
>>> f.y = 10
>>> f.a = 15
>>> f2 = Foo('value')
>>> print "f.keys()", f.keys()
f.keys() ['d', 'a', 's', 'k', 'x', 'y']
>>> print "f2.keys()", f2.keys()
f2.keys() ['d', 'a', 's', 'k']
print list(f.iteritems())
[('d', 'value'), ('a', 15), ('s', 'value'), ('k', 'value'), ('x', 5), ('y', 10)]

你可以给你的类一个类似于
\uuuu dict\uuuu
的方法,但是它会返回一个OrderedDict

from collections import OrderedDict

class Foo(object):
    def __init__(self, d, a, s, k):
        self.d = d
        self.a = a
        self.s = s
        self.k = k

    def ordered_dict(self):
        return OrderedDict(
            (key, getattr(self, key)) for key in ('d', 'a', 's', 'k')
        )
这是这样的:

>>> myfoo = Foo('bar', 1, 7, 'foo')
>>> myfoo.ordered_dict()
OrderedDict([('d', 'bar'),('a', 1), ('s', 7), ('k', 'foo')])

>>> list(myfoo.ordered_dict())
['d', 'a', 's', 'k']

您可以实现
\uuuu setattr\uuuu
方法来跟踪以下内容:

#!python3
class OrderedAttrs:
    def __init__(self, d, a, s, k):
        self._order = []
        self.d = d
        self.a = a
        self.s = s
        self.k = k


    def __setattr__(self, name, value):
        super().__setattr__(name, value)

        if not name in self._order:
            self._order.append(name)

        return value

    def ordered_attrs(self, with_order=False):
        return [(k,getattr(self, k)) for k in self._order if k != '_order' or with_order]

oa = OrderedAttrs('dee', 'eh', 'ess', 'kay')
oa.foo = 'bar'
oa.baz = 'moo'

print("Default:",oa.ordered_attrs())
print("With _order:", oa.ordered_attrs(with_order=True))

我认为这是不可能的,因为字典不能维持秩序。@JonathonReinhart:可以用元类……
keys().sorted(key=lambda x:mapdict[x])
?@AlexHall:请看我的编辑。:)@tripleee:除非我弄错了,
list(vars(Foo('value')).keys().sorted(key=lambda x:mapdict[x])
产生以下错误:
AttributeError:'list'对象没有“sorted”属性。
。你能更明确一点吗?但是这些不能作为常规实例变量访问。当然不能,但它确实“产生了类似的效果”。这就是为什么我写了“实例变量”(注意引号)。如果您不想编写自己的元类,这将是您所能得到的最接近的结果。这很有趣,而且似乎很有效,但我收到了一条
DeprecationWarning:object()不带参数的消息。我使用的是python2.7。不幸的是,这正是我想要获得变量实例的原因,这要归功于
vars()
。我必须键入许多变量名:/如果您想以特定的正确顺序获取属性,您必须在某个地方声明该顺序。
#!python3
class OrderedAttrs:
    def __init__(self, d, a, s, k):
        self._order = []
        self.d = d
        self.a = a
        self.s = s
        self.k = k


    def __setattr__(self, name, value):
        super().__setattr__(name, value)

        if not name in self._order:
            self._order.append(name)

        return value

    def ordered_attrs(self, with_order=False):
        return [(k,getattr(self, k)) for k in self._order if k != '_order' or with_order]

oa = OrderedAttrs('dee', 'eh', 'ess', 'kay')
oa.foo = 'bar'
oa.baz = 'moo'

print("Default:",oa.ordered_attrs())
print("With _order:", oa.ordered_attrs(with_order=True))