gpt4 book ai didi

python - 如何在 Python 中获取基类的属性?

转载 作者:太空宇宙 更新时间:2023-11-03 15:41:10 24 4
gpt4 key购买 nike

所以我正在编写一个界面框架,允许人们编写一组命令。

我在这里试图做的是,对于 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com