MEP26:艺术家造型¶
摘要¶
这个MEP提出了一个新的样式表实现,允许艺术家进行更全面和动态的样式设计。
Matplotlib(1.4.0)的当前版本允许在创建绘图之前应用基于rcParams语法的样式表。下面的方法提出了一种基于CSS的新语法,它允许对单个艺术家和属性进行样式设置,这些样式可以动态应用于现有对象。
这与(并朝着)移动到类DOM/树架构的总体目标相关。
详细描述¶
当前,现有艺术家对象(图形、轴、线2d等)的外观和外观只能通过以下方式更新: set_ 和 get_ 对艺术家对象的方法,这是非常困难的,特别是如果没有存储对艺术家的引用。1.4中引入的新样式表允许在创建绘图之前进行样式设置,但不提供任何方法来动态更新绘图或区分相同类型的艺术家(即指定 line color 和 line style 单独用于不同的 Line2D 对象)。
最初的开发应该集中在允许艺术家原语(那些 Artist 不包含其他 Artist s) ,进一步的开发可以扩展CSS语法规则和解析器以允许更复杂的样式。原语列表见附录。
新方法需要制定若干步骤:
- 一种新的样式表语法(可能基于CSS),允许按类型、类、ID等选择艺术家。
- 将样式表解析为树的机制
- 一种将解析树转换为可用于更新相关艺术家属性的内容的机制。理想情况下,这将实现一种方法,通过这种方法可以在树状结构中遍历艺术家。
- 从现有艺术家属性生成样式表的机制。这将有助于允许用户从现有图形中导出样式表(在该图形中,外观可能是使用matplotlib api设置的)。
实施¶
如果将“样式”创建为单独的类,并将其作为属性存储,则允许“第三方”修改/设置艺术家的样式最简单。这个 GraphicsContext 类已经提供了 Style 班级和艺术家的 draw 方法可以重构为使用 Style 类而不是设置它自己的类 GraphicsContext 并将其与样式相关的属性传递给它。关于如何实现这一点的一个最小示例如下:https://github.com/jamesramm/mpl_实验
IMO,这也将使API和代码库更整洁,因为艺术家风格属性的单独get/set方法现在是多余的…间接相关的是用属性替换get/set方法的通用驱动器。用属性实现样式类将是朝着这一目标迈出的一大步…
对于初始开发,我建议开发一个基于很多(非常多)简化版CSS的语法。我赞成将此艺术家样式表命名为:+1::
BNF文法¶
我提出了一个非常简单的语法来最初实现(就像一个概念证明),它可以在将来扩展。语法的bnf形式如下所示,然后解释:
RuleSet ::= SelectorSequence "{"Declaration"}"
SelectorSequence :: = Selector {"," Selector}
Declaration ::= propName":" propValue";"
Selector ::= ArtistIdent{"#"Ident}
propName ::= Ident
propValue ::= Ident | Number | Colour | "None"
ArtistIdent , Ident , Number 和 Colour 是由正则表达式定义的标记(表达式的基本构建块)。
句法¶
CSS样式表由一系列 规则集 按层次顺序(规则从上到下应用)。每个规则遵循以下语法::
selector {attribute: value;}
每个规则可以有任意数量的 attribute: value 对和样式表可以有任意数量的规则。
初始语法仅为 Artist 基元。它没有解决如何设置属性的问题 Container 类型(其属性本身可能是 Artist 但是,未来的解决方案可以简单地嵌套 RuleSet 的S
选择器¶
选择器定义应用属性更新的对象。作为一个起点,我建议在初始开发中只使用两个选择器:
艺术家类型选择器
选择一个 Artist 按它的类型。例如 Line2D 或 Text ::
Line2D {attribute: value}
用于匹配艺术家类型选择器的regex (ArtistIdent 在bnf语法中)应该是:
ArtistIdent = r'(?P<ArtistIdent>\bLine2D\b|\bText\b|\bAxesImage\b|\bFigureImage\b|\bPatch\b)'
GID选择器¶
选择一个 Artist 由其 gid ::
Line2D#myGID {attribute: value}
A gid 可以是任何字符串,因此regex可以如下所示:
Ident = r'(?P<Ident>[a-zA-Z_][a-zA-Z_0-9]*)'
上述选择器大致对应于它们的CSS对应项(http://www.w3.org/tr/css21/selector.html)
句法分析¶
解析将包括将样式表拆分为标记(Python食谱在第66页提供了一个很好的标记化方法),应用语法规则并构造一个 Tree . 我们可以借用语法来定义样式表。令人高兴的是,python食谱中也有这样的食谱。
Matplotlib人物的访客模式¶
为了将样式表规则应用于相关艺术家,我们需要在图形中“访问”每个艺术家并应用相关规则。这是一个访客类(再次感谢python食谱),在这里 node 将是一个艺术家的形象。一 visit_ 需要为每个MPL艺术家实现方法,以处理每个艺术家的不同属性:
class Visitor:
def visit(self, node):
name = 'visit_' + type(node).__name__
meth = getattr(self, name, None)
if meth is None:
raise NotImplementedError
return meth(node)
安 evaluator 然后,类将获取样式表规则,并在每个规则上实现访问者。
向后兼容性¶
实施单独的 Style 类将破坏向后兼容性,因为艺术家上的许多get/set方法将变得多余。虽然可以改变这些方法来钩住 Style 类(作为对艺术家的属性存储),我赞成简单地将它们删除,以同时整理/简化代码库,并提供简单、整洁的API…