2011-03-09 80 views
1

檢查類屬性定義或在給定的類派生

class A: 
    foo = 1 

class B: 
    foo = 2 

class C: 
    foo = 3 

class D(A, B, C): 
    pass 

def collect_foo(cls): 
    import inspect 
    foos = [] 
    for c in inspect.getmro(cls): 
     if hasattr(c, 'foo'): 
      foos.append(c.foo) 
    return foos 

現在collect_foo(D)返回[1, 1, 2, 3] - 1加倍作爲DA導出它。問題是 - 如何獲得獨特的foo s。我想到的第一件事就是檢查財產是否在給定的類別中派生或宣佈 - 是否有可能?怎麼做?

+0

這是一件討厭的事情。你爲什麼這樣做? – katrielalex

+0

另外,'set(collect_foo(D))'做你想要的嗎? – katrielalex

+0

我需要編寫大約一百個類,其中許多類將具有諸如「Class1(Feature1,Feature2)」或「Class2(Feature2,Feature1337)」等特徵的特定組合。事情是有一些屬性,我不想被覆蓋,但混入並可用於派生類 - 所以'Feature'類之一提供了從繼承層次結構收集它們的方法。這並不是什麼壞事 - 如果某些東西是獨立於實現的,與版本無關的(甚至是2.x/3.x),並且有很好的文檔記錄,我不會稱之爲討厭的黑客攻擊。 – Mikoskay

回答

4

我相信這會起作用......看看它是否屬於該類的__dict__屬性。但是,確保你真的想要這樣做。

例子:

if name in cls.__dict__: 
    # ... your code here ... 
    pass 
+0

不完全,但非常接近斯文的答案,這是我一直在尋找的答案。 – Mikoskay

+1

@Mikoskay:我其實並沒有看到我的答案有任何顯着差異。 –

7

只是檢查的

'foo' in c.__dict__ 

代替

hasattr(c, 'foo') 

這隻會產生True如果屬性在c定義本身。

+0

完美,謝謝。 – Mikoskay

+1

請注意,如果該類有__slots__,則會失敗,因此請同時選中。 –

1

「的事情是有,我不想被重寫,但在混合,可派生類的一些屬性」

這正是命名空間的mangling在Python中。不應該像這樣重寫的屬性應該以兩個下劃線開頭。這樣他們不會被重寫,但對於每個班級都是獨一無二的。

0

我同意接受的答案,但@classmethod不匹配我的情況......

我認爲應該從基類的情況下檢查類字典或混合型,其中如果它適用於派生類,我只想執行一些代碼路徑,例如,如果特定的方法被覆蓋。

即(在Python 3.6):
if method_name in self.__class__.__dict__.keys(): # do something

我合理化它如下。

  1. self是實例
  2. __class__是該實例的實際類型
  3. 因此,字典只包含在派生類中重寫實際的方法。