我试图创建一些超类的子类,这些超类具有属性(由property
装饰器描述)和一个properties()
方法,该方法将属性及其值作为dict
返回。我希望子类能够利用继承的properties()
方法,并且需要将最少的样板代码复制并粘贴到每个子类定义中。我使用Python 3.8,如果它在这里有区别的话。
这里的重点是我想要重构的 * 样板 * 代码。
我从一个简单的类BaseClass
开始,定义如下:
class BaseClass(object):
def __init__(self, A, B):
self._A = A
self._B = B
@property
def A(self):
return self._A
@A.setter
def A(self, new_value):
# ... Validate input ...
self._A = new_value
@property
def B(self):
return self._B
@B.setter
def B(self, new_value):
# ... Validate input ...
self._B = new_value
def properties(self):
class_items = self.__class__.__dict__.items()
return dict((k, getattr(self, k)) for k, v in class_items if isinstance(v, property))
我应该注意到,我在阅读this other stackoverflow answer之后,在最后定义了properties()
方法。
如上定义的BaseClass
的示例用法:
>>> base_instance = BaseClass('foo','bar')
>>> base_instance.properties()
{'A': 'foo', 'B': 'bar'}
从那里,我想创建一些继承自BaseClass
的子类,并让properties()
方法以相同的方式工作。考虑以下情况:
class SubClass(BaseClass):
def __init__(self, A, B):
super().__init__(A, B)
但这并不像我预期的那样:
>>> sub_instance = SubClass('spam',10)
>>> sub_instance.A # works as expected
'spam'
>>> sub_instance.B # works as expected
10
>>> sub_instance.properties() # expected {'A': 'spam', 'B': 10}
{}
我知道下面的可选子类定义产生了我所期望的行为:
class SubClass(BaseClass):
def __init__(self, A, B):
super().__init__(A, B)
@BaseClass.A.getter #
def A(self): # This is all boilerplate
return self._A # that I need to copy and
# paste in every subclass
@BaseClass.B.getter # of BaseClass I define...
def B(self): #
return self._B #
>>> sub_instance = SubClass('spam',10)
>>> sub_instance.properties()
{'A': 'spam', 'B': 10}
有没有一种更简洁的方法来定义超类BaseClass
中的属性(使用property
装饰器),以便properties()
方法“正常工作”,而不需要样板代码行?
3条答案
按热度按时间8yoxcaq71#
你可以尝试使用
inspect.getmro
来获取所有的基类:图纸:
lkaoscv72#
您应该修复定义
properties
的方式,以遍历整个MRO:irtuqstp3#
为了在一定程度上减少属性的模板代码,您可以创建函数,自动实现对指定内部变量的存储和检索。
使用这个函数,你可以用一行来定义读/写属性,当你需要对赋值进行特殊处理时,你可以把它用作装饰器(后缀为
.setter
):这将在
properties()
方法中生成属性列表。dir()
而不是__class__.__dict__
,因为子类在它们的__dict__
中不会有超类的属性名称 *定义子类时,可以使用相同的方法添加更多属性:
properties()
方法现在访问子类和超类的累积属性: