問題描述
假設我們有以下類層次結構:
Suppose we have the following class hierarchy:
class ClassA:
@property
def foo(self): return "hello"
class ClassB(ClassA):
@property
def bar(self): return "world"
如果我像這樣在 ClassB 上探索 __dict__,我只會看到 bar 屬性:
If I explore __dict__ on ClassB like so, I only see the bar attribute:
for name,_ in ClassB.__dict__.items():
if name.startswith("__"):
continue
print(name)
輸出是條形
我可以使用自己的方法來獲取指定類型及其祖先的屬性.但是,我的問題是,python 中是否已經有一種方法可以讓我在不重新發明輪子的情況下做到這一點.
I can roll my own means to get attributes on not only the specified type but its ancestors. However, my question is whether there's already a way in python for me to do this without re-inventing a wheel.
def return_attributes_including_inherited(type):
results = []
return_attributes_including_inherited_helper(type,results)
return results
def return_attributes_including_inherited_helper(type,attributes):
for name,attribute_as_object in type.__dict__.items():
if name.startswith("__"):
continue
attributes.append(name)
for base_type in type.__bases__:
return_attributes_including_inherited_helper(base_type,attributes)
如下運行我的代碼...
Running my code as follows...
for attribute_name in return_attributes_including_inherited(ClassB):
print(attribute_name)
...返回 bar 和 foo.
... gives back both bar and foo.
請注意,我正在簡化一些事情:名稱沖突、在本示例中我可以使用 dict 時使用 items()、跳過以 __ 開頭的任何內容、忽略兩個祖先本身具有共同祖先的可能性等.
Note that I'm simplifying some things: name collisions, using items() when for this example I could use dict, skipping over anything that starts with __, ignoring the possibility that two ancestors themselves have a common ancestor, etc.
EDIT1 - 我試圖使示例保持簡單.但我真的想要每個類和祖先類的屬性名稱和屬性引用.下面的答案之一讓我走上了更好的軌道,當我讓它工作時,我會發布一些更好的代碼.
EDIT1 - I tried to keep the example simple. But I really want both the attribute name and the attribute reference for each class and ancestor class. One of the answers below has me on a better track, I'll post some better code when I get it to work.
EDIT2 - 這是我想要的并且非常簡潔.它基于 Eli 在下面的回答.
EDIT2 - This does what I want and is very succinct. It's based on Eli's answer below.
def get_attributes(type):
attributes = set(type.__dict__.items())
for type in type.__mro__:
attributes.update(type.__dict__.items())
return attributes
它返回屬性名稱和它們的引用.
It gives back both the attribute names and their references.
EDIT3 - 以下答案之一建議使用inspect.getmembers.這看起來非常有用,因為它就像 dict 一樣,只是它也對祖先類進行操作.
EDIT3 - One of the answers below suggested using inspect.getmembers. This appears very useful because it's like dict only it operates on ancestor classes as well.
由于我試圖做的大部分工作是查找標有特定描述符的屬性,并包括祖先類,因此這里有一些代碼可以幫助做到這一點,以防對任何人有所幫助:
Since a large part of what I was trying to do was find attributes marked with a particular descriptor, and include ancestors classes, here is some code that would help do that in case it helps anyone:
class MyCustomDescriptor:
# This is greatly oversimplified
def __init__(self,foo,bar):
self._foo = foo
self._bar = bar
pass
def __call__(self,decorated_function):
return self
def __get__(self,instance,type):
if not instance:
return self
return 10
class ClassA:
@property
def foo(self): return "hello"
@MyCustomDescriptor(foo="a",bar="b")
def bar(self): pass
@MyCustomDescriptor(foo="c",bar="d")
def baz(self): pass
class ClassB(ClassA):
@property
def something_we_dont_care_about(self): return "world"
@MyCustomDescriptor(foo="e",bar="f")
def blah(self): pass
# This will get attributes on the specified type (class) that are of matching_attribute_type. It just returns the attributes themselves, not their names.
def get_attributes_of_matching_type(type,matching_attribute_type):
return_value = []
for member in inspect.getmembers(type):
member_name = member[0]
member_instance = member[1]
if isinstance(member_instance,matching_attribute_type):
return_value.append(member_instance)
return return_value
# This will return a dictionary of name & instance of attributes on type that are of matching_attribute_type (useful when you're looking for attributes marked with a particular descriptor)
def get_attribute_name_and_instance_of_matching_type(type,matching_attribute_type):
return_value = {}
for member in inspect.getmembers(ClassB):
member_name = member[0]
member_instance = member[1]
if isinstance(member_instance,matching_attribute_type):
return_value[member_name] = member_instance
return return_value
推薦答案
您應該使用 python 的 inspect
模塊來實現任何此類內省功能.
You should use python's inspect
module for any such introspective capabilities.
.
.
>>> class ClassC(ClassB):
... def baz(self):
... return "hiya"
...
>>> import inspect
>>> for attr in inspect.getmembers(ClassC):
... print attr
...
('__doc__', None)
('__module__', '__main__')
('bar', <property object at 0x10046bf70>)
('baz', <unbound method ClassC.baz>)
('foo', <property object at 0x10046bf18>)
在這里閱讀更多關于inspect
模塊的信息.
Read more about the inspect
module here.
這篇關于有沒有辦法訪問包含基類的 __dict__ (或類似的東西)?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!