在以下代碼:如何確定某個屬性是位於原始類還是繼承類?
class Klass_1:
a = 1
class Klass_2(Klass_1):
b = 2
k = Klass_2()
,能夠訪問兩個k.a
和k.b
,和hasattr(k, ...)
是True
兩個「一」和「b」。
如何確定屬性是否位於原始類別Klass_2
或繼承類別Klass_1
?
在以下代碼:如何確定某個屬性是位於原始類還是繼承類?
class Klass_1:
a = 1
class Klass_2(Klass_1):
b = 2
k = Klass_2()
,能夠訪問兩個k.a
和k.b
,和hasattr(k, ...)
是True
兩個「一」和「b」。
如何確定屬性是否位於原始類別Klass_2
或繼承類別Klass_1
?
你必須檢查在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'>
您可以在__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"
這僅涵蓋直接基類,如果層次是什麼更深? –
@MartijnPieters是的,在這種情況下,我們可以使用'mro'。但是這個答案仍然沒有錯,因此它不值得投票決定。) – Kasramvd
好吧,如果這是'class A(object):a_attr = 1',class B(A): b_attr = 2'和'class C(B):c_attr = 3',並且你在'C'的一個實例中要求'a_attr'。你的代碼說在這種情況下屬性不存在。 –