【发布时间】:2018-09-21 04:12:15
【问题描述】:
所以我正在编写一个允许人们编写命令集合的界面框架。
我在这里尝试做的是,对于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)
现在我当前方法的问题是它没有检测到方法覆盖。假设我将这个sn-p添加到类B的定义中
def a(self): pass
a.description='B.a'
现在生成的描述将完全错误。我想要的是,当一个方法被覆盖时,它收集的描述也被覆盖。因此,描述应始终指向 Python 通常会解决的方法,如果人们以通常的方式进行处理(例如B.a.description)
因此预期的输出将变为
a: B.a
b: A.b
c: B.c
d: B.d
我想我可以用单词descriptions 制作一个特殊情况并修复第一个description 方法。
但是有没有更优雅和 Pythonic 的方式来实现这一点?老实说,self.__class__.__mro__ 看起来很可怕。
【问题讨论】:
-
您希望使用覆盖发生什么?
-
如果我猜对了,那么您应该使用“这不起作用”的版本,但检查
type(self)而不是self。但是,如果您不告诉我们您想要什么,就很难确定。 -
(或者更好,将属性放在 metaclass 并通过类而不是实例访问它。)
-
@user2357112 我想要的是,当一个方法被覆盖时,它收集的描述也被覆盖。因此,描述应该始终指向 Python 通常会解决的方法,如果人们以通常的方式(例如
B.a.description)进行处理。
标签: python oop inheritance python-3.7