【发布时间】:2019-02-25 01:27:10
【问题描述】:
在attrs 中,生成的init 方法的参数顺序由类中的属性定义顺序+ MRO 确定(一种基于多重继承关系定义总顺序的标准方法)。这对我的用例不利,但似乎没有任何灵活性。这是用例:
我正在使用attrs 来定义一些建模图形基元的类。这些原语是相关的,因为它们都需要数据来处理并生成具有给定高度和宽度的图形,这些图形具有默认值。所以在顶层有一个类
@attr.s
class BaseGraphics:
data = attr.ib()
height = attr.ib(default=300)
width = attr.ib(default=400)
由此派生出三个类,UnivariateGraphics、BivariateGraphics 和 MultivariateGraphics,它们分别在 data 中使用一、两或更多列。让我展示一个:
@attr.s
class BivariateGraphics(BaseGraphics):
x = attr.ib()
y = attr.ib()
单变量案例只有x,多变量案例只有一个columns 属性。这失败了,因为在 MRO 中 x 和 y 在 height 和 width 之后,但 x 和 y 是强制性的,而 height 和 width 不是强制性的。确切的错误是
ValueError: No mandatory attributes allowed after an attribute with
a default value or factory. Attribute in question:
Attribute(name='x', default=NOTHING, validator=None, repr=True,
cmp=True, hash=None, init=True, metadata=mappingproxy({}), type=None,
converter=None, kw_only=False)
我可以为x 和y 设置默认值,就像第一列和第二列一样,但顺序仍然是错误的。例如,如果想写类似的东西
BivariateGraphics(iris_data, "petalWidth", "sepalWidth")
第二个和第三个参数将被解释为height 和width,而不是x 和y。我可以通过将所有属性设置为仅data 关键字来防止此错误,但我不支持此语法。通过阅读几个相关问题,例如#38,看来这是推荐的方法。关闭但没有雪茄。
另一种解决方法是将height 和width 分别添加到每个派生类。这将违反 DRY 原则,并且无法表达和执行类之间的这种共性。有超过三个类,它会变得非常讨厌。
这不仅仅是一个“学术”问题。我在包autosig 中使用attrs,以帮助以一致的方式定义API。这又在统计图形包altair_recipes 中使用,实际发生上述情况的地方(嗯,在下一个版本中,当我需要将height 和width 添加到所有图形基元时)。
我可以向开发人员提出问题,但由于主要开发人员开玩笑地 (?) 威胁使用电击子类的人,我觉得这将是徒劳的。我会对不需要 DRY 违规或样板的非继承解决方案感兴趣。谢谢
【问题讨论】:
标签: python-attrs