- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
所以我正在编写一个界面框架,允许人们编写一组命令。
我在这里试图做的是,对于 Base
的每个子类,找到它的所有具有描述的方法,然后收集所有这些函数并从中生成一个集体描述(加上其他东西,但它与这个问题无关)
这是MCVE
import types
class Meta(type):
def __init__(cls, *args, **kwargs):
cls._interfaces = {}
super().__init__(*args, **kwargs)
def __call__(cls, id, *args, **kwargs):
if id in cls._interfaces:
return cls._interfaces[id]
obj = cls.__new__(cls, *args, **kwargs)
obj.__init__(*args, **kwargs)
cls._interfaces[id] = obj
return obj
class Base(metaclass=Meta):
@property
def descriptions(self): # this doesn't work. It gives RecursionError
res=''
for name in dir(self):
attr=getattr(self,name)
if isinstance(attr, types.FunctionType) and hasattr(attr, 'description'):
res += f'{name}: {attr.description}\n'
return res
@property
def descriptions(self):
res=''
for cls in self.__class__.__mro__:
for name,attr in cls.__dict__.items():
if isinstance(attr, types.FunctionType) and hasattr(attr, 'description'):
res += f'{name}: {attr.description}\n'
return res
class A(Base):
def a(self): pass
a.description='A.a'
def b(self): pass
b.description='A.b'
class B(A):
def c(self): pass
c.description='B.c'
def d(self): pass
d.description='B.d'
print(B(0).descriptions)
现在我当前方法的问题是它不检测方法覆盖。假设我将这段代码添加到类 B
def a(self): pass
a.description='B.a'
现在生成的描述将完全错误。我想要的是当一个方法被覆盖时,它收集的描述也被覆盖。因此,如果人们使用通常的方式(例如 B.a.description
),那么描述应该始终指向 Python 通常会解析到的方法
所以预期的输出会变成
a: B.a
b: A.b
c: B.c
d: B.d
我想我可以用单词 descriptions
做一个特例并修复第一个 description
方法。
但是有没有更优雅和 Pythonic 的方式来实现它呢?老实说,self.__class__.__mro__
看起来很糟糕。
最佳答案
当您遍历 self.__class__.__mro__
时,您正在迭代解析顺序,这将是 <class '__main__.B'> <class '__main__.A'> <class '__main__.Base'> <class 'object'>
在你的例子中。
因此,您正在查看 description
随后这些类中的每一个的属性。当你声明 a.description = 'B.a'
内部类B
, 你实际上并没有在父类中覆盖它 A
,你只是在子类中覆盖它 B
.
因此,您可以这样做:
import inspect
class Base(metaclass=Meta):
def descriptions(self):
res = ''
for mtd in inspect.getmembers(self, predicate=inspect.ismethod):
if hasattr(mtd[1], 'description'):
res += f'{mtd[0]}: {mtd[1].description}\n'
return res
这样,您仅检查实际的 child 而不是其 parent 。然而,Base.descriptions
在这种情况下不能是一个属性,因为属性在声明时得到评估,这将使 inspect.getmembers
无限长地检查自己。
关于python - 如何在 Python 中获取基类的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52436502/
我是一名优秀的程序员,十分优秀!