Mathematica 中的可选命名参数

Posted

技术标签:

【中文标题】Mathematica 中的可选命名参数【英文标题】:Optional named arguments in Mathematica 【发布时间】:2010-12-09 14:32:51 【问题描述】:

用可选的命名参数定义函数的最佳/规范方法是什么?具体来说,让我们创建一个函数foo,其命名参数为abc,分别默认为1、2 和3。为了比较,这里有一个带有位置参数的 foo 版本:

foo[a_:1, b_:2, c_:3] := bar[a,b,c]

这是foo 的命名参数版本的示例输入和输出:

foo[]                  --> bar[1,2,3]
foo[b->7]              --> bar[1,7,3]
foo[a->6, b->7, c->8]  --> bar[6,7,8]

在命名参数之前当然也应该很容易有位置参数。

【问题讨论】:

另见:***.com/questions/4682742/… 【参考方案1】:

我在 Mathematica 文档中找到了执行此操作的标准方法:http://reference.wolfram.com/mathematica/tutorial/SettingUpFunctionsWithOptionalArguments.html

Options[foo] = a->1, b->2, c->3;  (* defaults *)
foo[OptionsPattern[]] := bar[OptionValue@a, OptionValue@b, OptionValue@c]

每次都输入“OptionValue”有点麻烦。出于某种原因,您不能只使用像 ov = OptionValue 这样的全局缩写,但您可以这样做:

foo[OptionsPattern[]] := Module[ov,
  ov[x___] := OptionValue[x];
  bar[ov@a, ov@b, ov@c]]

或者这个:

With[ov = OptionValue,
  foo[OptionsPattern[]] := bar[ov@a, ov@b, ov@c]
]

或者这个:

$PreRead = ReplaceAll[#, "ov" -> "OptionValue"] &;

foo[OptionsPattern[]] := bar[ov@a, ov@b, ov@c]

【讨论】:

关于 OptionValue 的繁琐输入:在这种情况下你可以说In[32]:= OptionValue /@ bar[a, b, c] Out[32]= bar[OptionValue[a], OptionValue[b], OptionValue[c]] @dreeves 最后一个代码块的形式更简洁,使用With 而不是Module。我可以编辑你的答案来附加这个吗? @Sjoerd 很有趣,当我加载此页面时,您的评论不存在。我猜你也在读这些旧帖子。 @Mr.Wizard Yep,由 dreeves 的一连串问题引发。 @Mr.Wizard 请做! (我认为您一般不需要问;如果原作者不喜欢编辑,则恢复很容易。)哦,不要附加,如果更好就更改它。【参考方案2】:

是的,OptionValue 可能有点棘手,因为它依赖于一种魔法,因此

OptionValue[name] 等价于OptionValue[f,name],其中f 是出现OptionValue[name] 的变换规则左侧的头部。

抛出一个明确的Automatic 通常可以解决问题,所以在你的情况下,我会说解决方案是:

Options[foo] = a -> 1, b -> 2, c -> 3;
foo[OptionsPattern[]] := 
  bar @@ (OptionValue[Automatic, #] &) /@ First /@ Options[foo] 

顺便说一句,选项过去是通过匹配opts:___?OptionQ 来完成的,然后手动查找选项值作为a,b,c/.Flatten[opts]。模式检查OptionQ 仍然存在(尽管没有记录),但OptionValue 方法的优点是您会收到不存在选项的警告(例如foo[d->3])。您的第二次回复也是如此,但您接受的回复并非如此。

【讨论】:

【参考方案3】:

我将把这个可能的解决方案混在一起:

foo[opts___Rule] := Module[f,
  f@a = 1; (* defaults... *)
  f@b = 2;
  f@c = 3;
  each[a_->v_, opts, f@a = v];

  Return[bar[f@a, f@b, f@c]]
]

我喜欢它的简洁性,但我认为这不是标准的方式。这样做有什么问题吗?

PS,它使用了以下方便的实用功能:

SetAttributes[each, HoldAll];                (* each[pattern, list, body]     *)
each[pat_, lst_, bod_] :=                    (*  converts pattern to body for *)
  Scan[Replace[#, pat:>bod]&, Evaluate@lst]  (*   each element of list.       *)

【讨论】:

以上是关于Mathematica 中的可选命名参数的主要内容,如果未能解决你的问题,请参考以下文章

使用argparse的可选命名参数

C#4.0中的更改——命名参数和可选参数

C++ 宏的可选参数

Python argparse:可以命名或定位的命令行参数

.net 可选参数和命名参数

命名参数和可选参数,以及 WCF