【问题标题】:How to iterate over a the attributes of a class, in the order they were defined? [duplicate]如何按照定义的顺序遍历类的属性? [复制]
【发布时间】:2011-01-17 20:48:29
【问题描述】:

Python 带有方便的dir() 函数,它可以为您列出类的内容。例如,对于这个类:

class C:
   i = 1
   a = 'b'

dir(C) 会返回

['__doc__', '__module__', 'a', 'i']

这很好,但请注意 'a''i' 的顺序现在与定义它们的顺序有何不同。

如何按定义的顺序迭代 C 的属性(可能忽略内置的文档和模块属性)?对于上面的 C 类,将是 'i' 然后是 'a'

附录: - 我正在编写一些序列化/日志记录代码,我想在其中按照定义的顺序对属性进行序列化,以便输出类似于创建类的代码。

【问题讨论】:

  • 为什么定义它们的顺序很重要?在这种情况下,顺序无关紧要。如果你能得到这些信息,你会如何使用它?
  • 你是在序列化类还是类的实例?在您的示例中,ai 是类属性。如果你的意思是这些是实例属性,你应该在__init__ 中使用self.a = 'b'self.i = 1 定义它们。
  • 这些是类级别的属性,不如实例变量有用。你为什么要保持类属性的顺序?保留实例变量的顺序不是更好吗?你为什么要尝试使用类级变量?
  • 我正在构建一个生成的类定制代码,该代码被注入到类对象中。在类级别上枚举属性是一个自然的选择。如果切换到实例对象会让事情变得更容易,我会很乐意切换。

标签: python reflection


【解决方案1】:

我认为这在 Python 2.x 中是不可能的。当类成员被提供给__new__ 方法时,它们被作为字典提供,因此此时顺序已经丢失。因此,即使元类在这里也无法帮助您(除非我错过了其他功能)。

在 Python 3 中,您可以使用新的 __prepare__ 特殊方法来创建有序 dict(这甚至在 PEP 3115 中作为示例给出)。

【讨论】:

【解决方案2】:

此信息不可访问,因为属性存储在 dict 中,该 dict 本质上是无序的。 Python 不会将有关订单的这些信息存储在任何地方。

如果您希望序列化格式以特定顺序存储内容,您可以明确指定那个顺序。你不会使用dir,它包含你不知道或不关心的东西,你会明确地提供一个列表(或其他)来描述要序列化的内容。

【讨论】:

    【解决方案3】:

    我是python新手,所以我的解决方案可能无效

    class Q:
    def __init__(self):
        self.a = 5
        self.b = 10
    
    if __name__ == "__main__":
        w = Q() 
        keys = w.__dict__.keys()
        for k in keys:
            print "Q.%s = %d"%(k,w.__dict__[k])
    

    输出是:

    Q.a = 5
    Q.b = 10
    

    【讨论】:

    • 这不会保留订单。
    【解决方案4】:

    把这个方法放到你的类中

    def __setattr__(self, attr, value):
        if attr not in dir(self):
            if attr == "__ordered_fields__":
                super.__setattr__(self, attr, value)
            else:
                if not hasattr(self, "__ordered_fields__"):
                    setattr(self, "__ordered_fields__", [])
                self.__ordered_fields__.append(attr)
                super.__setattr__(self, attr, value)
    

    要按顺序排列字段,只需执行以下操作:

    print(self.__ordered_fields__)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-09
      • 2011-05-26
      • 1970-01-01
      • 2019-05-12
      • 2018-09-04
      • 2020-03-21
      • 1970-01-01
      相关资源
      最近更新 更多