2010-02-17 26 views
9

Python帶有方便的dir()函數,可以爲你列出一個類的內容。舉例來說,對於這個類:如何迭代類的屬性,按照它們的定義順序?

class C: 
    i = 1 
    a = 'b' 

dir(C)將返回

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

這是偉大的,但要注意的'a''i'順序如何,現在不同,那麼它們所定義的順序

如何按照定義的順序遍歷C的屬性(可能忽略內置文檔&模塊屬性)?對於上面的C類,將是'i',然後是'a'

附錄: - 我正在編寫一些序列化/日誌記錄代碼,我希望按照定義的順序對屬性進行序列化,以便輸出與創建該類的代碼類似。

+0

爲什麼他們定義的順序很重要?在這種情況下,訂單無關緊要。如果你能得到它,你會如何使用這些信息? – 2010-02-17 13:38:11

+0

你在序列化類的一個或多個實例嗎?在你的例子中,'a'和'i'是類屬性。如果你的意思是這些是實例屬性,你應該在'__init__'中使用'self.a ='b''和'self.i = 1'來定義它們。 – PaulMcG 2010-02-17 14:06:38

+0

這些是類級別的屬性,它們不如實例變量有用。你爲什麼試圖保持類屬性的順序?保持實例變量的順序不是更好嗎?你爲什麼要用類級別的變量做技巧? – 2010-02-17 15:14:30

回答

7

我不認爲這在Python 2.x中是可行的。當類成員被提供給__new__方法時,它們被作爲字典給出,所以訂單已經在那個時候丟失了。因此,即使是元類也無法幫到你(除非我錯過了其他功能)。

在Python 3中,您可以使用新的__prepare__特殊方法創建一個有序的字典(這甚至在PEP 3115中作爲示例給出)。

+0

下面是Django如何執行它(Python 2.x及更高版本): https://github.com/django/django/blob/stable/1.3.x/django/db/models/fields/__init__.py#L56 – tobych 2013-01-11 01:25:50

+0

我還沒有使用Django,但我想這需要在每個任務中創建一個新的'Field'實例?聽起來是一個很好的解決方案。 – nikow 2013-01-13 11:02:46

+0

是的,這就是Django所做的。 – tobych 2013-01-15 00:23:48

1

此信息不可訪問,因爲屬性存儲在字典中,這本質上是無序的。 Python不會在任何地方存儲有關訂單的信息。

如果你想要你的序列化格式以某種順序存儲的東西,你會指定明確訂購。你不會使用dir,它包含你不知道或關心的事情,你會明確地提供一個列表(或其他)來描述序列化的內容。

2

我在蟒蛇新的,所以我的解決方案可能是無效

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 
+0

這不保留訂單。 – 2011-11-24 12:39:42

2

把這種方法在你的類

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__) 
相關問題