如何找到函数所有 **args 的列表?

4

如何找到函数的所有**args列表?

例如,我知道symbols()接受positive=Truereal=True等参数,并且我想查看可能的参数的完整列表。然而,在Sympy Core的文档页面中没有列出它们。

我已经深入研究了源代码,但无法找到我要查找的内容。


想知道这里的答案是否对您有帮助,或者您是否需要更多特定方面的细节? - J Richard Snape
是的先生。听起来假设模块是需要查看的地方。我特别感谢代码演示!非常有教育意义。虽然我只是旁观者,但我认为将其记录在文档页面中会很好。 - saintsfan342000
很好 - 很高兴它有帮助。如果你觉得一个答案解决了问题,请接受它。我同意文档可以更明确地说明“这是您可以传递的所有可能参数的完整列表”。 - J Richard Snape
4个回答

4

symbols()函数

正如其他答案所指出的,在symbols中使用**args的一个用途是传递关于创建的Symbol的假设。您可以传递的假设列表在假设页面下记录为支持的谓词

但是,您还应该注意,一些其他特殊命名的参数也可以被传递。

这些都在您链接的部分中有记录,它们是:

  1. cls=<ClassName>

    尽管它的名称是symbols(),但它可以创建类似于Function或Wild类的符号对象。为了实现这一点,将cls关键字参数设置为所需类型:

    N.B. 如果未指定,则使用默认的Symbol类。

  2. seq=<True|False>

    文档中说:

    如果需要一个可迭代的容器来表示单个符号,请将seq参数设置为True或在符号名称后面加上逗号

代码漫步

你注意到了代码 - 那么我将向你展示这些在代码中是如何实现的。如果你调用symbols()函数,它会对其参数进行各种检查,包括从**args弹出clsseq参数,然后执行更多的检查等等,最后调用Symbol这里, 这里这里来实例化。这些调用Symbol(或通过cls传递的子类)的构造函数,使用**args中剩余的内容作为构造函数中的假设进行解释。它们在这里被清理,即在这一点上,非假设或不适用的命名参数被丢弃
这表明假设 + cls + seq 组成了一组可作为命名参数传递给 symbols() 中的 **args 的参数集合。

其他函数(一般情况)

我想到symbols()可能只是更一般问题的代表性例子。我希望上面的内容已经让您相信,可以有用地传递给symbols()的所有值都已记录在文档中。这可能使您对SymPy中的其他函数也是如此有信心。

然而,在一般情况下,答案是很难证明所有可以作为关键字参数传递的值都在任何库或函数的文档中。实际上,有时只有其中的一个子集被故意记录下来,因为它们是库的“公共API”,而实际代码可能需要其他参数,但由于某种原因,开发人员不想将它们暴露给公众——例如,因为它们的可用性可能会改变,或者它们的功能未经测试。

如果您传递无效的参数,则您使用的库的行为可能会有所不同。有些库或函数将忽略它们,而其他库或函数则会在您传递无效的关键字参数时引发错误。

如果您想确定是否是这种情况(并且该库像SymPy一样是开源的),那么您可以随时深入代码(如上面的代码漫步所示)。如果您这样做-您需要跟随执行路径,寻找args.pop()出现的情况。如果您担心SymPy中的其他函数,请在评论中告诉我-但希望这种通用方法适用于您。
我假设您已经了解上述*args**args语法。如果您还不太清楚-Python官方教程的这一部分会涉及到它。

@Dietrich,作为您设置悬赏的人,我想知道您是否更关心特定的symbols()函数,或者是否有其他我可以帮助您的事情? - J Richard Snape
非常感谢您提供的全面答案。假设页面的链接真的很有帮助。作为一个偶尔使用Sympy的用户(试图减少对Mathematica的依赖),我经常会遇到记不住这些参数的问题,特别是因为它们没有被验证过有效性:例如,symbols('x', pos=True)不会引发错误(这不是在自己的代码中发现的好bug)。 - Dietrich
感谢您的评论和悬赏。我同意 - 这些错误非常可怕。我不太喜欢 SymPy 忽略不支持的名称,只是通过 弹出它们并在此处忽略 的方式。这不是一个 bug,但它确实使您提供的示例非常难以调试。 - J Richard Snape

