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…