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
属性。这失败了,因为在 MROx
和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
and width
,而不是x
and y
。我可以通过只设置关键字以外的所有属性来防止这个错误data
,但我不支持这种语法。从阅读几个相关问题,例如#38,看来这是推荐的方法。关闭但没有雪茄。
另一种解决方法是独立地向每个派生类添加height
和。width
这将违反 DRY 原则,并且无法表达和执行类之间的这种共性。有超过三个类,它会变得非常讨厌。
这不仅仅是一个“学术”问题。我attrs
在包中使用autosig
, 来帮助以一致的方式定义 API。这又在统计图形包中使用,altair_recipes
实际发生上述情况的地方(嗯,在下一个版本中,当我需要添加height
和width
到所有图形基元时)。
我可以向开发人员提出问题,但由于主要开发人员开玩笑地(?)威胁那些使用电击子类的人,我觉得这将是徒劳的。我会对不需要 DRY 违规或样板的非继承解决方案感兴趣。谢谢