3
这些论点被称为假设,并可以在文档中找到:Sympy 假设

3

假设分类

  • 与简化符号有关,例如Q.positiveQ.even
  • 与代数领域/环有关,例如Q.realQ.complex
  • 与一些事实有关,例如is_boundedis_infinityis_zero等等。它们帮助我们在核心计算中进行操作。 显然,它们是从上述其他类别的假设中派生出来的(在对象启动时)(在这种情况下,例如is_zero意味着它是环的零)。或者它们可以从表达式的分析中推导出来:在这种情况下,我们可以创建一些被计算的假设类别(在这种情况下,is_zero可能意味着这种计算方式很困难,所谓的“零测试”问题)。无论如何,我们都能清楚地认识到我们正在处理什么(现在在核心中我们在第二个意义上使用了is_zero)。

假设示例:

M ... Mathematica
S0 ... SymPy, current approach
S1 .... SymPy, approach 1
S2 .... SymPy, approach 2

M: Simplify[1/Sqrt[x] - Sqrt[1/x], x > 0]
S1: x = Symbol('x', assumptions=IsPositive)
  simplify(1/sqrt(x) - sqrt(1/x))
S2: simplify(1/sqrt(x) - sqrt(1/x), Assumptions(x>0))

M: FunctionExpand[Log[x y], x > 0 && y > 0]
S1: x, y = Symbol('x', assumptions=IsPositive), Symbol('y', assumptions=IsPositive)
 log(x*y).expand()
S2: log(x*y).expand(Assumptions([x>0, y>0]))

M: Simplify[Sin[n Pi], n \[Element] Integers]
S1: n = Symbol('n', assumptions=IsInteger)
  simplify(sin(n*pi))
S2: simplify(sin(n*pi), Assumptions(Element(n, Integer)))

# we can talk about the syntax of Element(n, Integer)

M: FunctionExpand[EulerPhi[m n], {m, n} \[Element] Integers && GCD[m, n] == 1]
S1: n = Symbol('n', assumptions=IsInteger)
  m = Symbol('m', assumptions=IsInteger)
  n.assumptions.add(Eq(gcd(m, n) - 1))
  euler_phi(m, n)
S2: euler_phi(m, n).expand(Assumptions([Element(n, Integer), Element(m, Integer), Eq(gcd(m, n) - 1)]))

# again we can talk about the syntax of Element(n, Integer)

M: RealQ[x, x \[Element] Real]
S0: x = Symbol('x',real=True, integer=True)
  assert x.is_real == True
S1:
S2: assert IsElement(x, Real, assumptions=Element(x, Real))

M: Refine[Abs[x], x>0]
   Refine[Abs[x], x0))
  print e.refine(Assumptions(x))

更多参考资料:
- Sympi Assumptions Wiki - Assuming - 在Sympy中相对于其他变量设置变量假设 - 使用SymPy的新假设

1
你可以使用名为inspect的内置Python库从任何函数中获取参数详情:
import inspect
inspect.getargspec(funcname)

它将返回一个名为ArgSpec的命名元组,其中包含一些信息,例如:
ArgSpec(args=['myarg'], varargs=None, keywords=None, defaults=(None,))

要获取参数名称,您只需访问返回对象的args属性。

1
虽然这对于命名参数有效,但在此处不适用,因为OP正在寻找在传递到**args dict中时有效的关键字参数列表。您可以通过导入sympy并执行inspect.getargspec(sympy.symbols)来进行测试。你会得到ArgSpec(args = ['names'],varargs = None,keywords ='args',defaults = None),而不是可以传递给args的所有值的列表。 - J Richard Snape

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接