2017-02-28 54 views

回答

5

你必須檢查在MRO每個類的__dict__對象(可以使用vars()功能這裏爲了使代碼更清潔):

def class_for_attribute(instance, attribute_name): 
    for cls in type(instance).mro(): 
     if attribute_name in vars(cls): 
      return cls 

演示:

>>> class_for_attribute(k, 'a') 
<class '__main__.Klass_1'> 
>>> class_for_attribute(k, 'b') 
<class '__main__.Klass_2'> 
1

您可以在__dict__中搜索類對象或其超類的屬性。這是一個普通的功能:

In [23]: def find_origin(instance, arg): 
      if arg in type(instance).__dict__: 
       return 'class' 
      elif any(arg in c.__dict__ for c in type(instance).__bases__): 
       return 'super class' 
      return "doesn't exist" 
    ....: 

In [24]: 

In [24]: find_origin(k, 'a') 
Out[24]: 'super class' 

In [25]: 

In [25]: find_origin(k, 'b') 
Out[25]: 'class' 

In [26]: find_origin(k, 'd') 
Out[26]: "doesn't exist" 

由於@Martijn皮特斯爲了在您需要使用類obejct代替__bases__mro屬性超類的更深層次的搜索提及。作爲一個更Python的方式,你可以next()函數中使用生成器表達式:

In [38]: def find_origin(instance, arg): 
      return next((c for c in type(instance).mro() if arg in c.__dict__), "doesn't exist") 
    ....: 

In [39]: find_origin(k, 'a') 
Out[39]: __main__.Klass_1 

In [40]: find_origin(k, 'b') 
Out[40]: __main__.Klass_2 

In [41]: find_origin(k, 'c') 
Out[41]: "doesn't exist" 
+0

這僅涵蓋直接基類,如果層次是什麼更深? –

+0

@MartijnPieters是的,在這種情況下,我們可以使用'mro'。但是這個答案仍然沒有錯,因此它不值得投票決定。) – Kasramvd

+0

好吧,如果這是'class A(object):a_attr = 1',class B(A): b_attr = 2'和'class C(B):c_attr = 3',並且你在'C'的一個實例中要求'a_attr'。你的代碼說在這種情況下屬性不存在。 –

相關問題